blob: 44a06e7f8be5e4d3d3d273a79a9b13a7fc09e6cc [file] [log] [blame]
license.botbf09a502008-08-24 00:55:551// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
2// 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]bacff652009-03-31 17:50:3310#include "net/base/ssl_info.h"
initial.commit586acc5fe2008-07-26 22:42:5211#include "net/base/test_completion_callback.h"
12#include "net/base/upload_data.h"
[email protected]385a4672009-03-11 22:21:2913#include "net/http/http_auth_handler_ntlm.h"
initial.commit586acc5fe2008-07-26 22:42:5214#include "net/http/http_network_session.h"
15#include "net/http/http_network_transaction.h"
16#include "net/http/http_transaction_unittest.h"
[email protected]51fff29d2008-12-19 22:17:5317#include "net/proxy/proxy_config_service_fixed.h"
[email protected]f7984fc62009-06-22 23:26:4418#include "net/socket/client_socket_factory.h"
19#include "net/socket/socket_test_util.h"
20#include "net/socket/ssl_client_socket.h"
initial.commit586acc5fe2008-07-26 22:42:5221#include "testing/gtest/include/gtest/gtest.h"
[email protected]23887f04f2008-12-02 19:20:1522#include "testing/platform_test.h"
initial.commit586acc5fe2008-07-26 22:42:5223
24//-----------------------------------------------------------------------------
25
[email protected]89ceba9a2009-03-21 03:46:0626namespace net {
27
[email protected]db8f44c2008-12-13 04:52:0128// Create a proxy service which fails on all requests (falls back to direct).
[email protected]1c773ea12009-04-28 19:58:4229ProxyService* CreateNullProxyService() {
30 return ProxyService::CreateNull();
initial.commit586acc5fe2008-07-26 22:42:5231}
32
[email protected]e44de5d2009-06-05 20:12:4533// Helper to manage the lifetimes of the dependencies for a
34// HttpNetworkTransaction.
[email protected]228ff742009-06-05 01:19:5935class SessionDependencies {
36 public:
37 // Default set of dependencies -- "null" proxy service.
[email protected]b59ff372009-07-15 22:04:3238 SessionDependencies() : host_resolver(new MockHostResolver),
[email protected]94a0d3d92009-06-27 01:50:1439 proxy_service(CreateNullProxyService()) {}
[email protected]228ff742009-06-05 01:19:5940
41 // Custom proxy service dependency.
[email protected]e44de5d2009-06-05 20:12:4542 explicit SessionDependencies(ProxyService* proxy_service)
[email protected]b59ff372009-07-15 22:04:3243 : host_resolver(new MockHostResolver), proxy_service(proxy_service) {}
[email protected]228ff742009-06-05 01:19:5944
[email protected]a2c2fb92009-07-18 07:31:0445 scoped_refptr<MockHostResolverBase> host_resolver;
[email protected]228ff742009-06-05 01:19:5946 scoped_ptr<ProxyService> proxy_service;
47 MockClientSocketFactory socket_factory;
48};
49
[email protected]1c773ea12009-04-28 19:58:4250ProxyService* CreateFixedProxyService(const std::string& proxy) {
[email protected]ab501a6a2009-05-12 15:07:5051 net::ProxyConfig proxy_config;
52 proxy_config.proxy_rules.ParseFromString(proxy);
[email protected]3e44697f2009-05-22 14:37:3953 return ProxyService::CreateFixed(proxy_config);
[email protected]51fff29d2008-12-19 22:17:5354}
55
56
[email protected]228ff742009-06-05 01:19:5957HttpNetworkSession* CreateSession(SessionDependencies* session_deps) {
[email protected]94a0d3d92009-06-27 01:50:1458 return new HttpNetworkSession(session_deps->host_resolver,
[email protected]8a00f00a2009-06-12 00:49:3859 session_deps->proxy_service.get(),
[email protected]228ff742009-06-05 01:19:5960 &session_deps->socket_factory);
[email protected]e8d536192008-10-17 22:21:1461}
62
[email protected]89836e22008-09-25 20:33:4263class HttpNetworkTransactionTest : public PlatformTest {
initial.commit586acc5fe2008-07-26 22:42:5264 public:
[email protected]0e75a732008-10-16 20:36:0965 virtual void TearDown() {
66 // Empty the current queue.
67 MessageLoop::current()->RunAllPending();
68 PlatformTest::TearDown();
69 }
70
[email protected]3d2a59b2008-09-26 19:44:2571 protected:
72 void KeepAliveConnectionResendRequestTest(const MockRead& read_failure);
initial.commit586acc5fe2008-07-26 22:42:5273
[email protected]ff007e162009-05-23 09:13:1574 struct SimpleGetHelperResult {
75 int rv;
76 std::string status_line;
77 std::string response_data;
78 };
initial.commit586acc5fe2008-07-26 22:42:5279
[email protected]ff007e162009-05-23 09:13:1580 SimpleGetHelperResult SimpleGetHelper(MockRead data_reads[]) {
81 SimpleGetHelperResult out;
initial.commit586acc5fe2008-07-26 22:42:5282
[email protected]228ff742009-06-05 01:19:5983 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:4084 scoped_ptr<HttpTransaction> trans(
85 new HttpNetworkTransaction(
[email protected]228ff742009-06-05 01:19:5986 CreateSession(&session_deps),
87 &session_deps.socket_factory));
initial.commit586acc5fe2008-07-26 22:42:5288
[email protected]ff007e162009-05-23 09:13:1589 HttpRequestInfo request;
90 request.method = "GET";
91 request.url = GURL("http://www.google.com/");
92 request.load_flags = 0;
initial.commit586acc5fe2008-07-26 22:42:5293
[email protected]69b43fe2009-06-15 09:47:3794 StaticMockSocket data(data_reads, NULL);
[email protected]228ff742009-06-05 01:19:5995 session_deps.socket_factory.AddMockSocket(&data);
initial.commit586acc5fe2008-07-26 22:42:5296
[email protected]ff007e162009-05-23 09:13:1597 TestCompletionCallback callback;
initial.commit586acc5fe2008-07-26 22:42:5298
[email protected]ff007e162009-05-23 09:13:1599 int rv = trans->Start(&request, &callback);
100 EXPECT_EQ(ERR_IO_PENDING, rv);
initial.commit586acc5fe2008-07-26 22:42:52101
[email protected]ff007e162009-05-23 09:13:15102 out.rv = callback.WaitForResult();
103 if (out.rv != OK)
104 return out;
105
106 const HttpResponseInfo* response = trans->GetResponseInfo();
107 EXPECT_TRUE(response != NULL);
108
109 EXPECT_TRUE(response->headers != NULL);
110 out.status_line = response->headers->GetStatusLine();
111
112 rv = ReadTransaction(trans.get(), &out.response_data);
113 EXPECT_EQ(OK, rv);
114
[email protected]aecfbf22008-10-16 02:02:47115 return out;
[email protected]ff007e162009-05-23 09:13:15116 }
initial.commit586acc5fe2008-07-26 22:42:52117
[email protected]ff007e162009-05-23 09:13:15118 void ConnectStatusHelperWithExpectedStatus(const MockRead& status,
119 int expected_status);
initial.commit586acc5fe2008-07-26 22:42:52120
[email protected]ff007e162009-05-23 09:13:15121 void ConnectStatusHelper(const MockRead& status);
[email protected]ff007e162009-05-23 09:13:15122};
[email protected]231d5a32008-09-13 00:45:27123
[email protected]15a5ccf82008-10-23 19:57:43124// Fill |str| with a long header list that consumes >= |size| bytes.
125void FillLargeHeadersString(std::string* str, int size) {
[email protected]4ddaf2502008-10-23 18:26:19126 const char* row =
127 "SomeHeaderName: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\r\n";
128 const int sizeof_row = strlen(row);
129 const int num_rows = static_cast<int>(
130 ceil(static_cast<float>(size) / sizeof_row));
131 const int sizeof_data = num_rows * sizeof_row;
132 DCHECK(sizeof_data >= size);
[email protected]15a5ccf82008-10-23 19:57:43133 str->reserve(sizeof_data);
[email protected]372d34a2008-11-05 21:30:51134
[email protected]4ddaf2502008-10-23 18:26:19135 for (int i = 0; i < num_rows; ++i)
[email protected]15a5ccf82008-10-23 19:57:43136 str->append(row, sizeof_row);
[email protected]4ddaf2502008-10-23 18:26:19137}
138
[email protected]385a4672009-03-11 22:21:29139// Alternative functions that eliminate randomness and dependency on the local
140// host name so that the generated NTLM messages are reproducible.
[email protected]fe2bc6a2009-03-23 16:52:20141void MockGenerateRandom1(uint8* output, size_t n) {
[email protected]385a4672009-03-11 22:21:29142 static const uint8 bytes[] = {
143 0x55, 0x29, 0x66, 0x26, 0x6b, 0x9c, 0x73, 0x54
144 };
145 static size_t current_byte = 0;
146 for (size_t i = 0; i < n; ++i) {
147 output[i] = bytes[current_byte++];
148 current_byte %= arraysize(bytes);
149 }
150}
151
[email protected]fe2bc6a2009-03-23 16:52:20152void MockGenerateRandom2(uint8* output, size_t n) {
[email protected]385a4672009-03-11 22:21:29153 static const uint8 bytes[] = {
154 0x96, 0x79, 0x85, 0xe7, 0x49, 0x93, 0x70, 0xa1,
155 0x4e, 0xe7, 0x87, 0x45, 0x31, 0x5b, 0xd3, 0x1f
156 };
157 static size_t current_byte = 0;
158 for (size_t i = 0; i < n; ++i) {
159 output[i] = bytes[current_byte++];
160 current_byte %= arraysize(bytes);
161 }
162}
163
[email protected]fe2bc6a2009-03-23 16:52:20164std::string MockGetHostName() {
165 return "WTC-WIN7";
[email protected]385a4672009-03-11 22:21:29166}
167
[email protected]04e5be32009-06-26 20:00:31168class CaptureGroupNameSocketPool : public ClientSocketPool {
169 public:
170 CaptureGroupNameSocketPool() {
171 }
172 virtual int RequestSocket(const std::string& group_name,
173 const HostResolver::RequestInfo& resolve_info,
174 int priority,
175 ClientSocketHandle* handle,
176 CompletionCallback* callback) {
177 last_group_name_ = group_name;
178 return ERR_IO_PENDING;
179 }
180
181 const std::string last_group_name_received() const {
182 return last_group_name_;
183 }
184
185 virtual void CancelRequest(const std::string& group_name,
186 const ClientSocketHandle* handle) { }
187 virtual void ReleaseSocket(const std::string& group_name,
188 ClientSocket* socket) {}
189 virtual void CloseIdleSockets() {}
190 virtual HostResolver* GetHostResolver() const {
191 return NULL;
192 }
193 virtual int IdleSocketCount() const {
194 return 0;
195 }
196 virtual int IdleSocketCountInGroup(const std::string& group_name) const {
197 return 0;
198 }
199 virtual LoadState GetLoadState(const std::string& group_name,
200 const ClientSocketHandle* handle) const {
201 return LOAD_STATE_IDLE;
202 }
203 protected:
204 std::string last_group_name_;
205};
206
[email protected]231d5a32008-09-13 00:45:27207//-----------------------------------------------------------------------------
208
209TEST_F(HttpNetworkTransactionTest, Basic) {
[email protected]228ff742009-06-05 01:19:59210 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:40211 scoped_ptr<HttpTransaction> trans(
212 new HttpNetworkTransaction(
[email protected]228ff742009-06-05 01:19:59213 CreateSession(&session_deps),
214 &session_deps.socket_factory));
[email protected]231d5a32008-09-13 00:45:27215}
216
217TEST_F(HttpNetworkTransactionTest, SimpleGET) {
218 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35219 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
220 MockRead("hello world"),
[email protected]1c773ea12009-04-28 19:58:42221 MockRead(false, OK),
[email protected]231d5a32008-09-13 00:45:27222 };
[email protected]231d5a32008-09-13 00:45:27223 SimpleGetHelperResult out = SimpleGetHelper(data_reads);
[email protected]1c773ea12009-04-28 19:58:42224 EXPECT_EQ(OK, out.rv);
[email protected]231d5a32008-09-13 00:45:27225 EXPECT_EQ("HTTP/1.0 200 OK", out.status_line);
226 EXPECT_EQ("hello world", out.response_data);
227}
228
229// Response with no status line.
230TEST_F(HttpNetworkTransactionTest, SimpleGETNoHeaders) {
231 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35232 MockRead("hello world"),
[email protected]1c773ea12009-04-28 19:58:42233 MockRead(false, OK),
[email protected]231d5a32008-09-13 00:45:27234 };
[email protected]231d5a32008-09-13 00:45:27235 SimpleGetHelperResult out = SimpleGetHelper(data_reads);
[email protected]1c773ea12009-04-28 19:58:42236 EXPECT_EQ(OK, out.rv);
[email protected]231d5a32008-09-13 00:45:27237 EXPECT_EQ("HTTP/0.9 200 OK", out.status_line);
238 EXPECT_EQ("hello world", out.response_data);
239}
240
241// Allow up to 4 bytes of junk to precede status line.
242TEST_F(HttpNetworkTransactionTest, StatusLineJunk2Bytes) {
243 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35244 MockRead("xxxHTTP/1.0 404 Not Found\nServer: blah\n\nDATA"),
[email protected]1c773ea12009-04-28 19:58:42245 MockRead(false, OK),
[email protected]231d5a32008-09-13 00:45:27246 };
247 SimpleGetHelperResult out = SimpleGetHelper(data_reads);
[email protected]1c773ea12009-04-28 19:58:42248 EXPECT_EQ(OK, out.rv);
[email protected]231d5a32008-09-13 00:45:27249 EXPECT_EQ("HTTP/1.0 404 Not Found", out.status_line);
250 EXPECT_EQ("DATA", out.response_data);
251}
252
253// Allow up to 4 bytes of junk to precede status line.
254TEST_F(HttpNetworkTransactionTest, StatusLineJunk4Bytes) {
255 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35256 MockRead("\n\nQJHTTP/1.0 404 Not Found\nServer: blah\n\nDATA"),
[email protected]1c773ea12009-04-28 19:58:42257 MockRead(false, OK),
[email protected]231d5a32008-09-13 00:45:27258 };
259 SimpleGetHelperResult out = SimpleGetHelper(data_reads);
[email protected]1c773ea12009-04-28 19:58:42260 EXPECT_EQ(OK, out.rv);
[email protected]231d5a32008-09-13 00:45:27261 EXPECT_EQ("HTTP/1.0 404 Not Found", out.status_line);
262 EXPECT_EQ("DATA", out.response_data);
263}
264
265// Beyond 4 bytes of slop and it should fail to find a status line.
266TEST_F(HttpNetworkTransactionTest, StatusLineJunk5Bytes) {
267 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35268 MockRead("xxxxxHTTP/1.1 404 Not Found\nServer: blah"),
[email protected]1c773ea12009-04-28 19:58:42269 MockRead(false, OK),
[email protected]231d5a32008-09-13 00:45:27270 };
271 SimpleGetHelperResult out = SimpleGetHelper(data_reads);
[email protected]1c773ea12009-04-28 19:58:42272 EXPECT_EQ(OK, out.rv);
[email protected]3d2a59b2008-09-26 19:44:25273 EXPECT_EQ("HTTP/0.9 200 OK", out.status_line);
274 EXPECT_EQ("xxxxxHTTP/1.1 404 Not Found\nServer: blah", out.response_data);
[email protected]231d5a32008-09-13 00:45:27275}
276
277// Same as StatusLineJunk4Bytes, except the read chunks are smaller.
278TEST_F(HttpNetworkTransactionTest, StatusLineJunk4Bytes_Slow) {
279 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35280 MockRead("\n"),
281 MockRead("\n"),
282 MockRead("Q"),
283 MockRead("J"),
284 MockRead("HTTP/1.0 404 Not Found\nServer: blah\n\nDATA"),
[email protected]1c773ea12009-04-28 19:58:42285 MockRead(false, OK),
[email protected]231d5a32008-09-13 00:45:27286 };
287 SimpleGetHelperResult out = SimpleGetHelper(data_reads);
[email protected]1c773ea12009-04-28 19:58:42288 EXPECT_EQ(OK, out.rv);
[email protected]231d5a32008-09-13 00:45:27289 EXPECT_EQ("HTTP/1.0 404 Not Found", out.status_line);
290 EXPECT_EQ("DATA", out.response_data);
291}
292
293// Close the connection before enough bytes to have a status line.
294TEST_F(HttpNetworkTransactionTest, StatusLinePartial) {
295 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35296 MockRead("HTT"),
[email protected]1c773ea12009-04-28 19:58:42297 MockRead(false, OK),
[email protected]231d5a32008-09-13 00:45:27298 };
299 SimpleGetHelperResult out = SimpleGetHelper(data_reads);
[email protected]1c773ea12009-04-28 19:58:42300 EXPECT_EQ(OK, out.rv);
[email protected]231d5a32008-09-13 00:45:27301 EXPECT_EQ("HTTP/0.9 200 OK", out.status_line);
302 EXPECT_EQ("HTT", out.response_data);
initial.commit586acc5fe2008-07-26 22:42:52303}
304
[email protected]f9d44aa2008-09-23 23:57:17305// Simulate a 204 response, lacking a Content-Length header, sent over a
306// persistent connection. The response should still terminate since a 204
307// cannot have a response body.
308TEST_F(HttpNetworkTransactionTest, StopsReading204) {
309 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35310 MockRead("HTTP/1.1 204 No Content\r\n\r\n"),
311 MockRead("junk"), // Should not be read!!
[email protected]1c773ea12009-04-28 19:58:42312 MockRead(false, OK),
[email protected]f9d44aa2008-09-23 23:57:17313 };
314 SimpleGetHelperResult out = SimpleGetHelper(data_reads);
[email protected]1c773ea12009-04-28 19:58:42315 EXPECT_EQ(OK, out.rv);
[email protected]f9d44aa2008-09-23 23:57:17316 EXPECT_EQ("HTTP/1.1 204 No Content", out.status_line);
317 EXPECT_EQ("", out.response_data);
318}
319
[email protected]ef0faf2e72009-03-05 23:27:23320// Do a request using the HEAD method. Verify that we don't try to read the
321// message body (since HEAD has none).
322TEST_F(HttpNetworkTransactionTest, Head) {
[email protected]228ff742009-06-05 01:19:59323 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:40324 scoped_ptr<HttpTransaction> trans(
325 new HttpNetworkTransaction(
[email protected]228ff742009-06-05 01:19:59326 CreateSession(&session_deps),
327 &session_deps.socket_factory));
[email protected]ef0faf2e72009-03-05 23:27:23328
[email protected]1c773ea12009-04-28 19:58:42329 HttpRequestInfo request;
[email protected]ef0faf2e72009-03-05 23:27:23330 request.method = "HEAD";
331 request.url = GURL("http://www.google.com/");
332 request.load_flags = 0;
333
334 MockWrite data_writes1[] = {
335 MockWrite("HEAD / HTTP/1.1\r\n"
336 "Host: www.google.com\r\n"
337 "Connection: keep-alive\r\n"
338 "Content-Length: 0\r\n\r\n"),
339 };
340 MockRead data_reads1[] = {
341 MockRead("HTTP/1.1 404 Not Found\r\n"),
342 MockRead("Server: Blah\r\n"),
343 MockRead("Content-Length: 1234\r\n\r\n"),
344
345 // No response body because the test stops reading here.
[email protected]1c773ea12009-04-28 19:58:42346 MockRead(false, ERR_UNEXPECTED), // Should not be reached.
[email protected]ef0faf2e72009-03-05 23:27:23347 };
348
[email protected]69b43fe2009-06-15 09:47:37349 StaticMockSocket data1(data_reads1, data_writes1);
[email protected]228ff742009-06-05 01:19:59350 session_deps.socket_factory.AddMockSocket(&data1);
[email protected]ef0faf2e72009-03-05 23:27:23351
352 TestCompletionCallback callback1;
353
354 int rv = trans->Start(&request, &callback1);
[email protected]1c773ea12009-04-28 19:58:42355 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]ef0faf2e72009-03-05 23:27:23356
357 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42358 EXPECT_EQ(OK, rv);
[email protected]ef0faf2e72009-03-05 23:27:23359
[email protected]1c773ea12009-04-28 19:58:42360 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]ef0faf2e72009-03-05 23:27:23361 EXPECT_FALSE(response == NULL);
362
363 // Check that the headers got parsed.
364 EXPECT_TRUE(response->headers != NULL);
365 EXPECT_EQ(1234, response->headers->GetContentLength());
366 EXPECT_EQ("HTTP/1.1 404 Not Found", response->headers->GetStatusLine());
367
368 std::string server_header;
369 void* iter = NULL;
370 bool has_server_header = response->headers->EnumerateHeader(
371 &iter, "Server", &server_header);
372 EXPECT_TRUE(has_server_header);
373 EXPECT_EQ("Blah", server_header);
374
375 // Reading should give EOF right away, since there is no message body
376 // (despite non-zero content-length).
377 std::string response_data;
378 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:42379 EXPECT_EQ(OK, rv);
[email protected]ef0faf2e72009-03-05 23:27:23380 EXPECT_EQ("", response_data);
381}
382
initial.commit586acc5fe2008-07-26 22:42:52383TEST_F(HttpNetworkTransactionTest, ReuseConnection) {
[email protected]228ff742009-06-05 01:19:59384 SessionDependencies session_deps;
385 scoped_refptr<HttpNetworkSession> session = CreateSession(&session_deps);
initial.commit586acc5fe2008-07-26 22:42:52386
387 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35388 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
389 MockRead("hello"),
390 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
391 MockRead("world"),
[email protected]1c773ea12009-04-28 19:58:42392 MockRead(false, OK),
initial.commit586acc5fe2008-07-26 22:42:52393 };
[email protected]69b43fe2009-06-15 09:47:37394 StaticMockSocket data(data_reads, NULL);
[email protected]228ff742009-06-05 01:19:59395 session_deps.socket_factory.AddMockSocket(&data);
initial.commit586acc5fe2008-07-26 22:42:52396
397 const char* kExpectedResponseData[] = {
398 "hello", "world"
399 };
400
401 for (int i = 0; i < 2; ++i) {
[email protected]1c773ea12009-04-28 19:58:42402 scoped_ptr<HttpTransaction> trans(
[email protected]228ff742009-06-05 01:19:59403 new HttpNetworkTransaction(session, &session_deps.socket_factory));
initial.commit586acc5fe2008-07-26 22:42:52404
[email protected]1c773ea12009-04-28 19:58:42405 HttpRequestInfo request;
initial.commit586acc5fe2008-07-26 22:42:52406 request.method = "GET";
407 request.url = GURL("http://www.google.com/");
408 request.load_flags = 0;
409
410 TestCompletionCallback callback;
411
412 int rv = trans->Start(&request, &callback);
[email protected]1c773ea12009-04-28 19:58:42413 EXPECT_EQ(ERR_IO_PENDING, rv);
initial.commit586acc5fe2008-07-26 22:42:52414
415 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42416 EXPECT_EQ(OK, rv);
initial.commit586acc5fe2008-07-26 22:42:52417
[email protected]1c773ea12009-04-28 19:58:42418 const HttpResponseInfo* response = trans->GetResponseInfo();
initial.commit586acc5fe2008-07-26 22:42:52419 EXPECT_TRUE(response != NULL);
420
421 EXPECT_TRUE(response->headers != NULL);
[email protected]3d2a59b2008-09-26 19:44:25422 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
initial.commit586acc5fe2008-07-26 22:42:52423
424 std::string response_data;
[email protected]af4876d2008-10-21 23:10:57425 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:42426 EXPECT_EQ(OK, rv);
[email protected]3d2a59b2008-09-26 19:44:25427 EXPECT_EQ(kExpectedResponseData[i], response_data);
initial.commit586acc5fe2008-07-26 22:42:52428 }
429}
430
431TEST_F(HttpNetworkTransactionTest, Ignores100) {
[email protected]228ff742009-06-05 01:19:59432 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:40433 scoped_ptr<HttpTransaction> trans(
434 new HttpNetworkTransaction(
[email protected]228ff742009-06-05 01:19:59435 CreateSession(&session_deps),
436 &session_deps.socket_factory));
initial.commit586acc5fe2008-07-26 22:42:52437
[email protected]1c773ea12009-04-28 19:58:42438 HttpRequestInfo request;
initial.commit586acc5fe2008-07-26 22:42:52439 request.method = "POST";
440 request.url = GURL("http://www.foo.com/");
[email protected]1c773ea12009-04-28 19:58:42441 request.upload_data = new UploadData;
initial.commit586acc5fe2008-07-26 22:42:52442 request.upload_data->AppendBytes("foo", 3);
443 request.load_flags = 0;
444
445 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35446 MockRead("HTTP/1.0 100 Continue\r\n\r\n"),
447 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
448 MockRead("hello world"),
[email protected]1c773ea12009-04-28 19:58:42449 MockRead(false, OK),
initial.commit586acc5fe2008-07-26 22:42:52450 };
[email protected]69b43fe2009-06-15 09:47:37451 StaticMockSocket data(data_reads, NULL);
[email protected]228ff742009-06-05 01:19:59452 session_deps.socket_factory.AddMockSocket(&data);
initial.commit586acc5fe2008-07-26 22:42:52453
454 TestCompletionCallback callback;
455
456 int rv = trans->Start(&request, &callback);
[email protected]1c773ea12009-04-28 19:58:42457 EXPECT_EQ(ERR_IO_PENDING, rv);
initial.commit586acc5fe2008-07-26 22:42:52458
459 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42460 EXPECT_EQ(OK, rv);
initial.commit586acc5fe2008-07-26 22:42:52461
[email protected]1c773ea12009-04-28 19:58:42462 const HttpResponseInfo* response = trans->GetResponseInfo();
initial.commit586acc5fe2008-07-26 22:42:52463 EXPECT_TRUE(response != NULL);
464
465 EXPECT_TRUE(response->headers != NULL);
[email protected]3d2a59b2008-09-26 19:44:25466 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
initial.commit586acc5fe2008-07-26 22:42:52467
468 std::string response_data;
[email protected]af4876d2008-10-21 23:10:57469 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:42470 EXPECT_EQ(OK, rv);
[email protected]3d2a59b2008-09-26 19:44:25471 EXPECT_EQ("hello world", response_data);
initial.commit586acc5fe2008-07-26 22:42:52472}
473
[email protected]3a2d3662009-03-27 03:49:14474// This test is almost the same as Ignores100 above, but the response contains
475// a 102 instead of a 100. Also, instead of HTTP/1.0 the response is
476// HTTP/1.1.
477TEST_F(HttpNetworkTransactionTest, Ignores1xx) {
[email protected]228ff742009-06-05 01:19:59478 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:40479 scoped_ptr<HttpTransaction> trans(
480 new HttpNetworkTransaction(
[email protected]228ff742009-06-05 01:19:59481 CreateSession(&session_deps),
482 &session_deps.socket_factory));
[email protected]3a2d3662009-03-27 03:49:14483
[email protected]1c773ea12009-04-28 19:58:42484 HttpRequestInfo request;
[email protected]3a2d3662009-03-27 03:49:14485 request.method = "GET";
486 request.url = GURL("http://www.foo.com/");
487 request.load_flags = 0;
488
489 MockRead data_reads[] = {
490 MockRead("HTTP/1.1 102 Unspecified status code\r\n\r\n"),
491 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
492 MockRead("hello world"),
[email protected]1c773ea12009-04-28 19:58:42493 MockRead(false, OK),
[email protected]3a2d3662009-03-27 03:49:14494 };
[email protected]69b43fe2009-06-15 09:47:37495 StaticMockSocket data(data_reads, NULL);
[email protected]228ff742009-06-05 01:19:59496 session_deps.socket_factory.AddMockSocket(&data);
[email protected]3a2d3662009-03-27 03:49:14497
498 TestCompletionCallback callback;
499
500 int rv = trans->Start(&request, &callback);
[email protected]1c773ea12009-04-28 19:58:42501 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]3a2d3662009-03-27 03:49:14502
503 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42504 EXPECT_EQ(OK, rv);
[email protected]3a2d3662009-03-27 03:49:14505
[email protected]1c773ea12009-04-28 19:58:42506 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]3a2d3662009-03-27 03:49:14507 EXPECT_TRUE(response != NULL);
508
509 EXPECT_TRUE(response->headers != NULL);
510 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
511
512 std::string response_data;
513 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:42514 EXPECT_EQ(OK, rv);
[email protected]3a2d3662009-03-27 03:49:14515 EXPECT_EQ("hello world", response_data);
516}
517
[email protected]3d2a59b2008-09-26 19:44:25518// read_failure specifies a read failure that should cause the network
519// transaction to resend the request.
520void HttpNetworkTransactionTest::KeepAliveConnectionResendRequestTest(
521 const MockRead& read_failure) {
[email protected]228ff742009-06-05 01:19:59522 SessionDependencies session_deps;
523 scoped_refptr<HttpNetworkSession> session = CreateSession(&session_deps);
initial.commit586acc5fe2008-07-26 22:42:52524
[email protected]1c773ea12009-04-28 19:58:42525 HttpRequestInfo request;
initial.commit586acc5fe2008-07-26 22:42:52526 request.method = "GET";
527 request.url = GURL("http://www.foo.com/");
528 request.load_flags = 0;
529
530 MockRead data1_reads[] = {
[email protected]217e6022008-09-29 18:18:35531 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
532 MockRead("hello"),
[email protected]3d2a59b2008-09-26 19:44:25533 read_failure, // Now, we reuse the connection and fail the first read.
initial.commit586acc5fe2008-07-26 22:42:52534 };
[email protected]69b43fe2009-06-15 09:47:37535 StaticMockSocket data1(data1_reads, NULL);
[email protected]228ff742009-06-05 01:19:59536 session_deps.socket_factory.AddMockSocket(&data1);
initial.commit586acc5fe2008-07-26 22:42:52537
538 MockRead data2_reads[] = {
[email protected]217e6022008-09-29 18:18:35539 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
540 MockRead("world"),
[email protected]1c773ea12009-04-28 19:58:42541 MockRead(true, OK),
initial.commit586acc5fe2008-07-26 22:42:52542 };
[email protected]69b43fe2009-06-15 09:47:37543 StaticMockSocket data2(data2_reads, NULL);
[email protected]228ff742009-06-05 01:19:59544 session_deps.socket_factory.AddMockSocket(&data2);
initial.commit586acc5fe2008-07-26 22:42:52545
546 const char* kExpectedResponseData[] = {
547 "hello", "world"
548 };
549
550 for (int i = 0; i < 2; ++i) {
551 TestCompletionCallback callback;
552
[email protected]1c773ea12009-04-28 19:58:42553 scoped_ptr<HttpTransaction> trans(
[email protected]228ff742009-06-05 01:19:59554 new HttpNetworkTransaction(session, &session_deps.socket_factory));
initial.commit586acc5fe2008-07-26 22:42:52555
556 int rv = trans->Start(&request, &callback);
[email protected]1c773ea12009-04-28 19:58:42557 EXPECT_EQ(ERR_IO_PENDING, rv);
initial.commit586acc5fe2008-07-26 22:42:52558
559 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42560 EXPECT_EQ(OK, rv);
initial.commit586acc5fe2008-07-26 22:42:52561
[email protected]1c773ea12009-04-28 19:58:42562 const HttpResponseInfo* response = trans->GetResponseInfo();
initial.commit586acc5fe2008-07-26 22:42:52563 EXPECT_TRUE(response != NULL);
564
565 EXPECT_TRUE(response->headers != NULL);
[email protected]3d2a59b2008-09-26 19:44:25566 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
initial.commit586acc5fe2008-07-26 22:42:52567
568 std::string response_data;
[email protected]af4876d2008-10-21 23:10:57569 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:42570 EXPECT_EQ(OK, rv);
[email protected]3d2a59b2008-09-26 19:44:25571 EXPECT_EQ(kExpectedResponseData[i], response_data);
initial.commit586acc5fe2008-07-26 22:42:52572 }
573}
[email protected]3d2a59b2008-09-26 19:44:25574
575TEST_F(HttpNetworkTransactionTest, KeepAliveConnectionReset) {
[email protected]1c773ea12009-04-28 19:58:42576 MockRead read_failure(true, ERR_CONNECTION_RESET);
[email protected]3d2a59b2008-09-26 19:44:25577 KeepAliveConnectionResendRequestTest(read_failure);
578}
579
580TEST_F(HttpNetworkTransactionTest, KeepAliveConnectionEOF) {
[email protected]1c773ea12009-04-28 19:58:42581 MockRead read_failure(false, OK); // EOF
[email protected]3d2a59b2008-09-26 19:44:25582 KeepAliveConnectionResendRequestTest(read_failure);
583}
584
585TEST_F(HttpNetworkTransactionTest, NonKeepAliveConnectionReset) {
[email protected]228ff742009-06-05 01:19:59586 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:40587 scoped_ptr<HttpTransaction> trans(
588 new HttpNetworkTransaction(
[email protected]228ff742009-06-05 01:19:59589 CreateSession(&session_deps),
590 &session_deps.socket_factory));
[email protected]3d2a59b2008-09-26 19:44:25591
[email protected]1c773ea12009-04-28 19:58:42592 HttpRequestInfo request;
[email protected]3d2a59b2008-09-26 19:44:25593 request.method = "GET";
594 request.url = GURL("http://www.google.com/");
595 request.load_flags = 0;
596
597 MockRead data_reads[] = {
[email protected]1c773ea12009-04-28 19:58:42598 MockRead(true, ERR_CONNECTION_RESET),
[email protected]217e6022008-09-29 18:18:35599 MockRead("HTTP/1.0 200 OK\r\n\r\n"), // Should not be used
600 MockRead("hello world"),
[email protected]1c773ea12009-04-28 19:58:42601 MockRead(false, OK),
[email protected]3d2a59b2008-09-26 19:44:25602 };
[email protected]69b43fe2009-06-15 09:47:37603 StaticMockSocket data(data_reads, NULL);
[email protected]228ff742009-06-05 01:19:59604 session_deps.socket_factory.AddMockSocket(&data);
[email protected]3d2a59b2008-09-26 19:44:25605
606 TestCompletionCallback callback;
607
608 int rv = trans->Start(&request, &callback);
[email protected]1c773ea12009-04-28 19:58:42609 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]3d2a59b2008-09-26 19:44:25610
611 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42612 EXPECT_EQ(ERR_CONNECTION_RESET, rv);
[email protected]3d2a59b2008-09-26 19:44:25613
[email protected]1c773ea12009-04-28 19:58:42614 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]3d2a59b2008-09-26 19:44:25615 EXPECT_TRUE(response == NULL);
[email protected]3d2a59b2008-09-26 19:44:25616}
617
618// What do various browsers do when the server closes a non-keepalive
619// connection without sending any response header or body?
620//
621// IE7: error page
622// Safari 3.1.2 (Windows): error page
623// Firefox 3.0.1: blank page
624// Opera 9.52: after five attempts, blank page
[email protected]1c773ea12009-04-28 19:58:42625// Us with WinHTTP: error page (ERR_INVALID_RESPONSE)
626// Us: error page (EMPTY_RESPONSE)
[email protected]3d2a59b2008-09-26 19:44:25627TEST_F(HttpNetworkTransactionTest, NonKeepAliveConnectionEOF) {
628 MockRead data_reads[] = {
[email protected]1c773ea12009-04-28 19:58:42629 MockRead(false, OK), // EOF
[email protected]217e6022008-09-29 18:18:35630 MockRead("HTTP/1.0 200 OK\r\n\r\n"), // Should not be used
631 MockRead("hello world"),
[email protected]1c773ea12009-04-28 19:58:42632 MockRead(false, OK),
[email protected]3d2a59b2008-09-26 19:44:25633 };
634 SimpleGetHelperResult out = SimpleGetHelper(data_reads);
[email protected]1c773ea12009-04-28 19:58:42635 EXPECT_EQ(ERR_EMPTY_RESPONSE, out.rv);
[email protected]3d2a59b2008-09-26 19:44:25636}
[email protected]038e9a32008-10-08 22:40:16637
638// Test the request-challenge-retry sequence for basic auth.
639// (basic auth is the easiest to mock, because it has no randomness).
640TEST_F(HttpNetworkTransactionTest, BasicAuth) {
[email protected]228ff742009-06-05 01:19:59641 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:40642 scoped_ptr<HttpTransaction> trans(
643 new HttpNetworkTransaction(
[email protected]228ff742009-06-05 01:19:59644 CreateSession(&session_deps),
645 &session_deps.socket_factory));
[email protected]038e9a32008-10-08 22:40:16646
[email protected]1c773ea12009-04-28 19:58:42647 HttpRequestInfo request;
[email protected]038e9a32008-10-08 22:40:16648 request.method = "GET";
649 request.url = GURL("http://www.google.com/");
650 request.load_flags = 0;
651
[email protected]f9ee6b52008-11-08 06:46:23652 MockWrite data_writes1[] = {
653 MockWrite("GET / HTTP/1.1\r\n"
654 "Host: www.google.com\r\n"
655 "Connection: keep-alive\r\n\r\n"),
656 };
657
[email protected]038e9a32008-10-08 22:40:16658 MockRead data_reads1[] = {
659 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
660 // Give a couple authenticate options (only the middle one is actually
661 // supported).
[email protected]aaead502008-10-15 00:20:11662 MockRead("WWW-Authenticate: Basic\r\n"), // Malformed
[email protected]038e9a32008-10-08 22:40:16663 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
664 MockRead("WWW-Authenticate: UNSUPPORTED realm=\"FOO\"\r\n"),
665 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
666 // Large content-length -- won't matter, as connection will be reset.
667 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:42668 MockRead(false, ERR_FAILED),
[email protected]038e9a32008-10-08 22:40:16669 };
670
671 // After calling trans->RestartWithAuth(), this is the request we should
672 // be issuing -- the final header line contains the credentials.
673 MockWrite data_writes2[] = {
674 MockWrite("GET / HTTP/1.1\r\n"
675 "Host: www.google.com\r\n"
676 "Connection: keep-alive\r\n"
677 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
678 };
679
680 // Lastly, the server responds with the actual content.
681 MockRead data_reads2[] = {
682 MockRead("HTTP/1.0 200 OK\r\n"),
683 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
684 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:42685 MockRead(false, OK),
[email protected]038e9a32008-10-08 22:40:16686 };
687
[email protected]69b43fe2009-06-15 09:47:37688 StaticMockSocket data1(data_reads1, data_writes1);
689 StaticMockSocket data2(data_reads2, data_writes2);
[email protected]228ff742009-06-05 01:19:59690 session_deps.socket_factory.AddMockSocket(&data1);
691 session_deps.socket_factory.AddMockSocket(&data2);
[email protected]038e9a32008-10-08 22:40:16692
693 TestCompletionCallback callback1;
694
695 int rv = trans->Start(&request, &callback1);
[email protected]1c773ea12009-04-28 19:58:42696 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]038e9a32008-10-08 22:40:16697
698 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42699 EXPECT_EQ(OK, rv);
[email protected]038e9a32008-10-08 22:40:16700
[email protected]1c773ea12009-04-28 19:58:42701 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]038e9a32008-10-08 22:40:16702 EXPECT_FALSE(response == NULL);
703
704 // The password prompt info should have been set in response->auth_challenge.
705 EXPECT_FALSE(response->auth_challenge.get() == NULL);
706
[email protected]71e4573a2009-05-21 22:03:00707 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
[email protected]038e9a32008-10-08 22:40:16708 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
709 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
710
711 TestCompletionCallback callback2;
712
713 rv = trans->RestartWithAuth(L"foo", L"bar", &callback2);
[email protected]1c773ea12009-04-28 19:58:42714 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]038e9a32008-10-08 22:40:16715
716 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42717 EXPECT_EQ(OK, rv);
[email protected]038e9a32008-10-08 22:40:16718
719 response = trans->GetResponseInfo();
720 EXPECT_FALSE(response == NULL);
721 EXPECT_TRUE(response->auth_challenge.get() == NULL);
722 EXPECT_EQ(100, response->headers->GetContentLength());
[email protected]038e9a32008-10-08 22:40:16723}
724
[email protected]2d2697f92009-02-18 21:00:32725// Test the request-challenge-retry sequence for basic auth, over a keep-alive
726// connection.
727TEST_F(HttpNetworkTransactionTest, BasicAuthKeepAlive) {
[email protected]228ff742009-06-05 01:19:59728 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:40729 scoped_ptr<HttpTransaction> trans(
730 new HttpNetworkTransaction(
[email protected]228ff742009-06-05 01:19:59731 CreateSession(&session_deps),
732 &session_deps.socket_factory));
[email protected]2d2697f92009-02-18 21:00:32733
[email protected]1c773ea12009-04-28 19:58:42734 HttpRequestInfo request;
[email protected]2d2697f92009-02-18 21:00:32735 request.method = "GET";
736 request.url = GURL("http://www.google.com/");
737 request.load_flags = 0;
738
739 MockWrite data_writes1[] = {
740 MockWrite("GET / HTTP/1.1\r\n"
741 "Host: www.google.com\r\n"
742 "Connection: keep-alive\r\n\r\n"),
743
744 // After calling trans->RestartWithAuth(), this is the request we should
745 // be issuing -- the final header line contains the credentials.
746 MockWrite("GET / HTTP/1.1\r\n"
747 "Host: www.google.com\r\n"
748 "Connection: keep-alive\r\n"
749 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
750 };
751
752 MockRead data_reads1[] = {
753 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
754 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
755 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
756 MockRead("Content-Length: 14\r\n\r\n"),
757 MockRead("Unauthorized\r\n"),
758
759 // Lastly, the server responds with the actual content.
760 MockRead("HTTP/1.1 200 OK\r\n"),
761 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
762 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:42763 MockRead(false, OK),
[email protected]2d2697f92009-02-18 21:00:32764 };
765
[email protected]69b43fe2009-06-15 09:47:37766 StaticMockSocket data1(data_reads1, data_writes1);
[email protected]228ff742009-06-05 01:19:59767 session_deps.socket_factory.AddMockSocket(&data1);
[email protected]2d2697f92009-02-18 21:00:32768
769 TestCompletionCallback callback1;
770
771 int rv = trans->Start(&request, &callback1);
[email protected]1c773ea12009-04-28 19:58:42772 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:32773
774 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42775 EXPECT_EQ(OK, rv);
[email protected]2d2697f92009-02-18 21:00:32776
[email protected]1c773ea12009-04-28 19:58:42777 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]2d2697f92009-02-18 21:00:32778 EXPECT_FALSE(response == NULL);
779
780 // The password prompt info should have been set in response->auth_challenge.
781 EXPECT_FALSE(response->auth_challenge.get() == NULL);
782
[email protected]71e4573a2009-05-21 22:03:00783 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
[email protected]2d2697f92009-02-18 21:00:32784 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
785 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
786
787 TestCompletionCallback callback2;
788
789 rv = trans->RestartWithAuth(L"foo", L"bar", &callback2);
[email protected]1c773ea12009-04-28 19:58:42790 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:32791
792 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42793 EXPECT_EQ(OK, rv);
[email protected]2d2697f92009-02-18 21:00:32794
795 response = trans->GetResponseInfo();
796 EXPECT_FALSE(response == NULL);
797 EXPECT_TRUE(response->auth_challenge.get() == NULL);
798 EXPECT_EQ(100, response->headers->GetContentLength());
799}
800
801// Test the request-challenge-retry sequence for basic auth, over a keep-alive
802// connection and with no response body to drain.
803TEST_F(HttpNetworkTransactionTest, BasicAuthKeepAliveNoBody) {
[email protected]228ff742009-06-05 01:19:59804 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:40805 scoped_ptr<HttpTransaction> trans(
806 new HttpNetworkTransaction(
[email protected]228ff742009-06-05 01:19:59807 CreateSession(&session_deps),
808 &session_deps.socket_factory));
[email protected]2d2697f92009-02-18 21:00:32809
[email protected]1c773ea12009-04-28 19:58:42810 HttpRequestInfo request;
[email protected]2d2697f92009-02-18 21:00:32811 request.method = "GET";
812 request.url = GURL("http://www.google.com/");
813 request.load_flags = 0;
814
815 MockWrite data_writes1[] = {
816 MockWrite("GET / HTTP/1.1\r\n"
817 "Host: www.google.com\r\n"
818 "Connection: keep-alive\r\n\r\n"),
819
820 // After calling trans->RestartWithAuth(), this is the request we should
821 // be issuing -- the final header line contains the credentials.
822 MockWrite("GET / HTTP/1.1\r\n"
823 "Host: www.google.com\r\n"
824 "Connection: keep-alive\r\n"
825 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
826 };
827
828 // Respond with 5 kb of response body.
829 std::string large_body_string("Unauthorized");
830 large_body_string.append(5 * 1024, ' ');
831 large_body_string.append("\r\n");
832
833 MockRead data_reads1[] = {
834 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
835 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
836 MockRead("Content-Length: 0\r\n\r\n"),
837
838 // Lastly, the server responds with the actual content.
839 MockRead("HTTP/1.1 200 OK\r\n"),
840 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
841 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:42842 MockRead(false, OK),
[email protected]2d2697f92009-02-18 21:00:32843 };
844
[email protected]69b43fe2009-06-15 09:47:37845 StaticMockSocket data1(data_reads1, data_writes1);
[email protected]228ff742009-06-05 01:19:59846 session_deps.socket_factory.AddMockSocket(&data1);
[email protected]2d2697f92009-02-18 21:00:32847
848 TestCompletionCallback callback1;
849
850 int rv = trans->Start(&request, &callback1);
[email protected]1c773ea12009-04-28 19:58:42851 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:32852
853 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42854 EXPECT_EQ(OK, rv);
[email protected]2d2697f92009-02-18 21:00:32855
[email protected]1c773ea12009-04-28 19:58:42856 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]2d2697f92009-02-18 21:00:32857 EXPECT_FALSE(response == NULL);
858
859 // The password prompt info should have been set in response->auth_challenge.
860 EXPECT_FALSE(response->auth_challenge.get() == NULL);
861
[email protected]71e4573a2009-05-21 22:03:00862 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
[email protected]2d2697f92009-02-18 21:00:32863 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
864 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
865
866 TestCompletionCallback callback2;
867
868 rv = trans->RestartWithAuth(L"foo", L"bar", &callback2);
[email protected]1c773ea12009-04-28 19:58:42869 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:32870
871 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42872 EXPECT_EQ(OK, rv);
[email protected]2d2697f92009-02-18 21:00:32873
874 response = trans->GetResponseInfo();
875 EXPECT_FALSE(response == NULL);
876 EXPECT_TRUE(response->auth_challenge.get() == NULL);
877 EXPECT_EQ(100, response->headers->GetContentLength());
878}
879
880// Test the request-challenge-retry sequence for basic auth, over a keep-alive
881// connection and with a large response body to drain.
882TEST_F(HttpNetworkTransactionTest, BasicAuthKeepAliveLargeBody) {
[email protected]228ff742009-06-05 01:19:59883 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:40884 scoped_ptr<HttpTransaction> trans(
885 new HttpNetworkTransaction(
[email protected]228ff742009-06-05 01:19:59886 CreateSession(&session_deps),
887 &session_deps.socket_factory));
[email protected]2d2697f92009-02-18 21:00:32888
[email protected]1c773ea12009-04-28 19:58:42889 HttpRequestInfo request;
[email protected]2d2697f92009-02-18 21:00:32890 request.method = "GET";
891 request.url = GURL("http://www.google.com/");
892 request.load_flags = 0;
893
894 MockWrite data_writes1[] = {
895 MockWrite("GET / HTTP/1.1\r\n"
896 "Host: www.google.com\r\n"
897 "Connection: keep-alive\r\n\r\n"),
898
899 // After calling trans->RestartWithAuth(), this is the request we should
900 // be issuing -- the final header line contains the credentials.
901 MockWrite("GET / HTTP/1.1\r\n"
902 "Host: www.google.com\r\n"
903 "Connection: keep-alive\r\n"
904 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
905 };
906
907 // Respond with 5 kb of response body.
908 std::string large_body_string("Unauthorized");
909 large_body_string.append(5 * 1024, ' ');
910 large_body_string.append("\r\n");
911
912 MockRead data_reads1[] = {
913 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
914 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
915 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
916 // 5134 = 12 + 5 * 1024 + 2
917 MockRead("Content-Length: 5134\r\n\r\n"),
918 MockRead(true, large_body_string.data(), large_body_string.size()),
919
920 // Lastly, the server responds with the actual content.
921 MockRead("HTTP/1.1 200 OK\r\n"),
922 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
923 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:42924 MockRead(false, OK),
[email protected]2d2697f92009-02-18 21:00:32925 };
926
[email protected]69b43fe2009-06-15 09:47:37927 StaticMockSocket data1(data_reads1, data_writes1);
[email protected]228ff742009-06-05 01:19:59928 session_deps.socket_factory.AddMockSocket(&data1);
[email protected]2d2697f92009-02-18 21:00:32929
930 TestCompletionCallback callback1;
931
932 int rv = trans->Start(&request, &callback1);
[email protected]1c773ea12009-04-28 19:58:42933 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:32934
935 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42936 EXPECT_EQ(OK, rv);
[email protected]2d2697f92009-02-18 21:00:32937
[email protected]1c773ea12009-04-28 19:58:42938 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]2d2697f92009-02-18 21:00:32939 EXPECT_FALSE(response == NULL);
940
941 // The password prompt info should have been set in response->auth_challenge.
942 EXPECT_FALSE(response->auth_challenge.get() == NULL);
943
[email protected]71e4573a2009-05-21 22:03:00944 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
[email protected]2d2697f92009-02-18 21:00:32945 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
946 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
947
948 TestCompletionCallback callback2;
949
950 rv = trans->RestartWithAuth(L"foo", L"bar", &callback2);
[email protected]1c773ea12009-04-28 19:58:42951 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:32952
953 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42954 EXPECT_EQ(OK, rv);
[email protected]2d2697f92009-02-18 21:00:32955
956 response = trans->GetResponseInfo();
957 EXPECT_FALSE(response == NULL);
958 EXPECT_TRUE(response->auth_challenge.get() == NULL);
959 EXPECT_EQ(100, response->headers->GetContentLength());
960}
961
962// Test the request-challenge-retry sequence for basic auth, over a keep-alive
963// proxy connection, when setting up an SSL tunnel.
964TEST_F(HttpNetworkTransactionTest, BasicAuthProxyKeepAlive) {
965 // Configure against proxy server "myproxy:70".
[email protected]228ff742009-06-05 01:19:59966 SessionDependencies session_deps(CreateFixedProxyService("myproxy:70"));
967 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]2d2697f92009-02-18 21:00:32968
[email protected]1c773ea12009-04-28 19:58:42969 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(
[email protected]228ff742009-06-05 01:19:59970 session.get(), &session_deps.socket_factory));
[email protected]2d2697f92009-02-18 21:00:32971
[email protected]1c773ea12009-04-28 19:58:42972 HttpRequestInfo request;
[email protected]2d2697f92009-02-18 21:00:32973 request.method = "GET";
974 request.url = GURL("https://www.google.com/");
975 request.load_flags = 0;
976
977 // Since we have proxy, should try to establish tunnel.
978 MockWrite data_writes1[] = {
979 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
[email protected]e44de5d2009-06-05 20:12:45980 "Host: www.google.com\r\n"
981 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]2d2697f92009-02-18 21:00:32982
983 // After calling trans->RestartWithAuth(), this is the request we should
984 // be issuing -- the final header line contains the credentials.
985 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
986 "Host: www.google.com\r\n"
[email protected]e44de5d2009-06-05 20:12:45987 "Proxy-Connection: keep-alive\r\n"
[email protected]2d2697f92009-02-18 21:00:32988 "Proxy-Authorization: Basic Zm9vOmJheg==\r\n\r\n"),
989 };
990
991 // The proxy responds to the connect with a 407, using a persistent
992 // connection.
993 MockRead data_reads1[] = {
994 // No credentials.
995 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
996 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
997 MockRead("Content-Length: 10\r\n\r\n"),
998 MockRead("0123456789"),
999
1000 // Wrong credentials (wrong password).
1001 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
1002 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1003 MockRead("Content-Length: 10\r\n\r\n"),
1004 // No response body because the test stops reading here.
[email protected]1c773ea12009-04-28 19:58:421005 MockRead(false, ERR_UNEXPECTED), // Should not be reached.
[email protected]2d2697f92009-02-18 21:00:321006 };
1007
[email protected]69b43fe2009-06-15 09:47:371008 StaticMockSocket data1(data_reads1, data_writes1);
[email protected]228ff742009-06-05 01:19:591009 session_deps.socket_factory.AddMockSocket(&data1);
[email protected]2d2697f92009-02-18 21:00:321010
1011 TestCompletionCallback callback1;
1012
1013 int rv = trans->Start(&request, &callback1);
[email protected]1c773ea12009-04-28 19:58:421014 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:321015
1016 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421017 EXPECT_EQ(OK, rv);
[email protected]2d2697f92009-02-18 21:00:321018
[email protected]1c773ea12009-04-28 19:58:421019 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]2d2697f92009-02-18 21:00:321020 EXPECT_FALSE(response == NULL);
1021
1022 EXPECT_TRUE(response->headers->IsKeepAlive());
1023 EXPECT_EQ(407, response->headers->response_code());
1024 EXPECT_EQ(10, response->headers->GetContentLength());
[email protected]1c773ea12009-04-28 19:58:421025 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
[email protected]2d2697f92009-02-18 21:00:321026
1027 // The password prompt info should have been set in response->auth_challenge.
1028 EXPECT_FALSE(response->auth_challenge.get() == NULL);
1029
[email protected]71e4573a2009-05-21 22:03:001030 EXPECT_EQ(L"myproxy:70", response->auth_challenge->host_and_port);
[email protected]2d2697f92009-02-18 21:00:321031 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
1032 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
1033
1034 TestCompletionCallback callback2;
1035
1036 // Wrong password (should be "bar").
1037 rv = trans->RestartWithAuth(L"foo", L"baz", &callback2);
[email protected]1c773ea12009-04-28 19:58:421038 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:321039
1040 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421041 EXPECT_EQ(OK, rv);
[email protected]2d2697f92009-02-18 21:00:321042
1043 response = trans->GetResponseInfo();
1044 EXPECT_FALSE(response == NULL);
1045
1046 EXPECT_TRUE(response->headers->IsKeepAlive());
1047 EXPECT_EQ(407, response->headers->response_code());
1048 EXPECT_EQ(10, response->headers->GetContentLength());
[email protected]1c773ea12009-04-28 19:58:421049 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
[email protected]2d2697f92009-02-18 21:00:321050
1051 // The password prompt info should have been set in response->auth_challenge.
1052 EXPECT_FALSE(response->auth_challenge.get() == NULL);
1053
[email protected]71e4573a2009-05-21 22:03:001054 EXPECT_EQ(L"myproxy:70", response->auth_challenge->host_and_port);
[email protected]2d2697f92009-02-18 21:00:321055 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
1056 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
1057}
1058
[email protected]a8e9b162009-03-12 00:06:441059// Test that we don't read the response body when we fail to establish a tunnel,
1060// even if the user cancels the proxy's auth attempt.
1061TEST_F(HttpNetworkTransactionTest, BasicAuthProxyCancelTunnel) {
1062 // Configure against proxy server "myproxy:70".
[email protected]228ff742009-06-05 01:19:591063 SessionDependencies session_deps(CreateFixedProxyService("myproxy:70"));
[email protected]a8e9b162009-03-12 00:06:441064
[email protected]e44de5d2009-06-05 20:12:451065 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]a8e9b162009-03-12 00:06:441066
[email protected]1c773ea12009-04-28 19:58:421067 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(
[email protected]228ff742009-06-05 01:19:591068 session.get(), &session_deps.socket_factory));
[email protected]a8e9b162009-03-12 00:06:441069
[email protected]1c773ea12009-04-28 19:58:421070 HttpRequestInfo request;
[email protected]a8e9b162009-03-12 00:06:441071 request.method = "GET";
1072 request.url = GURL("https://www.google.com/");
1073 request.load_flags = 0;
1074
1075 // Since we have proxy, should try to establish tunnel.
1076 MockWrite data_writes[] = {
1077 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
[email protected]e44de5d2009-06-05 20:12:451078 "Host: www.google.com\r\n"
1079 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]a8e9b162009-03-12 00:06:441080 };
1081
1082 // The proxy responds to the connect with a 407.
1083 MockRead data_reads[] = {
1084 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
1085 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1086 MockRead("Content-Length: 10\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:421087 MockRead(false, ERR_UNEXPECTED), // Should not be reached.
[email protected]a8e9b162009-03-12 00:06:441088 };
1089
[email protected]69b43fe2009-06-15 09:47:371090 StaticMockSocket data(data_reads, data_writes);
[email protected]228ff742009-06-05 01:19:591091 session_deps.socket_factory.AddMockSocket(&data);
[email protected]a8e9b162009-03-12 00:06:441092
1093 TestCompletionCallback callback;
1094
1095 int rv = trans->Start(&request, &callback);
[email protected]1c773ea12009-04-28 19:58:421096 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]a8e9b162009-03-12 00:06:441097
1098 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421099 EXPECT_EQ(OK, rv);
[email protected]a8e9b162009-03-12 00:06:441100
[email protected]1c773ea12009-04-28 19:58:421101 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]a8e9b162009-03-12 00:06:441102 EXPECT_FALSE(response == NULL);
1103
1104 EXPECT_TRUE(response->headers->IsKeepAlive());
1105 EXPECT_EQ(407, response->headers->response_code());
1106 EXPECT_EQ(10, response->headers->GetContentLength());
[email protected]1c773ea12009-04-28 19:58:421107 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
[email protected]a8e9b162009-03-12 00:06:441108
1109 std::string response_data;
1110 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:421111 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED, rv);
[email protected]a8e9b162009-03-12 00:06:441112}
1113
[email protected]ff007e162009-05-23 09:13:151114void HttpNetworkTransactionTest::ConnectStatusHelperWithExpectedStatus(
[email protected]c744cf22009-02-27 07:28:081115 const MockRead& status, int expected_status) {
1116 // Configure against proxy server "myproxy:70".
[email protected]228ff742009-06-05 01:19:591117 SessionDependencies session_deps(CreateFixedProxyService("myproxy:70"));
[email protected]c744cf22009-02-27 07:28:081118
[email protected]228ff742009-06-05 01:19:591119 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]c744cf22009-02-27 07:28:081120
[email protected]1c773ea12009-04-28 19:58:421121 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(
[email protected]228ff742009-06-05 01:19:591122 session.get(), &session_deps.socket_factory));
[email protected]c744cf22009-02-27 07:28:081123
[email protected]1c773ea12009-04-28 19:58:421124 HttpRequestInfo request;
[email protected]c744cf22009-02-27 07:28:081125 request.method = "GET";
1126 request.url = GURL("https://www.google.com/");
1127 request.load_flags = 0;
1128
1129 // Since we have proxy, should try to establish tunnel.
1130 MockWrite data_writes[] = {
1131 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
[email protected]e44de5d2009-06-05 20:12:451132 "Host: www.google.com\r\n"
1133 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]c744cf22009-02-27 07:28:081134 };
1135
1136 MockRead data_reads[] = {
1137 status,
1138 MockRead("Content-Length: 10\r\n\r\n"),
1139 // No response body because the test stops reading here.
[email protected]1c773ea12009-04-28 19:58:421140 MockRead(false, ERR_UNEXPECTED), // Should not be reached.
[email protected]c744cf22009-02-27 07:28:081141 };
1142
[email protected]69b43fe2009-06-15 09:47:371143 StaticMockSocket data(data_reads, data_writes);
[email protected]228ff742009-06-05 01:19:591144 session_deps.socket_factory.AddMockSocket(&data);
[email protected]c744cf22009-02-27 07:28:081145
1146 TestCompletionCallback callback;
1147
1148 int rv = trans->Start(&request, &callback);
[email protected]1c773ea12009-04-28 19:58:421149 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]c744cf22009-02-27 07:28:081150
1151 rv = callback.WaitForResult();
1152 EXPECT_EQ(expected_status, rv);
1153}
1154
[email protected]ff007e162009-05-23 09:13:151155void HttpNetworkTransactionTest::ConnectStatusHelper(const MockRead& status) {
[email protected]c744cf22009-02-27 07:28:081156 ConnectStatusHelperWithExpectedStatus(
[email protected]1c773ea12009-04-28 19:58:421157 status, ERR_TUNNEL_CONNECTION_FAILED);
[email protected]c744cf22009-02-27 07:28:081158}
1159
1160TEST_F(HttpNetworkTransactionTest, ConnectStatus100) {
1161 ConnectStatusHelper(MockRead("HTTP/1.1 100 Continue\r\n"));
1162}
1163
1164TEST_F(HttpNetworkTransactionTest, ConnectStatus101) {
1165 ConnectStatusHelper(MockRead("HTTP/1.1 101 Switching Protocols\r\n"));
1166}
1167
1168TEST_F(HttpNetworkTransactionTest, ConnectStatus201) {
1169 ConnectStatusHelper(MockRead("HTTP/1.1 201 Created\r\n"));
1170}
1171
1172TEST_F(HttpNetworkTransactionTest, ConnectStatus202) {
1173 ConnectStatusHelper(MockRead("HTTP/1.1 202 Accepted\r\n"));
1174}
1175
1176TEST_F(HttpNetworkTransactionTest, ConnectStatus203) {
1177 ConnectStatusHelper(
1178 MockRead("HTTP/1.1 203 Non-Authoritative Information\r\n"));
1179}
1180
1181TEST_F(HttpNetworkTransactionTest, ConnectStatus204) {
1182 ConnectStatusHelper(MockRead("HTTP/1.1 204 No Content\r\n"));
1183}
1184
1185TEST_F(HttpNetworkTransactionTest, ConnectStatus205) {
1186 ConnectStatusHelper(MockRead("HTTP/1.1 205 Reset Content\r\n"));
1187}
1188
1189TEST_F(HttpNetworkTransactionTest, ConnectStatus206) {
1190 ConnectStatusHelper(MockRead("HTTP/1.1 206 Partial Content\r\n"));
1191}
1192
1193TEST_F(HttpNetworkTransactionTest, ConnectStatus300) {
1194 ConnectStatusHelper(MockRead("HTTP/1.1 300 Multiple Choices\r\n"));
1195}
1196
1197TEST_F(HttpNetworkTransactionTest, ConnectStatus301) {
1198 ConnectStatusHelper(MockRead("HTTP/1.1 301 Moved Permanently\r\n"));
1199}
1200
1201TEST_F(HttpNetworkTransactionTest, ConnectStatus302) {
1202 ConnectStatusHelper(MockRead("HTTP/1.1 302 Found\r\n"));
1203}
1204
1205TEST_F(HttpNetworkTransactionTest, ConnectStatus303) {
1206 ConnectStatusHelper(MockRead("HTTP/1.1 303 See Other\r\n"));
1207}
1208
1209TEST_F(HttpNetworkTransactionTest, ConnectStatus304) {
1210 ConnectStatusHelper(MockRead("HTTP/1.1 304 Not Modified\r\n"));
1211}
1212
1213TEST_F(HttpNetworkTransactionTest, ConnectStatus305) {
1214 ConnectStatusHelper(MockRead("HTTP/1.1 305 Use Proxy\r\n"));
1215}
1216
1217TEST_F(HttpNetworkTransactionTest, ConnectStatus306) {
1218 ConnectStatusHelper(MockRead("HTTP/1.1 306\r\n"));
1219}
1220
1221TEST_F(HttpNetworkTransactionTest, ConnectStatus307) {
1222 ConnectStatusHelper(MockRead("HTTP/1.1 307 Temporary Redirect\r\n"));
1223}
1224
1225TEST_F(HttpNetworkTransactionTest, ConnectStatus400) {
1226 ConnectStatusHelper(MockRead("HTTP/1.1 400 Bad Request\r\n"));
1227}
1228
1229TEST_F(HttpNetworkTransactionTest, ConnectStatus401) {
1230 ConnectStatusHelper(MockRead("HTTP/1.1 401 Unauthorized\r\n"));
1231}
1232
1233TEST_F(HttpNetworkTransactionTest, ConnectStatus402) {
1234 ConnectStatusHelper(MockRead("HTTP/1.1 402 Payment Required\r\n"));
1235}
1236
1237TEST_F(HttpNetworkTransactionTest, ConnectStatus403) {
1238 ConnectStatusHelper(MockRead("HTTP/1.1 403 Forbidden\r\n"));
1239}
1240
1241TEST_F(HttpNetworkTransactionTest, ConnectStatus404) {
1242 ConnectStatusHelper(MockRead("HTTP/1.1 404 Not Found\r\n"));
1243}
1244
1245TEST_F(HttpNetworkTransactionTest, ConnectStatus405) {
1246 ConnectStatusHelper(MockRead("HTTP/1.1 405 Method Not Allowed\r\n"));
1247}
1248
1249TEST_F(HttpNetworkTransactionTest, ConnectStatus406) {
1250 ConnectStatusHelper(MockRead("HTTP/1.1 406 Not Acceptable\r\n"));
1251}
1252
1253TEST_F(HttpNetworkTransactionTest, ConnectStatus407) {
1254 ConnectStatusHelperWithExpectedStatus(
1255 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
[email protected]1c773ea12009-04-28 19:58:421256 ERR_PROXY_AUTH_REQUESTED);
[email protected]c744cf22009-02-27 07:28:081257}
1258
1259TEST_F(HttpNetworkTransactionTest, ConnectStatus408) {
1260 ConnectStatusHelper(MockRead("HTTP/1.1 408 Request Timeout\r\n"));
1261}
1262
1263TEST_F(HttpNetworkTransactionTest, ConnectStatus409) {
1264 ConnectStatusHelper(MockRead("HTTP/1.1 409 Conflict\r\n"));
1265}
1266
1267TEST_F(HttpNetworkTransactionTest, ConnectStatus410) {
1268 ConnectStatusHelper(MockRead("HTTP/1.1 410 Gone\r\n"));
1269}
1270
1271TEST_F(HttpNetworkTransactionTest, ConnectStatus411) {
1272 ConnectStatusHelper(MockRead("HTTP/1.1 411 Length Required\r\n"));
1273}
1274
1275TEST_F(HttpNetworkTransactionTest, ConnectStatus412) {
1276 ConnectStatusHelper(MockRead("HTTP/1.1 412 Precondition Failed\r\n"));
1277}
1278
1279TEST_F(HttpNetworkTransactionTest, ConnectStatus413) {
1280 ConnectStatusHelper(MockRead("HTTP/1.1 413 Request Entity Too Large\r\n"));
1281}
1282
1283TEST_F(HttpNetworkTransactionTest, ConnectStatus414) {
1284 ConnectStatusHelper(MockRead("HTTP/1.1 414 Request-URI Too Long\r\n"));
1285}
1286
1287TEST_F(HttpNetworkTransactionTest, ConnectStatus415) {
1288 ConnectStatusHelper(MockRead("HTTP/1.1 415 Unsupported Media Type\r\n"));
1289}
1290
1291TEST_F(HttpNetworkTransactionTest, ConnectStatus416) {
1292 ConnectStatusHelper(
1293 MockRead("HTTP/1.1 416 Requested Range Not Satisfiable\r\n"));
1294}
1295
1296TEST_F(HttpNetworkTransactionTest, ConnectStatus417) {
1297 ConnectStatusHelper(MockRead("HTTP/1.1 417 Expectation Failed\r\n"));
1298}
1299
1300TEST_F(HttpNetworkTransactionTest, ConnectStatus500) {
1301 ConnectStatusHelper(MockRead("HTTP/1.1 500 Internal Server Error\r\n"));
1302}
1303
1304TEST_F(HttpNetworkTransactionTest, ConnectStatus501) {
1305 ConnectStatusHelper(MockRead("HTTP/1.1 501 Not Implemented\r\n"));
1306}
1307
1308TEST_F(HttpNetworkTransactionTest, ConnectStatus502) {
1309 ConnectStatusHelper(MockRead("HTTP/1.1 502 Bad Gateway\r\n"));
1310}
1311
1312TEST_F(HttpNetworkTransactionTest, ConnectStatus503) {
1313 ConnectStatusHelper(MockRead("HTTP/1.1 503 Service Unavailable\r\n"));
1314}
1315
1316TEST_F(HttpNetworkTransactionTest, ConnectStatus504) {
1317 ConnectStatusHelper(MockRead("HTTP/1.1 504 Gateway Timeout\r\n"));
1318}
1319
1320TEST_F(HttpNetworkTransactionTest, ConnectStatus505) {
1321 ConnectStatusHelper(MockRead("HTTP/1.1 505 HTTP Version Not Supported\r\n"));
1322}
1323
[email protected]038e9a32008-10-08 22:40:161324// Test the flow when both the proxy server AND origin server require
1325// authentication. Again, this uses basic auth for both since that is
1326// the simplest to mock.
1327TEST_F(HttpNetworkTransactionTest, BasicAuthProxyThenServer) {
[email protected]228ff742009-06-05 01:19:591328 SessionDependencies session_deps(CreateFixedProxyService("myproxy:70"));
[email protected]db8f44c2008-12-13 04:52:011329
[email protected]038e9a32008-10-08 22:40:161330 // Configure against proxy server "myproxy:70".
[email protected]1c773ea12009-04-28 19:58:421331 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(
[email protected]228ff742009-06-05 01:19:591332 CreateSession(&session_deps),
1333 &session_deps.socket_factory));
[email protected]038e9a32008-10-08 22:40:161334
[email protected]1c773ea12009-04-28 19:58:421335 HttpRequestInfo request;
[email protected]038e9a32008-10-08 22:40:161336 request.method = "GET";
1337 request.url = GURL("http://www.google.com/");
1338 request.load_flags = 0;
1339
[email protected]f9ee6b52008-11-08 06:46:231340 MockWrite data_writes1[] = {
1341 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
1342 "Host: www.google.com\r\n"
1343 "Proxy-Connection: keep-alive\r\n\r\n"),
1344 };
1345
[email protected]038e9a32008-10-08 22:40:161346 MockRead data_reads1[] = {
1347 MockRead("HTTP/1.0 407 Unauthorized\r\n"),
1348 // Give a couple authenticate options (only the middle one is actually
1349 // supported).
[email protected]aaead502008-10-15 00:20:111350 MockRead("Proxy-Authenticate: Basic\r\n"), // Malformed
[email protected]038e9a32008-10-08 22:40:161351 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1352 MockRead("Proxy-Authenticate: UNSUPPORTED realm=\"FOO\"\r\n"),
1353 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1354 // Large content-length -- won't matter, as connection will be reset.
1355 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:421356 MockRead(false, ERR_FAILED),
[email protected]038e9a32008-10-08 22:40:161357 };
1358
1359 // After calling trans->RestartWithAuth() the first time, this is the
1360 // request we should be issuing -- the final header line contains the
1361 // proxy's credentials.
1362 MockWrite data_writes2[] = {
1363 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
1364 "Host: www.google.com\r\n"
1365 "Proxy-Connection: keep-alive\r\n"
1366 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
1367 };
1368
1369 // Now the proxy server lets the request pass through to origin server.
1370 // The origin server responds with a 401.
1371 MockRead data_reads2[] = {
1372 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
1373 // Note: We are using the same realm-name as the proxy server. This is
1374 // completely valid, as realms are unique across hosts.
1375 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1376 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1377 MockRead("Content-Length: 2000\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:421378 MockRead(false, ERR_FAILED), // Won't be reached.
[email protected]038e9a32008-10-08 22:40:161379 };
1380
1381 // After calling trans->RestartWithAuth() the second time, we should send
1382 // the credentials for both the proxy and origin server.
1383 MockWrite data_writes3[] = {
1384 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
1385 "Host: www.google.com\r\n"
1386 "Proxy-Connection: keep-alive\r\n"
1387 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n"
1388 "Authorization: Basic Zm9vMjpiYXIy\r\n\r\n"),
1389 };
1390
1391 // Lastly we get the desired content.
1392 MockRead data_reads3[] = {
1393 MockRead("HTTP/1.0 200 OK\r\n"),
1394 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1395 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:421396 MockRead(false, OK),
[email protected]038e9a32008-10-08 22:40:161397 };
1398
[email protected]69b43fe2009-06-15 09:47:371399 StaticMockSocket data1(data_reads1, data_writes1);
1400 StaticMockSocket data2(data_reads2, data_writes2);
1401 StaticMockSocket data3(data_reads3, data_writes3);
[email protected]228ff742009-06-05 01:19:591402 session_deps.socket_factory.AddMockSocket(&data1);
1403 session_deps.socket_factory.AddMockSocket(&data2);
1404 session_deps.socket_factory.AddMockSocket(&data3);
[email protected]038e9a32008-10-08 22:40:161405
1406 TestCompletionCallback callback1;
1407
1408 int rv = trans->Start(&request, &callback1);
[email protected]1c773ea12009-04-28 19:58:421409 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]038e9a32008-10-08 22:40:161410
1411 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421412 EXPECT_EQ(OK, rv);
[email protected]038e9a32008-10-08 22:40:161413
[email protected]1c773ea12009-04-28 19:58:421414 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]038e9a32008-10-08 22:40:161415 EXPECT_FALSE(response == NULL);
1416
1417 // The password prompt info should have been set in response->auth_challenge.
1418 EXPECT_FALSE(response->auth_challenge.get() == NULL);
1419
[email protected]71e4573a2009-05-21 22:03:001420 EXPECT_EQ(L"myproxy:70", response->auth_challenge->host_and_port);
[email protected]038e9a32008-10-08 22:40:161421 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
1422 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
1423
1424 TestCompletionCallback callback2;
1425
1426 rv = trans->RestartWithAuth(L"foo", L"bar", &callback2);
[email protected]1c773ea12009-04-28 19:58:421427 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]038e9a32008-10-08 22:40:161428
1429 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421430 EXPECT_EQ(OK, rv);
[email protected]038e9a32008-10-08 22:40:161431
1432 response = trans->GetResponseInfo();
1433 EXPECT_FALSE(response == NULL);
1434 EXPECT_FALSE(response->auth_challenge.get() == NULL);
1435
[email protected]71e4573a2009-05-21 22:03:001436 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
[email protected]038e9a32008-10-08 22:40:161437 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
1438 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
1439
1440 TestCompletionCallback callback3;
1441
1442 rv = trans->RestartWithAuth(L"foo2", L"bar2", &callback3);
[email protected]1c773ea12009-04-28 19:58:421443 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]038e9a32008-10-08 22:40:161444
1445 rv = callback3.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421446 EXPECT_EQ(OK, rv);
[email protected]038e9a32008-10-08 22:40:161447
1448 response = trans->GetResponseInfo();
1449 EXPECT_TRUE(response->auth_challenge.get() == NULL);
1450 EXPECT_EQ(100, response->headers->GetContentLength());
[email protected]038e9a32008-10-08 22:40:161451}
[email protected]4ddaf2502008-10-23 18:26:191452
[email protected]385a4672009-03-11 22:21:291453// The NTLM authentication unit tests were generated by capturing the HTTP
1454// requests and responses using Fiddler 2 and inspecting the generated random
1455// bytes in the debugger.
1456
1457// Enter the correct password and authenticate successfully.
1458TEST_F(HttpNetworkTransactionTest, NTLMAuth1) {
[email protected]1c773ea12009-04-28 19:58:421459 HttpAuthHandlerNTLM::ScopedProcSetter proc_setter(MockGenerateRandom1,
[email protected]fe2bc6a2009-03-23 16:52:201460 MockGetHostName);
[email protected]228ff742009-06-05 01:19:591461 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:401462 scoped_ptr<HttpTransaction> trans(
1463 new HttpNetworkTransaction(
[email protected]228ff742009-06-05 01:19:591464 CreateSession(&session_deps),
1465 &session_deps.socket_factory));
[email protected]3f918782009-02-28 01:29:241466
[email protected]1c773ea12009-04-28 19:58:421467 HttpRequestInfo request;
[email protected]3f918782009-02-28 01:29:241468 request.method = "GET";
1469 request.url = GURL("http://172.22.68.17/kids/login.aspx");
1470 request.load_flags = 0;
1471
1472 MockWrite data_writes1[] = {
1473 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
1474 "Host: 172.22.68.17\r\n"
1475 "Connection: keep-alive\r\n\r\n"),
1476 };
1477
1478 MockRead data_reads1[] = {
1479 MockRead("HTTP/1.1 401 Access Denied\r\n"),
1480 // Negotiate and NTLM are often requested together. We only support NTLM.
1481 MockRead("WWW-Authenticate: Negotiate\r\n"),
1482 MockRead("WWW-Authenticate: NTLM\r\n"),
1483 MockRead("Connection: close\r\n"),
1484 MockRead("Content-Length: 42\r\n"),
[email protected]076c85082009-04-10 23:21:361485 MockRead("Content-Type: text/html\r\n\r\n"),
[email protected]3f918782009-02-28 01:29:241486 // Missing content -- won't matter, as connection will be reset.
[email protected]1c773ea12009-04-28 19:58:421487 MockRead(false, ERR_UNEXPECTED),
[email protected]3f918782009-02-28 01:29:241488 };
1489
1490 MockWrite data_writes2[] = {
[email protected]0757e7702009-03-27 04:00:221491 // After restarting with a null identity, this is the
[email protected]3f918782009-02-28 01:29:241492 // request we should be issuing -- the final header line contains a Type
1493 // 1 message.
1494 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
1495 "Host: 172.22.68.17\r\n"
1496 "Connection: keep-alive\r\n"
1497 "Authorization: NTLM "
1498 "TlRMTVNTUAABAAAAB4IIAAAAAAAAAAAAAAAAAAAAAAA=\r\n\r\n"),
1499
1500 // After calling trans->RestartWithAuth(), we should send a Type 3 message
1501 // (the credentials for the origin server). The second request continues
1502 // on the same connection.
1503 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
1504 "Host: 172.22.68.17\r\n"
1505 "Connection: keep-alive\r\n"
[email protected]385a4672009-03-11 22:21:291506 "Authorization: NTLM TlRMTVNTUAADAAAAGAAYAGgAAAAYABgAgA"
1507 "AAAAAAAABAAAAAGAAYAEAAAAAQABAAWAAAAAAAAAAAAAAABYIIAHQA"
1508 "ZQBzAHQAaQBuAGcALQBuAHQAbABtAFcAVABDAC0AVwBJAE4ANwBVKW"
1509 "Yma5xzVAAAAAAAAAAAAAAAAAAAAACH+gWcm+YsP9Tqb9zCR3WAeZZX"
1510 "ahlhx5I=\r\n\r\n"),
[email protected]3f918782009-02-28 01:29:241511 };
1512
1513 MockRead data_reads2[] = {
1514 // The origin server responds with a Type 2 message.
1515 MockRead("HTTP/1.1 401 Access Denied\r\n"),
1516 MockRead("WWW-Authenticate: NTLM "
[email protected]385a4672009-03-11 22:21:291517 "TlRMTVNTUAACAAAADAAMADgAAAAFgokCjGpMpPGlYKkAAAAAAAAAALo"
[email protected]3f918782009-02-28 01:29:241518 "AugBEAAAABQEoCgAAAA9HAE8ATwBHAEwARQACAAwARwBPAE8ARwBMAE"
1519 "UAAQAaAEEASwBFAEUAUwBBAFIAQQAtAEMATwBSAFAABAAeAGMAbwByA"
1520 "HAALgBnAG8AbwBnAGwAZQAuAGMAbwBtAAMAQABhAGsAZQBlAHMAYQBy"
1521 "AGEALQBjAG8AcgBwAC4AYQBkAC4AYwBvAHIAcAAuAGcAbwBvAGcAbAB"
1522 "lAC4AYwBvAG0ABQAeAGMAbwByAHAALgBnAG8AbwBnAGwAZQAuAGMAbw"
1523 "BtAAAAAAA=\r\n"),
1524 MockRead("Content-Length: 42\r\n"),
[email protected]076c85082009-04-10 23:21:361525 MockRead("Content-Type: text/html\r\n\r\n"),
[email protected]3f918782009-02-28 01:29:241526 MockRead("You are not authorized to view this page\r\n"),
1527
1528 // Lastly we get the desired content.
1529 MockRead("HTTP/1.1 200 OK\r\n"),
1530 MockRead("Content-Type: text/html; charset=utf-8\r\n"),
1531 MockRead("Content-Length: 13\r\n\r\n"),
1532 MockRead("Please Login\r\n"),
[email protected]1c773ea12009-04-28 19:58:421533 MockRead(false, OK),
[email protected]3f918782009-02-28 01:29:241534 };
1535
[email protected]69b43fe2009-06-15 09:47:371536 StaticMockSocket data1(data_reads1, data_writes1);
1537 StaticMockSocket data2(data_reads2, data_writes2);
[email protected]228ff742009-06-05 01:19:591538 session_deps.socket_factory.AddMockSocket(&data1);
1539 session_deps.socket_factory.AddMockSocket(&data2);
[email protected]3f918782009-02-28 01:29:241540
1541 TestCompletionCallback callback1;
1542
1543 int rv = trans->Start(&request, &callback1);
[email protected]1c773ea12009-04-28 19:58:421544 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]3f918782009-02-28 01:29:241545
1546 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421547 EXPECT_EQ(OK, rv);
[email protected]3f918782009-02-28 01:29:241548
[email protected]0757e7702009-03-27 04:00:221549 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
1550 TestCompletionCallback callback2;
1551 rv = trans->RestartWithAuth(std::wstring(), std::wstring(), &callback2);
[email protected]1c773ea12009-04-28 19:58:421552 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]0757e7702009-03-27 04:00:221553 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421554 EXPECT_EQ(OK, rv);
[email protected]0757e7702009-03-27 04:00:221555 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
1556
[email protected]1c773ea12009-04-28 19:58:421557 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]3f918782009-02-28 01:29:241558 EXPECT_FALSE(response == NULL);
1559
1560 // The password prompt info should have been set in response->auth_challenge.
1561 EXPECT_FALSE(response->auth_challenge.get() == NULL);
1562
[email protected]71e4573a2009-05-21 22:03:001563 EXPECT_EQ(L"172.22.68.17:80", response->auth_challenge->host_and_port);
[email protected]3f918782009-02-28 01:29:241564 EXPECT_EQ(L"", response->auth_challenge->realm);
1565 EXPECT_EQ(L"ntlm", response->auth_challenge->scheme);
1566
[email protected]0757e7702009-03-27 04:00:221567 TestCompletionCallback callback3;
[email protected]3f918782009-02-28 01:29:241568
[email protected]0757e7702009-03-27 04:00:221569 rv = trans->RestartWithAuth(L"testing-ntlm", L"testing-ntlm", &callback3);
[email protected]1c773ea12009-04-28 19:58:421570 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]3f918782009-02-28 01:29:241571
[email protected]0757e7702009-03-27 04:00:221572 rv = callback3.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421573 EXPECT_EQ(OK, rv);
[email protected]3f918782009-02-28 01:29:241574
1575 response = trans->GetResponseInfo();
1576 EXPECT_TRUE(response->auth_challenge.get() == NULL);
1577 EXPECT_EQ(13, response->headers->GetContentLength());
1578}
1579
[email protected]385a4672009-03-11 22:21:291580// Enter a wrong password, and then the correct one.
1581TEST_F(HttpNetworkTransactionTest, NTLMAuth2) {
[email protected]1c773ea12009-04-28 19:58:421582 HttpAuthHandlerNTLM::ScopedProcSetter proc_setter(MockGenerateRandom2,
[email protected]fe2bc6a2009-03-23 16:52:201583 MockGetHostName);
[email protected]228ff742009-06-05 01:19:591584 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:401585 scoped_ptr<HttpTransaction> trans(
1586 new HttpNetworkTransaction(
[email protected]228ff742009-06-05 01:19:591587 CreateSession(&session_deps),
1588 &session_deps.socket_factory));
[email protected]385a4672009-03-11 22:21:291589
[email protected]1c773ea12009-04-28 19:58:421590 HttpRequestInfo request;
[email protected]385a4672009-03-11 22:21:291591 request.method = "GET";
1592 request.url = GURL("http://172.22.68.17/kids/login.aspx");
1593 request.load_flags = 0;
1594
1595 MockWrite data_writes1[] = {
1596 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
1597 "Host: 172.22.68.17\r\n"
1598 "Connection: keep-alive\r\n\r\n"),
1599 };
1600
1601 MockRead data_reads1[] = {
1602 MockRead("HTTP/1.1 401 Access Denied\r\n"),
1603 // Negotiate and NTLM are often requested together. We only support NTLM.
1604 MockRead("WWW-Authenticate: Negotiate\r\n"),
1605 MockRead("WWW-Authenticate: NTLM\r\n"),
1606 MockRead("Connection: close\r\n"),
1607 MockRead("Content-Length: 42\r\n"),
[email protected]076c85082009-04-10 23:21:361608 MockRead("Content-Type: text/html\r\n\r\n"),
[email protected]385a4672009-03-11 22:21:291609 // Missing content -- won't matter, as connection will be reset.
[email protected]1c773ea12009-04-28 19:58:421610 MockRead(false, ERR_UNEXPECTED),
[email protected]385a4672009-03-11 22:21:291611 };
1612
1613 MockWrite data_writes2[] = {
[email protected]0757e7702009-03-27 04:00:221614 // After restarting with a null identity, this is the
[email protected]385a4672009-03-11 22:21:291615 // request we should be issuing -- the final header line contains a Type
1616 // 1 message.
1617 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
1618 "Host: 172.22.68.17\r\n"
1619 "Connection: keep-alive\r\n"
1620 "Authorization: NTLM "
1621 "TlRMTVNTUAABAAAAB4IIAAAAAAAAAAAAAAAAAAAAAAA=\r\n\r\n"),
1622
1623 // After calling trans->RestartWithAuth(), we should send a Type 3 message
1624 // (the credentials for the origin server). The second request continues
1625 // on the same connection.
1626 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
1627 "Host: 172.22.68.17\r\n"
1628 "Connection: keep-alive\r\n"
1629 "Authorization: NTLM TlRMTVNTUAADAAAAGAAYAGgAAAAYABgAgA"
1630 "AAAAAAAABAAAAAGAAYAEAAAAAQABAAWAAAAAAAAAAAAAAABYIIAHQA"
1631 "ZQBzAHQAaQBuAGcALQBuAHQAbABtAFcAVABDAC0AVwBJAE4ANwCWeY"
1632 "XnSZNwoQAAAAAAAAAAAAAAAAAAAADLa34/phTTKzNTWdub+uyFleOj"
1633 "4Ww7b7E=\r\n\r\n"),
1634 };
1635
1636 MockRead data_reads2[] = {
1637 // The origin server responds with a Type 2 message.
1638 MockRead("HTTP/1.1 401 Access Denied\r\n"),
1639 MockRead("WWW-Authenticate: NTLM "
1640 "TlRMTVNTUAACAAAADAAMADgAAAAFgokCbVWUZezVGpAAAAAAAAAAALo"
1641 "AugBEAAAABQEoCgAAAA9HAE8ATwBHAEwARQACAAwARwBPAE8ARwBMAE"
1642 "UAAQAaAEEASwBFAEUAUwBBAFIAQQAtAEMATwBSAFAABAAeAGMAbwByA"
1643 "HAALgBnAG8AbwBnAGwAZQAuAGMAbwBtAAMAQABhAGsAZQBlAHMAYQBy"
1644 "AGEALQBjAG8AcgBwAC4AYQBkAC4AYwBvAHIAcAAuAGcAbwBvAGcAbAB"
1645 "lAC4AYwBvAG0ABQAeAGMAbwByAHAALgBnAG8AbwBnAGwAZQAuAGMAbw"
1646 "BtAAAAAAA=\r\n"),
1647 MockRead("Content-Length: 42\r\n"),
[email protected]076c85082009-04-10 23:21:361648 MockRead("Content-Type: text/html\r\n\r\n"),
[email protected]385a4672009-03-11 22:21:291649 MockRead("You are not authorized to view this page\r\n"),
1650
1651 // Wrong password.
1652 MockRead("HTTP/1.1 401 Access Denied\r\n"),
1653 MockRead("WWW-Authenticate: Negotiate\r\n"),
1654 MockRead("WWW-Authenticate: NTLM\r\n"),
1655 MockRead("Connection: close\r\n"),
1656 MockRead("Content-Length: 42\r\n"),
[email protected]076c85082009-04-10 23:21:361657 MockRead("Content-Type: text/html\r\n\r\n"),
[email protected]385a4672009-03-11 22:21:291658 // Missing content -- won't matter, as connection will be reset.
[email protected]1c773ea12009-04-28 19:58:421659 MockRead(false, ERR_UNEXPECTED),
[email protected]385a4672009-03-11 22:21:291660 };
1661
1662 MockWrite data_writes3[] = {
[email protected]0757e7702009-03-27 04:00:221663 // After restarting with a null identity, this is the
[email protected]385a4672009-03-11 22:21:291664 // request we should be issuing -- the final header line contains a Type
1665 // 1 message.
1666 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
1667 "Host: 172.22.68.17\r\n"
1668 "Connection: keep-alive\r\n"
1669 "Authorization: NTLM "
1670 "TlRMTVNTUAABAAAAB4IIAAAAAAAAAAAAAAAAAAAAAAA=\r\n\r\n"),
1671
1672 // After calling trans->RestartWithAuth(), we should send a Type 3 message
1673 // (the credentials for the origin server). The second request continues
1674 // on the same connection.
1675 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
1676 "Host: 172.22.68.17\r\n"
1677 "Connection: keep-alive\r\n"
1678 "Authorization: NTLM TlRMTVNTUAADAAAAGAAYAGgAAAAYABgAgA"
1679 "AAAAAAAABAAAAAGAAYAEAAAAAQABAAWAAAAAAAAAAAAAAABYIIAHQA"
1680 "ZQBzAHQAaQBuAGcALQBuAHQAbABtAFcAVABDAC0AVwBJAE4ANwBO54"
1681 "dFMVvTHwAAAAAAAAAAAAAAAAAAAACS7sT6Uzw7L0L//WUqlIaVWpbI"
1682 "+4MUm7c=\r\n\r\n"),
1683 };
1684
1685 MockRead data_reads3[] = {
1686 // The origin server responds with a Type 2 message.
1687 MockRead("HTTP/1.1 401 Access Denied\r\n"),
1688 MockRead("WWW-Authenticate: NTLM "
1689 "TlRMTVNTUAACAAAADAAMADgAAAAFgokCL24VN8dgOR8AAAAAAAAAALo"
1690 "AugBEAAAABQEoCgAAAA9HAE8ATwBHAEwARQACAAwARwBPAE8ARwBMAE"
1691 "UAAQAaAEEASwBFAEUAUwBBAFIAQQAtAEMATwBSAFAABAAeAGMAbwByA"
1692 "HAALgBnAG8AbwBnAGwAZQAuAGMAbwBtAAMAQABhAGsAZQBlAHMAYQBy"
1693 "AGEALQBjAG8AcgBwAC4AYQBkAC4AYwBvAHIAcAAuAGcAbwBvAGcAbAB"
1694 "lAC4AYwBvAG0ABQAeAGMAbwByAHAALgBnAG8AbwBnAGwAZQAuAGMAbw"
1695 "BtAAAAAAA=\r\n"),
1696 MockRead("Content-Length: 42\r\n"),
[email protected]076c85082009-04-10 23:21:361697 MockRead("Content-Type: text/html\r\n\r\n"),
[email protected]385a4672009-03-11 22:21:291698 MockRead("You are not authorized to view this page\r\n"),
1699
1700 // Lastly we get the desired content.
1701 MockRead("HTTP/1.1 200 OK\r\n"),
1702 MockRead("Content-Type: text/html; charset=utf-8\r\n"),
1703 MockRead("Content-Length: 13\r\n\r\n"),
1704 MockRead("Please Login\r\n"),
[email protected]1c773ea12009-04-28 19:58:421705 MockRead(false, OK),
[email protected]385a4672009-03-11 22:21:291706 };
1707
[email protected]69b43fe2009-06-15 09:47:371708 StaticMockSocket data1(data_reads1, data_writes1);
1709 StaticMockSocket data2(data_reads2, data_writes2);
1710 StaticMockSocket data3(data_reads3, data_writes3);
[email protected]228ff742009-06-05 01:19:591711 session_deps.socket_factory.AddMockSocket(&data1);
1712 session_deps.socket_factory.AddMockSocket(&data2);
1713 session_deps.socket_factory.AddMockSocket(&data3);
[email protected]385a4672009-03-11 22:21:291714
1715 TestCompletionCallback callback1;
1716
1717 int rv = trans->Start(&request, &callback1);
[email protected]1c773ea12009-04-28 19:58:421718 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]385a4672009-03-11 22:21:291719
1720 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421721 EXPECT_EQ(OK, rv);
[email protected]385a4672009-03-11 22:21:291722
[email protected]0757e7702009-03-27 04:00:221723 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
[email protected]385a4672009-03-11 22:21:291724 TestCompletionCallback callback2;
[email protected]0757e7702009-03-27 04:00:221725 rv = trans->RestartWithAuth(std::wstring(), std::wstring(), &callback2);
[email protected]1c773ea12009-04-28 19:58:421726 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]385a4672009-03-11 22:21:291727 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421728 EXPECT_EQ(OK, rv);
[email protected]0757e7702009-03-27 04:00:221729 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
[email protected]385a4672009-03-11 22:21:291730
[email protected]1c773ea12009-04-28 19:58:421731 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]385a4672009-03-11 22:21:291732 EXPECT_FALSE(response == NULL);
1733
1734 // The password prompt info should have been set in response->auth_challenge.
1735 EXPECT_FALSE(response->auth_challenge.get() == NULL);
1736
[email protected]71e4573a2009-05-21 22:03:001737 EXPECT_EQ(L"172.22.68.17:80", response->auth_challenge->host_and_port);
[email protected]385a4672009-03-11 22:21:291738 EXPECT_EQ(L"", response->auth_challenge->realm);
1739 EXPECT_EQ(L"ntlm", response->auth_challenge->scheme);
1740
1741 TestCompletionCallback callback3;
1742
[email protected]0757e7702009-03-27 04:00:221743 // Enter the wrong password.
1744 rv = trans->RestartWithAuth(L"testing-ntlm", L"wrongpassword", &callback3);
[email protected]1c773ea12009-04-28 19:58:421745 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]385a4672009-03-11 22:21:291746
1747 rv = callback3.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421748 EXPECT_EQ(OK, rv);
[email protected]385a4672009-03-11 22:21:291749
[email protected]0757e7702009-03-27 04:00:221750 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
1751 TestCompletionCallback callback4;
1752 rv = trans->RestartWithAuth(std::wstring(), std::wstring(), &callback4);
[email protected]1c773ea12009-04-28 19:58:421753 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]0757e7702009-03-27 04:00:221754 rv = callback4.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421755 EXPECT_EQ(OK, rv);
[email protected]0757e7702009-03-27 04:00:221756 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
1757
1758 response = trans->GetResponseInfo();
1759 EXPECT_FALSE(response == NULL);
1760
1761 // The password prompt info should have been set in response->auth_challenge.
1762 EXPECT_FALSE(response->auth_challenge.get() == NULL);
1763
[email protected]71e4573a2009-05-21 22:03:001764 EXPECT_EQ(L"172.22.68.17:80", response->auth_challenge->host_and_port);
[email protected]0757e7702009-03-27 04:00:221765 EXPECT_EQ(L"", response->auth_challenge->realm);
1766 EXPECT_EQ(L"ntlm", response->auth_challenge->scheme);
1767
1768 TestCompletionCallback callback5;
1769
1770 // Now enter the right password.
1771 rv = trans->RestartWithAuth(L"testing-ntlm", L"testing-ntlm", &callback5);
[email protected]1c773ea12009-04-28 19:58:421772 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]0757e7702009-03-27 04:00:221773
1774 rv = callback5.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421775 EXPECT_EQ(OK, rv);
[email protected]0757e7702009-03-27 04:00:221776
[email protected]385a4672009-03-11 22:21:291777 response = trans->GetResponseInfo();
1778 EXPECT_TRUE(response->auth_challenge.get() == NULL);
1779 EXPECT_EQ(13, response->headers->GetContentLength());
1780}
1781
[email protected]4ddaf2502008-10-23 18:26:191782// Test reading a server response which has only headers, and no body.
1783// After some maximum number of bytes is consumed, the transaction should
1784// fail with ERR_RESPONSE_HEADERS_TOO_BIG.
1785TEST_F(HttpNetworkTransactionTest, LargeHeadersNoBody) {
[email protected]228ff742009-06-05 01:19:591786 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:401787 scoped_ptr<HttpTransaction> trans(
1788 new HttpNetworkTransaction(
[email protected]228ff742009-06-05 01:19:591789 CreateSession(&session_deps),
1790 &session_deps.socket_factory));
[email protected]4ddaf2502008-10-23 18:26:191791
[email protected]1c773ea12009-04-28 19:58:421792 HttpRequestInfo request;
[email protected]4ddaf2502008-10-23 18:26:191793 request.method = "GET";
1794 request.url = GURL("http://www.google.com/");
1795 request.load_flags = 0;
1796
1797 // Respond with 50 kb of headers (we should fail after 32 kb).
[email protected]15a5ccf82008-10-23 19:57:431798 std::string large_headers_string;
1799 FillLargeHeadersString(&large_headers_string, 50 * 1024);
[email protected]4ddaf2502008-10-23 18:26:191800
1801 MockRead data_reads[] = {
1802 MockRead("HTTP/1.0 200 OK\r\n"),
[email protected]15a5ccf82008-10-23 19:57:431803 MockRead(true, large_headers_string.data(), large_headers_string.size()),
[email protected]4ddaf2502008-10-23 18:26:191804 MockRead("\r\nBODY"),
[email protected]1c773ea12009-04-28 19:58:421805 MockRead(false, OK),
[email protected]4ddaf2502008-10-23 18:26:191806 };
[email protected]69b43fe2009-06-15 09:47:371807 StaticMockSocket data(data_reads, NULL);
[email protected]228ff742009-06-05 01:19:591808 session_deps.socket_factory.AddMockSocket(&data);
[email protected]4ddaf2502008-10-23 18:26:191809
1810 TestCompletionCallback callback;
1811
1812 int rv = trans->Start(&request, &callback);
[email protected]1c773ea12009-04-28 19:58:421813 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]4ddaf2502008-10-23 18:26:191814
1815 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421816 EXPECT_EQ(ERR_RESPONSE_HEADERS_TOO_BIG, rv);
[email protected]4ddaf2502008-10-23 18:26:191817
[email protected]1c773ea12009-04-28 19:58:421818 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]4ddaf2502008-10-23 18:26:191819 EXPECT_TRUE(response == NULL);
1820}
[email protected]f4e426b2008-11-05 00:24:491821
1822// Make sure that we don't try to reuse a TCPClientSocket when failing to
1823// establish tunnel.
1824// http://code.google.com/p/chromium/issues/detail?id=3772
1825TEST_F(HttpNetworkTransactionTest, DontRecycleTCPSocketForSSLTunnel) {
1826 // Configure against proxy server "myproxy:70".
[email protected]228ff742009-06-05 01:19:591827 SessionDependencies session_deps(CreateFixedProxyService("myproxy:70"));
[email protected]db8f44c2008-12-13 04:52:011828
[email protected]228ff742009-06-05 01:19:591829 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]f4e426b2008-11-05 00:24:491830
[email protected]1c773ea12009-04-28 19:58:421831 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(
[email protected]228ff742009-06-05 01:19:591832 session.get(), &session_deps.socket_factory));
[email protected]f4e426b2008-11-05 00:24:491833
[email protected]1c773ea12009-04-28 19:58:421834 HttpRequestInfo request;
[email protected]f4e426b2008-11-05 00:24:491835 request.method = "GET";
1836 request.url = GURL("https://www.google.com/");
1837 request.load_flags = 0;
1838
1839 // Since we have proxy, should try to establish tunnel.
1840 MockWrite data_writes1[] = {
1841 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
[email protected]e44de5d2009-06-05 20:12:451842 "Host: www.google.com\r\n"
1843 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]f4e426b2008-11-05 00:24:491844 };
1845
[email protected]77848d12008-11-14 00:00:221846 // The proxy responds to the connect with a 404, using a persistent
[email protected]f4e426b2008-11-05 00:24:491847 // connection. Usually a proxy would return 501 (not implemented),
1848 // or 200 (tunnel established).
1849 MockRead data_reads1[] = {
1850 MockRead("HTTP/1.1 404 Not Found\r\n"),
1851 MockRead("Content-Length: 10\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:421852 MockRead(false, ERR_UNEXPECTED), // Should not be reached.
[email protected]f4e426b2008-11-05 00:24:491853 };
1854
[email protected]69b43fe2009-06-15 09:47:371855 StaticMockSocket data1(data_reads1, data_writes1);
[email protected]228ff742009-06-05 01:19:591856 session_deps.socket_factory.AddMockSocket(&data1);
[email protected]f4e426b2008-11-05 00:24:491857
1858 TestCompletionCallback callback1;
1859
1860 int rv = trans->Start(&request, &callback1);
[email protected]1c773ea12009-04-28 19:58:421861 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f4e426b2008-11-05 00:24:491862
1863 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421864 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED, rv);
[email protected]f4e426b2008-11-05 00:24:491865
[email protected]1c773ea12009-04-28 19:58:421866 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]c744cf22009-02-27 07:28:081867 EXPECT_TRUE(response == NULL);
[email protected]f4e426b2008-11-05 00:24:491868
[email protected]b4404c02009-04-10 16:38:521869 // Empty the current queue. This is necessary because idle sockets are
1870 // added to the connection pool asynchronously with a PostTask.
1871 MessageLoop::current()->RunAllPending();
1872
[email protected]f4e426b2008-11-05 00:24:491873 // We now check to make sure the TCPClientSocket was not added back to
1874 // the pool.
[email protected]df0c05c62009-06-17 15:50:581875 EXPECT_EQ(0, session->connection_pool()->IdleSocketCount());
[email protected]f4e426b2008-11-05 00:24:491876 trans.reset();
[email protected]b4404c02009-04-10 16:38:521877 MessageLoop::current()->RunAllPending();
[email protected]f4e426b2008-11-05 00:24:491878 // Make sure that the socket didn't get recycled after calling the destructor.
[email protected]df0c05c62009-06-17 15:50:581879 EXPECT_EQ(0, session->connection_pool()->IdleSocketCount());
[email protected]f4e426b2008-11-05 00:24:491880}
[email protected]372d34a2008-11-05 21:30:511881
[email protected]1b157c02009-04-21 01:55:401882// Make sure that we recycle a socket after reading all of the response body.
1883TEST_F(HttpNetworkTransactionTest, RecycleSocket) {
[email protected]228ff742009-06-05 01:19:591884 SessionDependencies session_deps;
1885 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]1b157c02009-04-21 01:55:401886
[email protected]1c773ea12009-04-28 19:58:421887 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(
[email protected]228ff742009-06-05 01:19:591888 session.get(), &session_deps.socket_factory));
[email protected]1b157c02009-04-21 01:55:401889
[email protected]1c773ea12009-04-28 19:58:421890 HttpRequestInfo request;
[email protected]1b157c02009-04-21 01:55:401891 request.method = "GET";
1892 request.url = GURL("http://www.google.com/");
1893 request.load_flags = 0;
1894
1895 MockRead data_reads[] = {
1896 // A part of the response body is received with the response headers.
1897 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 11\r\n\r\nhel"),
1898 // The rest of the response body is received in two parts.
1899 MockRead("lo"),
1900 MockRead(" world"),
1901 MockRead("junk"), // Should not be read!!
[email protected]1c773ea12009-04-28 19:58:421902 MockRead(false, OK),
[email protected]1b157c02009-04-21 01:55:401903 };
1904
[email protected]69b43fe2009-06-15 09:47:371905 StaticMockSocket data(data_reads, NULL);
[email protected]228ff742009-06-05 01:19:591906 session_deps.socket_factory.AddMockSocket(&data);
[email protected]1b157c02009-04-21 01:55:401907
1908 TestCompletionCallback callback;
1909
1910 int rv = trans->Start(&request, &callback);
[email protected]1c773ea12009-04-28 19:58:421911 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]1b157c02009-04-21 01:55:401912
1913 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421914 EXPECT_EQ(OK, rv);
[email protected]1b157c02009-04-21 01:55:401915
[email protected]1c773ea12009-04-28 19:58:421916 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]1b157c02009-04-21 01:55:401917 EXPECT_TRUE(response != NULL);
1918
1919 EXPECT_TRUE(response->headers != NULL);
1920 std::string status_line = response->headers->GetStatusLine();
1921 EXPECT_EQ("HTTP/1.1 200 OK", status_line);
1922
[email protected]df0c05c62009-06-17 15:50:581923 EXPECT_EQ(0, session->connection_pool()->IdleSocketCount());
[email protected]1b157c02009-04-21 01:55:401924
1925 std::string response_data;
1926 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:421927 EXPECT_EQ(OK, rv);
[email protected]1b157c02009-04-21 01:55:401928 EXPECT_EQ("hello world", response_data);
1929
1930 // Empty the current queue. This is necessary because idle sockets are
1931 // added to the connection pool asynchronously with a PostTask.
1932 MessageLoop::current()->RunAllPending();
1933
1934 // We now check to make sure the socket was added back to the pool.
[email protected]df0c05c62009-06-17 15:50:581935 EXPECT_EQ(1, session->connection_pool()->IdleSocketCount());
[email protected]1b157c02009-04-21 01:55:401936}
1937
[email protected]b4404c02009-04-10 16:38:521938// Make sure that we recycle a socket after a zero-length response.
1939// http://crbug.com/9880
1940TEST_F(HttpNetworkTransactionTest, RecycleSocketAfterZeroContentLength) {
[email protected]228ff742009-06-05 01:19:591941 SessionDependencies session_deps;
1942 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]b4404c02009-04-10 16:38:521943
[email protected]1c773ea12009-04-28 19:58:421944 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(
[email protected]228ff742009-06-05 01:19:591945 session.get(), &session_deps.socket_factory));
[email protected]b4404c02009-04-10 16:38:521946
[email protected]1c773ea12009-04-28 19:58:421947 HttpRequestInfo request;
[email protected]b4404c02009-04-10 16:38:521948 request.method = "GET";
1949 request.url = GURL("http://www.google.com/csi?v=3&s=web&action=&"
1950 "tran=undefined&ei=mAXcSeegAo-SMurloeUN&"
1951 "e=17259,18167,19592,19773,19981,20133,20173,20233&"
1952 "rt=prt.2642,ol.2649,xjs.2951");
1953 request.load_flags = 0;
1954
1955 MockRead data_reads[] = {
1956 MockRead("HTTP/1.1 204 No Content\r\n"
1957 "Content-Length: 0\r\n"
1958 "Content-Type: text/html\r\n\r\n"),
1959 MockRead("junk"), // Should not be read!!
[email protected]1c773ea12009-04-28 19:58:421960 MockRead(false, OK),
[email protected]b4404c02009-04-10 16:38:521961 };
1962
[email protected]69b43fe2009-06-15 09:47:371963 StaticMockSocket data(data_reads, NULL);
[email protected]228ff742009-06-05 01:19:591964 session_deps.socket_factory.AddMockSocket(&data);
[email protected]b4404c02009-04-10 16:38:521965
1966 TestCompletionCallback callback;
1967
1968 int rv = trans->Start(&request, &callback);
[email protected]1c773ea12009-04-28 19:58:421969 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]b4404c02009-04-10 16:38:521970
1971 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421972 EXPECT_EQ(OK, rv);
[email protected]b4404c02009-04-10 16:38:521973
[email protected]1c773ea12009-04-28 19:58:421974 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]b4404c02009-04-10 16:38:521975 EXPECT_TRUE(response != NULL);
1976
1977 EXPECT_TRUE(response->headers != NULL);
1978 std::string status_line = response->headers->GetStatusLine();
1979 EXPECT_EQ("HTTP/1.1 204 No Content", status_line);
1980
[email protected]df0c05c62009-06-17 15:50:581981 EXPECT_EQ(0, session->connection_pool()->IdleSocketCount());
[email protected]b4404c02009-04-10 16:38:521982
1983 std::string response_data;
1984 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:421985 EXPECT_EQ(OK, rv);
[email protected]b4404c02009-04-10 16:38:521986 EXPECT_EQ("", response_data);
1987
1988 // Empty the current queue. This is necessary because idle sockets are
1989 // added to the connection pool asynchronously with a PostTask.
1990 MessageLoop::current()->RunAllPending();
1991
1992 // We now check to make sure the socket was added back to the pool.
[email protected]df0c05c62009-06-17 15:50:581993 EXPECT_EQ(1, session->connection_pool()->IdleSocketCount());
[email protected]b4404c02009-04-10 16:38:521994}
1995
[email protected]372d34a2008-11-05 21:30:511996TEST_F(HttpNetworkTransactionTest, ResendRequestOnWriteBodyError) {
[email protected]1c773ea12009-04-28 19:58:421997 HttpRequestInfo request[2];
[email protected]372d34a2008-11-05 21:30:511998 // Transaction 1: a GET request that succeeds. The socket is recycled
1999 // after use.
2000 request[0].method = "GET";
2001 request[0].url = GURL("http://www.google.com/");
2002 request[0].load_flags = 0;
2003 // Transaction 2: a POST request. Reuses the socket kept alive from
2004 // transaction 1. The first attempts fails when writing the POST data.
2005 // This causes the transaction to retry with a new socket. The second
2006 // attempt succeeds.
2007 request[1].method = "POST";
2008 request[1].url = GURL("http://www.google.com/login.cgi");
[email protected]1c773ea12009-04-28 19:58:422009 request[1].upload_data = new UploadData;
[email protected]372d34a2008-11-05 21:30:512010 request[1].upload_data->AppendBytes("foo", 3);
2011 request[1].load_flags = 0;
2012
[email protected]228ff742009-06-05 01:19:592013 SessionDependencies session_deps;
2014 scoped_refptr<HttpNetworkSession> session = CreateSession(&session_deps);
[email protected]372d34a2008-11-05 21:30:512015
2016 // The first socket is used for transaction 1 and the first attempt of
2017 // transaction 2.
2018
2019 // The response of transaction 1.
2020 MockRead data_reads1[] = {
2021 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 11\r\n\r\n"),
2022 MockRead("hello world"),
[email protected]1c773ea12009-04-28 19:58:422023 MockRead(false, OK),
[email protected]372d34a2008-11-05 21:30:512024 };
2025 // The mock write results of transaction 1 and the first attempt of
2026 // transaction 2.
2027 MockWrite data_writes1[] = {
2028 MockWrite(false, 64), // GET
2029 MockWrite(false, 93), // POST
[email protected]1c773ea12009-04-28 19:58:422030 MockWrite(false, ERR_CONNECTION_ABORTED), // POST data
[email protected]372d34a2008-11-05 21:30:512031 };
[email protected]69b43fe2009-06-15 09:47:372032 StaticMockSocket data1(data_reads1, data_writes1);
[email protected]372d34a2008-11-05 21:30:512033
2034 // The second socket is used for the second attempt of transaction 2.
2035
2036 // The response of transaction 2.
2037 MockRead data_reads2[] = {
2038 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 7\r\n\r\n"),
2039 MockRead("welcome"),
[email protected]1c773ea12009-04-28 19:58:422040 MockRead(false, OK),
[email protected]372d34a2008-11-05 21:30:512041 };
2042 // The mock write results of the second attempt of transaction 2.
2043 MockWrite data_writes2[] = {
2044 MockWrite(false, 93), // POST
2045 MockWrite(false, 3), // POST data
2046 };
[email protected]69b43fe2009-06-15 09:47:372047 StaticMockSocket data2(data_reads2, data_writes2);
[email protected]372d34a2008-11-05 21:30:512048
[email protected]228ff742009-06-05 01:19:592049 session_deps.socket_factory.AddMockSocket(&data1);
2050 session_deps.socket_factory.AddMockSocket(&data2);
[email protected]372d34a2008-11-05 21:30:512051
2052 const char* kExpectedResponseData[] = {
2053 "hello world", "welcome"
2054 };
2055
2056 for (int i = 0; i < 2; ++i) {
[email protected]1c773ea12009-04-28 19:58:422057 scoped_ptr<HttpTransaction> trans(
[email protected]228ff742009-06-05 01:19:592058 new HttpNetworkTransaction(session, &session_deps.socket_factory));
[email protected]372d34a2008-11-05 21:30:512059
2060 TestCompletionCallback callback;
2061
2062 int rv = trans->Start(&request[i], &callback);
[email protected]1c773ea12009-04-28 19:58:422063 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]372d34a2008-11-05 21:30:512064
2065 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422066 EXPECT_EQ(OK, rv);
[email protected]372d34a2008-11-05 21:30:512067
[email protected]1c773ea12009-04-28 19:58:422068 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]372d34a2008-11-05 21:30:512069 EXPECT_TRUE(response != NULL);
2070
2071 EXPECT_TRUE(response->headers != NULL);
2072 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
2073
2074 std::string response_data;
2075 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:422076 EXPECT_EQ(OK, rv);
[email protected]372d34a2008-11-05 21:30:512077 EXPECT_EQ(kExpectedResponseData[i], response_data);
2078 }
2079}
[email protected]f9ee6b52008-11-08 06:46:232080
2081// Test the request-challenge-retry sequence for basic auth when there is
2082// an identity in the URL. The request should be sent as normal, but when
2083// it fails the identity from the URL is used to answer the challenge.
2084TEST_F(HttpNetworkTransactionTest, AuthIdentityInUrl) {
[email protected]228ff742009-06-05 01:19:592085 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:402086 scoped_ptr<HttpTransaction> trans(
2087 new HttpNetworkTransaction(
[email protected]228ff742009-06-05 01:19:592088 CreateSession(&session_deps),
2089 &session_deps.socket_factory));
[email protected]f9ee6b52008-11-08 06:46:232090
[email protected]1c773ea12009-04-28 19:58:422091 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:232092 request.method = "GET";
2093 // Note: the URL has a username:password in it.
2094 request.url = GURL("http://foo:[email protected]/");
2095 request.load_flags = 0;
2096
2097 MockWrite data_writes1[] = {
2098 MockWrite("GET / HTTP/1.1\r\n"
2099 "Host: www.google.com\r\n"
2100 "Connection: keep-alive\r\n\r\n"),
2101 };
2102
2103 MockRead data_reads1[] = {
2104 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
2105 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2106 MockRead("Content-Length: 10\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422107 MockRead(false, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:232108 };
2109
2110 // After the challenge above, the transaction will be restarted using the
2111 // identity from the url (foo, bar) to answer the challenge.
2112 MockWrite data_writes2[] = {
2113 MockWrite("GET / HTTP/1.1\r\n"
2114 "Host: www.google.com\r\n"
2115 "Connection: keep-alive\r\n"
2116 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2117 };
2118
2119 MockRead data_reads2[] = {
2120 MockRead("HTTP/1.0 200 OK\r\n"),
2121 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422122 MockRead(false, OK),
[email protected]f9ee6b52008-11-08 06:46:232123 };
2124
[email protected]69b43fe2009-06-15 09:47:372125 StaticMockSocket data1(data_reads1, data_writes1);
2126 StaticMockSocket data2(data_reads2, data_writes2);
[email protected]228ff742009-06-05 01:19:592127 session_deps.socket_factory.AddMockSocket(&data1);
2128 session_deps.socket_factory.AddMockSocket(&data2);
[email protected]f9ee6b52008-11-08 06:46:232129
2130 TestCompletionCallback callback1;
2131
2132 int rv = trans->Start(&request, &callback1);
[email protected]1c773ea12009-04-28 19:58:422133 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:232134
2135 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422136 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:232137
[email protected]0757e7702009-03-27 04:00:222138 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
2139 TestCompletionCallback callback2;
2140 rv = trans->RestartWithAuth(std::wstring(), std::wstring(), &callback2);
[email protected]1c773ea12009-04-28 19:58:422141 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]0757e7702009-03-27 04:00:222142 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422143 EXPECT_EQ(OK, rv);
[email protected]0757e7702009-03-27 04:00:222144 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
2145
[email protected]1c773ea12009-04-28 19:58:422146 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]f9ee6b52008-11-08 06:46:232147 EXPECT_FALSE(response == NULL);
2148
2149 // There is no challenge info, since the identity in URL worked.
2150 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2151
2152 EXPECT_EQ(100, response->headers->GetContentLength());
2153
2154 // Empty the current queue.
2155 MessageLoop::current()->RunAllPending();
2156}
2157
2158// Test that previously tried username/passwords for a realm get re-used.
2159TEST_F(HttpNetworkTransactionTest, BasicAuthCacheAndPreauth) {
[email protected]228ff742009-06-05 01:19:592160 SessionDependencies session_deps;
2161 scoped_refptr<HttpNetworkSession> session = CreateSession(&session_deps);
[email protected]f9ee6b52008-11-08 06:46:232162
2163 // Transaction 1: authenticate (foo, bar) on MyRealm1
2164 {
[email protected]1c773ea12009-04-28 19:58:422165 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(
[email protected]228ff742009-06-05 01:19:592166 session, &session_deps.socket_factory));
[email protected]f9ee6b52008-11-08 06:46:232167
[email protected]1c773ea12009-04-28 19:58:422168 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:232169 request.method = "GET";
2170 request.url = GURL("http://www.google.com/x/y/z");
2171 request.load_flags = 0;
2172
2173 MockWrite data_writes1[] = {
2174 MockWrite("GET /x/y/z HTTP/1.1\r\n"
2175 "Host: www.google.com\r\n"
2176 "Connection: keep-alive\r\n\r\n"),
2177 };
2178
2179 MockRead data_reads1[] = {
2180 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
2181 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2182 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422183 MockRead(false, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:232184 };
2185
2186 // Resend with authorization (username=foo, password=bar)
2187 MockWrite data_writes2[] = {
2188 MockWrite("GET /x/y/z HTTP/1.1\r\n"
2189 "Host: www.google.com\r\n"
2190 "Connection: keep-alive\r\n"
2191 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2192 };
2193
2194 // Sever accepts the authorization.
2195 MockRead data_reads2[] = {
2196 MockRead("HTTP/1.0 200 OK\r\n"),
2197 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422198 MockRead(false, OK),
[email protected]f9ee6b52008-11-08 06:46:232199 };
2200
[email protected]69b43fe2009-06-15 09:47:372201 StaticMockSocket data1(data_reads1, data_writes1);
2202 StaticMockSocket data2(data_reads2, data_writes2);
[email protected]228ff742009-06-05 01:19:592203 session_deps.socket_factory.AddMockSocket(&data1);
2204 session_deps.socket_factory.AddMockSocket(&data2);
[email protected]f9ee6b52008-11-08 06:46:232205
2206 TestCompletionCallback callback1;
2207
2208 int rv = trans->Start(&request, &callback1);
[email protected]1c773ea12009-04-28 19:58:422209 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:232210
2211 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422212 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:232213
[email protected]1c773ea12009-04-28 19:58:422214 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]f9ee6b52008-11-08 06:46:232215 EXPECT_FALSE(response == NULL);
2216
2217 // The password prompt info should have been set in
2218 // response->auth_challenge.
2219 EXPECT_FALSE(response->auth_challenge.get() == NULL);
2220
[email protected]71e4573a2009-05-21 22:03:002221 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
[email protected]f9ee6b52008-11-08 06:46:232222 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
2223 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
2224
2225 TestCompletionCallback callback2;
2226
2227 rv = trans->RestartWithAuth(L"foo", L"bar", &callback2);
[email protected]1c773ea12009-04-28 19:58:422228 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:232229
2230 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422231 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:232232
2233 response = trans->GetResponseInfo();
2234 EXPECT_FALSE(response == NULL);
2235 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2236 EXPECT_EQ(100, response->headers->GetContentLength());
2237 }
2238
2239 // ------------------------------------------------------------------------
2240
2241 // Transaction 2: authenticate (foo2, bar2) on MyRealm2
2242 {
[email protected]1c773ea12009-04-28 19:58:422243 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(
[email protected]228ff742009-06-05 01:19:592244 session, &session_deps.socket_factory));
[email protected]f9ee6b52008-11-08 06:46:232245
[email protected]1c773ea12009-04-28 19:58:422246 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:232247 request.method = "GET";
2248 // Note that Transaction 1 was at /x/y/z, so this is in the same
2249 // protection space as MyRealm1.
2250 request.url = GURL("http://www.google.com/x/y/a/b");
2251 request.load_flags = 0;
2252
2253 MockWrite data_writes1[] = {
2254 MockWrite("GET /x/y/a/b HTTP/1.1\r\n"
2255 "Host: www.google.com\r\n"
2256 "Connection: keep-alive\r\n"
2257 // Send preemptive authorization for MyRealm1
2258 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2259 };
2260
2261 // The server didn't like the preemptive authorization, and
2262 // challenges us for a different realm (MyRealm2).
2263 MockRead data_reads1[] = {
2264 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
2265 MockRead("WWW-Authenticate: Basic realm=\"MyRealm2\"\r\n"),
2266 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422267 MockRead(false, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:232268 };
2269
2270 // Resend with authorization for MyRealm2 (username=foo2, password=bar2)
2271 MockWrite data_writes2[] = {
2272 MockWrite("GET /x/y/a/b HTTP/1.1\r\n"
2273 "Host: www.google.com\r\n"
2274 "Connection: keep-alive\r\n"
2275 "Authorization: Basic Zm9vMjpiYXIy\r\n\r\n"),
2276 };
2277
2278 // Sever accepts the authorization.
2279 MockRead data_reads2[] = {
2280 MockRead("HTTP/1.0 200 OK\r\n"),
2281 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422282 MockRead(false, OK),
[email protected]f9ee6b52008-11-08 06:46:232283 };
2284
[email protected]69b43fe2009-06-15 09:47:372285 StaticMockSocket data1(data_reads1, data_writes1);
2286 StaticMockSocket data2(data_reads2, data_writes2);
[email protected]228ff742009-06-05 01:19:592287 session_deps.socket_factory.AddMockSocket(&data1);
2288 session_deps.socket_factory.AddMockSocket(&data2);
[email protected]f9ee6b52008-11-08 06:46:232289
2290 TestCompletionCallback callback1;
2291
2292 int rv = trans->Start(&request, &callback1);
[email protected]1c773ea12009-04-28 19:58:422293 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:232294
2295 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422296 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:232297
[email protected]1c773ea12009-04-28 19:58:422298 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]f9ee6b52008-11-08 06:46:232299 EXPECT_FALSE(response == NULL);
2300
2301 // The password prompt info should have been set in
2302 // response->auth_challenge.
2303 EXPECT_FALSE(response->auth_challenge.get() == NULL);
2304
[email protected]71e4573a2009-05-21 22:03:002305 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
[email protected]f9ee6b52008-11-08 06:46:232306 EXPECT_EQ(L"MyRealm2", response->auth_challenge->realm);
2307 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
2308
2309 TestCompletionCallback callback2;
2310
2311 rv = trans->RestartWithAuth(L"foo2", L"bar2", &callback2);
[email protected]1c773ea12009-04-28 19:58:422312 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:232313
2314 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422315 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:232316
2317 response = trans->GetResponseInfo();
2318 EXPECT_FALSE(response == NULL);
2319 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2320 EXPECT_EQ(100, response->headers->GetContentLength());
2321 }
2322
2323 // ------------------------------------------------------------------------
2324
2325 // Transaction 3: Resend a request in MyRealm's protection space --
2326 // succeed with preemptive authorization.
2327 {
[email protected]1c773ea12009-04-28 19:58:422328 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(
[email protected]228ff742009-06-05 01:19:592329 session, &session_deps.socket_factory));
[email protected]f9ee6b52008-11-08 06:46:232330
[email protected]1c773ea12009-04-28 19:58:422331 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:232332 request.method = "GET";
2333 request.url = GURL("http://www.google.com/x/y/z2");
2334 request.load_flags = 0;
2335
2336 MockWrite data_writes1[] = {
2337 MockWrite("GET /x/y/z2 HTTP/1.1\r\n"
2338 "Host: www.google.com\r\n"
2339 "Connection: keep-alive\r\n"
2340 // The authorization for MyRealm1 gets sent preemptively
2341 // (since the url is in the same protection space)
2342 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2343 };
2344
2345 // Sever accepts the preemptive authorization
2346 MockRead data_reads1[] = {
2347 MockRead("HTTP/1.0 200 OK\r\n"),
2348 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422349 MockRead(false, OK),
[email protected]f9ee6b52008-11-08 06:46:232350 };
2351
[email protected]69b43fe2009-06-15 09:47:372352 StaticMockSocket data1(data_reads1, data_writes1);
[email protected]228ff742009-06-05 01:19:592353 session_deps.socket_factory.AddMockSocket(&data1);
[email protected]f9ee6b52008-11-08 06:46:232354
2355 TestCompletionCallback callback1;
2356
2357 int rv = trans->Start(&request, &callback1);
[email protected]1c773ea12009-04-28 19:58:422358 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:232359
2360 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422361 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:232362
[email protected]1c773ea12009-04-28 19:58:422363 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]f9ee6b52008-11-08 06:46:232364 EXPECT_FALSE(response == NULL);
2365
2366 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2367 EXPECT_EQ(100, response->headers->GetContentLength());
2368 }
2369
2370 // ------------------------------------------------------------------------
2371
2372 // Transaction 4: request another URL in MyRealm (however the
2373 // url is not known to belong to the protection space, so no pre-auth).
2374 {
[email protected]1c773ea12009-04-28 19:58:422375 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(
[email protected]228ff742009-06-05 01:19:592376 session, &session_deps.socket_factory));
[email protected]f9ee6b52008-11-08 06:46:232377
[email protected]1c773ea12009-04-28 19:58:422378 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:232379 request.method = "GET";
2380 request.url = GURL("http://www.google.com/x/1");
2381 request.load_flags = 0;
2382
2383 MockWrite data_writes1[] = {
2384 MockWrite("GET /x/1 HTTP/1.1\r\n"
2385 "Host: www.google.com\r\n"
2386 "Connection: keep-alive\r\n\r\n"),
2387 };
2388
2389 MockRead data_reads1[] = {
2390 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
2391 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2392 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422393 MockRead(false, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:232394 };
2395
2396 // Resend with authorization from MyRealm's cache.
2397 MockWrite data_writes2[] = {
2398 MockWrite("GET /x/1 HTTP/1.1\r\n"
2399 "Host: www.google.com\r\n"
2400 "Connection: keep-alive\r\n"
2401 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2402 };
2403
2404 // Sever accepts the authorization.
2405 MockRead data_reads2[] = {
2406 MockRead("HTTP/1.0 200 OK\r\n"),
2407 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422408 MockRead(false, OK),
[email protected]f9ee6b52008-11-08 06:46:232409 };
2410
[email protected]69b43fe2009-06-15 09:47:372411 StaticMockSocket data1(data_reads1, data_writes1);
2412 StaticMockSocket data2(data_reads2, data_writes2);
[email protected]228ff742009-06-05 01:19:592413 session_deps.socket_factory.AddMockSocket(&data1);
2414 session_deps.socket_factory.AddMockSocket(&data2);
[email protected]f9ee6b52008-11-08 06:46:232415
2416 TestCompletionCallback callback1;
2417
2418 int rv = trans->Start(&request, &callback1);
[email protected]1c773ea12009-04-28 19:58:422419 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:232420
2421 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422422 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:232423
[email protected]0757e7702009-03-27 04:00:222424 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
2425 TestCompletionCallback callback2;
2426 rv = trans->RestartWithAuth(std::wstring(), std::wstring(), &callback2);
[email protected]1c773ea12009-04-28 19:58:422427 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]0757e7702009-03-27 04:00:222428 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422429 EXPECT_EQ(OK, rv);
[email protected]0757e7702009-03-27 04:00:222430 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
2431
[email protected]1c773ea12009-04-28 19:58:422432 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]f9ee6b52008-11-08 06:46:232433 EXPECT_FALSE(response == NULL);
2434 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2435 EXPECT_EQ(100, response->headers->GetContentLength());
2436 }
2437
2438 // ------------------------------------------------------------------------
2439
2440 // Transaction 5: request a URL in MyRealm, but the server rejects the
2441 // cached identity. Should invalidate and re-prompt.
2442 {
[email protected]1c773ea12009-04-28 19:58:422443 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(
[email protected]228ff742009-06-05 01:19:592444 session, &session_deps.socket_factory));
[email protected]f9ee6b52008-11-08 06:46:232445
[email protected]1c773ea12009-04-28 19:58:422446 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:232447 request.method = "GET";
2448 request.url = GURL("http://www.google.com/p/q/t");
2449 request.load_flags = 0;
2450
2451 MockWrite data_writes1[] = {
2452 MockWrite("GET /p/q/t HTTP/1.1\r\n"
2453 "Host: www.google.com\r\n"
2454 "Connection: keep-alive\r\n\r\n"),
2455 };
2456
2457 MockRead data_reads1[] = {
2458 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
2459 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2460 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422461 MockRead(false, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:232462 };
2463
2464 // Resend with authorization from cache for MyRealm.
2465 MockWrite data_writes2[] = {
2466 MockWrite("GET /p/q/t HTTP/1.1\r\n"
2467 "Host: www.google.com\r\n"
2468 "Connection: keep-alive\r\n"
2469 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2470 };
2471
2472 // Sever rejects the authorization.
2473 MockRead data_reads2[] = {
2474 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
2475 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2476 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422477 MockRead(false, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:232478 };
2479
2480 // At this point we should prompt for new credentials for MyRealm.
2481 // Restart with username=foo3, password=foo4.
2482 MockWrite data_writes3[] = {
2483 MockWrite("GET /p/q/t HTTP/1.1\r\n"
2484 "Host: www.google.com\r\n"
2485 "Connection: keep-alive\r\n"
2486 "Authorization: Basic Zm9vMzpiYXIz\r\n\r\n"),
2487 };
2488
2489 // Sever accepts the authorization.
2490 MockRead data_reads3[] = {
2491 MockRead("HTTP/1.0 200 OK\r\n"),
2492 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422493 MockRead(false, OK),
[email protected]f9ee6b52008-11-08 06:46:232494 };
2495
[email protected]69b43fe2009-06-15 09:47:372496 StaticMockSocket data1(data_reads1, data_writes1);
2497 StaticMockSocket data2(data_reads2, data_writes2);
2498 StaticMockSocket data3(data_reads3, data_writes3);
[email protected]228ff742009-06-05 01:19:592499 session_deps.socket_factory.AddMockSocket(&data1);
2500 session_deps.socket_factory.AddMockSocket(&data2);
2501 session_deps.socket_factory.AddMockSocket(&data3);
[email protected]f9ee6b52008-11-08 06:46:232502
2503 TestCompletionCallback callback1;
2504
2505 int rv = trans->Start(&request, &callback1);
[email protected]1c773ea12009-04-28 19:58:422506 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:232507
2508 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422509 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:232510
[email protected]0757e7702009-03-27 04:00:222511 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
2512 TestCompletionCallback callback2;
2513 rv = trans->RestartWithAuth(std::wstring(), std::wstring(), &callback2);
[email protected]1c773ea12009-04-28 19:58:422514 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]0757e7702009-03-27 04:00:222515 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422516 EXPECT_EQ(OK, rv);
[email protected]0757e7702009-03-27 04:00:222517 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
2518
[email protected]1c773ea12009-04-28 19:58:422519 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]f9ee6b52008-11-08 06:46:232520 EXPECT_FALSE(response == NULL);
2521
2522 // The password prompt info should have been set in
2523 // response->auth_challenge.
2524 EXPECT_FALSE(response->auth_challenge.get() == NULL);
2525
[email protected]71e4573a2009-05-21 22:03:002526 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
[email protected]f9ee6b52008-11-08 06:46:232527 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
2528 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
2529
[email protected]0757e7702009-03-27 04:00:222530 TestCompletionCallback callback3;
[email protected]f9ee6b52008-11-08 06:46:232531
[email protected]0757e7702009-03-27 04:00:222532 rv = trans->RestartWithAuth(L"foo3", L"bar3", &callback3);
[email protected]1c773ea12009-04-28 19:58:422533 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:232534
[email protected]0757e7702009-03-27 04:00:222535 rv = callback3.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422536 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:232537
2538 response = trans->GetResponseInfo();
2539 EXPECT_FALSE(response == NULL);
2540 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2541 EXPECT_EQ(100, response->headers->GetContentLength());
2542 }
2543}
[email protected]89ceba9a2009-03-21 03:46:062544
2545// Test the ResetStateForRestart() private method.
2546TEST_F(HttpNetworkTransactionTest, ResetStateForRestart) {
2547 // Create a transaction (the dependencies aren't important).
[email protected]228ff742009-06-05 01:19:592548 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:402549 scoped_ptr<HttpNetworkTransaction> trans(
2550 new HttpNetworkTransaction(
[email protected]228ff742009-06-05 01:19:592551 CreateSession(&session_deps),
2552 &session_deps.socket_factory));
[email protected]89ceba9a2009-03-21 03:46:062553
2554 // Setup some state (which we expect ResetStateForRestart() will clear).
[email protected]ffeb0882009-04-30 21:51:252555 trans->header_buf_->Realloc(10);
[email protected]89ceba9a2009-03-21 03:46:062556 trans->header_buf_capacity_ = 10;
2557 trans->header_buf_len_ = 3;
2558 trans->header_buf_body_offset_ = 11;
2559 trans->header_buf_http_offset_ = 0;
2560 trans->response_body_length_ = 100;
2561 trans->response_body_read_ = 1;
2562 trans->read_buf_ = new IOBuffer(15);
2563 trans->read_buf_len_ = 15;
[email protected]ffeb0882009-04-30 21:51:252564 trans->request_headers_->headers_ = "Authorization: NTLM";
[email protected]89ceba9a2009-03-21 03:46:062565 trans->request_headers_bytes_sent_ = 3;
2566
2567 // Setup state in response_
2568 trans->response_.auth_challenge = new AuthChallengeInfo();
2569 trans->response_.ssl_info.cert_status = -15;
2570 trans->response_.response_time = base::Time::Now();
[email protected]b4404c02009-04-10 16:38:522571 trans->response_.was_cached = true; // (Wouldn't ever actually be true...)
[email protected]89ceba9a2009-03-21 03:46:062572
2573 { // Setup state for response_.vary_data
2574 HttpRequestInfo request;
2575 std::string temp("HTTP/1.1 200 OK\nVary: foo, bar\n\n");
2576 std::replace(temp.begin(), temp.end(), '\n', '\0');
2577 scoped_refptr<HttpResponseHeaders> response = new HttpResponseHeaders(temp);
2578 request.extra_headers = "Foo: 1\nbar: 23";
2579 EXPECT_TRUE(trans->response_.vary_data.Init(request, *response));
2580 }
2581
2582 // Cause the above state to be reset.
2583 trans->ResetStateForRestart();
2584
2585 // Verify that the state that needed to be reset, has been reset.
[email protected]ffeb0882009-04-30 21:51:252586 EXPECT_EQ(NULL, trans->header_buf_->headers());
[email protected]89ceba9a2009-03-21 03:46:062587 EXPECT_EQ(0, trans->header_buf_capacity_);
2588 EXPECT_EQ(0, trans->header_buf_len_);
2589 EXPECT_EQ(-1, trans->header_buf_body_offset_);
2590 EXPECT_EQ(-1, trans->header_buf_http_offset_);
2591 EXPECT_EQ(-1, trans->response_body_length_);
2592 EXPECT_EQ(0, trans->response_body_read_);
2593 EXPECT_EQ(NULL, trans->read_buf_.get());
2594 EXPECT_EQ(0, trans->read_buf_len_);
[email protected]ffeb0882009-04-30 21:51:252595 EXPECT_EQ("", trans->request_headers_->headers_);
[email protected]89ceba9a2009-03-21 03:46:062596 EXPECT_EQ(0U, trans->request_headers_bytes_sent_);
2597 EXPECT_EQ(NULL, trans->response_.auth_challenge.get());
2598 EXPECT_EQ(NULL, trans->response_.headers.get());
2599 EXPECT_EQ(false, trans->response_.was_cached);
[email protected]89ceba9a2009-03-21 03:46:062600 EXPECT_EQ(0, trans->response_.ssl_info.cert_status);
2601 EXPECT_FALSE(trans->response_.vary_data.is_valid());
2602}
2603
[email protected]bacff652009-03-31 17:50:332604// Test HTTPS connections to a site with a bad certificate
2605TEST_F(HttpNetworkTransactionTest, HTTPSBadCertificate) {
[email protected]228ff742009-06-05 01:19:592606 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:402607 scoped_ptr<HttpTransaction> trans(
2608 new HttpNetworkTransaction(
[email protected]228ff742009-06-05 01:19:592609 CreateSession(&session_deps),
2610 &session_deps.socket_factory));
[email protected]bacff652009-03-31 17:50:332611
2612 HttpRequestInfo request;
2613 request.method = "GET";
2614 request.url = GURL("https://www.google.com/");
2615 request.load_flags = 0;
2616
2617 MockWrite data_writes[] = {
2618 MockWrite("GET / HTTP/1.1\r\n"
2619 "Host: www.google.com\r\n"
2620 "Connection: keep-alive\r\n\r\n"),
2621 };
2622
2623 MockRead data_reads[] = {
2624 MockRead("HTTP/1.0 200 OK\r\n"),
2625 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2626 MockRead("Content-Length: 100\r\n\r\n"),
2627 MockRead(false, OK),
2628 };
2629
[email protected]69b43fe2009-06-15 09:47:372630 StaticMockSocket ssl_bad_certificate;
2631 StaticMockSocket data(data_reads, data_writes);
[email protected]bacff652009-03-31 17:50:332632 MockSSLSocket ssl_bad(true, ERR_CERT_AUTHORITY_INVALID);
2633 MockSSLSocket ssl(true, OK);
2634
[email protected]228ff742009-06-05 01:19:592635 session_deps.socket_factory.AddMockSocket(&ssl_bad_certificate);
2636 session_deps.socket_factory.AddMockSocket(&data);
2637 session_deps.socket_factory.AddMockSSLSocket(&ssl_bad);
2638 session_deps.socket_factory.AddMockSSLSocket(&ssl);
[email protected]bacff652009-03-31 17:50:332639
2640 TestCompletionCallback callback;
2641
2642 int rv = trans->Start(&request, &callback);
2643 EXPECT_EQ(ERR_IO_PENDING, rv);
2644
2645 rv = callback.WaitForResult();
2646 EXPECT_EQ(ERR_CERT_AUTHORITY_INVALID, rv);
2647
2648 rv = trans->RestartIgnoringLastError(&callback);
2649 EXPECT_EQ(ERR_IO_PENDING, rv);
2650
2651 rv = callback.WaitForResult();
2652 EXPECT_EQ(OK, rv);
2653
2654 const HttpResponseInfo* response = trans->GetResponseInfo();
2655
2656 EXPECT_FALSE(response == NULL);
2657 EXPECT_EQ(100, response->headers->GetContentLength());
2658}
2659
2660// Test HTTPS connections to a site with a bad certificate, going through a
2661// proxy
2662TEST_F(HttpNetworkTransactionTest, HTTPSBadCertificateViaProxy) {
[email protected]228ff742009-06-05 01:19:592663 SessionDependencies session_deps(CreateFixedProxyService("myproxy:70"));
[email protected]bacff652009-03-31 17:50:332664
2665 HttpRequestInfo request;
2666 request.method = "GET";
2667 request.url = GURL("https://www.google.com/");
2668 request.load_flags = 0;
2669
2670 MockWrite proxy_writes[] = {
2671 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
[email protected]e44de5d2009-06-05 20:12:452672 "Host: www.google.com\r\n"
2673 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]bacff652009-03-31 17:50:332674 };
2675
2676 MockRead proxy_reads[] = {
2677 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422678 MockRead(false, OK)
[email protected]bacff652009-03-31 17:50:332679 };
2680
2681 MockWrite data_writes[] = {
2682 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
[email protected]e44de5d2009-06-05 20:12:452683 "Host: www.google.com\r\n"
2684 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]bacff652009-03-31 17:50:332685 MockWrite("GET / HTTP/1.1\r\n"
2686 "Host: www.google.com\r\n"
2687 "Connection: keep-alive\r\n\r\n"),
2688 };
2689
2690 MockRead data_reads[] = {
2691 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
2692 MockRead("HTTP/1.0 200 OK\r\n"),
2693 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2694 MockRead("Content-Length: 100\r\n\r\n"),
2695 MockRead(false, OK),
2696 };
2697
[email protected]69b43fe2009-06-15 09:47:372698 StaticMockSocket ssl_bad_certificate(proxy_reads, proxy_writes);
2699 StaticMockSocket data(data_reads, data_writes);
[email protected]bacff652009-03-31 17:50:332700 MockSSLSocket ssl_bad(true, ERR_CERT_AUTHORITY_INVALID);
2701 MockSSLSocket ssl(true, OK);
2702
[email protected]228ff742009-06-05 01:19:592703 session_deps.socket_factory.AddMockSocket(&ssl_bad_certificate);
2704 session_deps.socket_factory.AddMockSocket(&data);
2705 session_deps.socket_factory.AddMockSSLSocket(&ssl_bad);
2706 session_deps.socket_factory.AddMockSSLSocket(&ssl);
[email protected]bacff652009-03-31 17:50:332707
2708 TestCompletionCallback callback;
2709
2710 for (int i = 0; i < 2; i++) {
[email protected]228ff742009-06-05 01:19:592711 session_deps.socket_factory.ResetNextMockIndexes();
[email protected]bacff652009-03-31 17:50:332712
[email protected]d207a5f2009-06-04 05:28:402713 scoped_ptr<HttpTransaction> trans(
2714 new HttpNetworkTransaction(
[email protected]228ff742009-06-05 01:19:592715 CreateSession(&session_deps),
2716 &session_deps.socket_factory));
[email protected]bacff652009-03-31 17:50:332717
2718 int rv = trans->Start(&request, &callback);
2719 EXPECT_EQ(ERR_IO_PENDING, rv);
2720
2721 rv = callback.WaitForResult();
2722 EXPECT_EQ(ERR_CERT_AUTHORITY_INVALID, rv);
2723
2724 rv = trans->RestartIgnoringLastError(&callback);
2725 EXPECT_EQ(ERR_IO_PENDING, rv);
2726
2727 rv = callback.WaitForResult();
2728 EXPECT_EQ(OK, rv);
2729
2730 const HttpResponseInfo* response = trans->GetResponseInfo();
2731
2732 EXPECT_FALSE(response == NULL);
2733 EXPECT_EQ(100, response->headers->GetContentLength());
2734 }
2735}
2736
[email protected]1c773ea12009-04-28 19:58:422737TEST_F(HttpNetworkTransactionTest, BuildRequest_UserAgent) {
[email protected]228ff742009-06-05 01:19:592738 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:402739 scoped_ptr<HttpTransaction> trans(
2740 new HttpNetworkTransaction(
[email protected]228ff742009-06-05 01:19:592741 CreateSession(&session_deps),
2742 &session_deps.socket_factory));
[email protected]1c773ea12009-04-28 19:58:422743
2744 HttpRequestInfo request;
2745 request.method = "GET";
2746 request.url = GURL("http://www.google.com/");
2747 request.user_agent = "Chromium Ultra Awesome X Edition";
2748
2749 MockWrite data_writes[] = {
2750 MockWrite("GET / HTTP/1.1\r\n"
2751 "Host: www.google.com\r\n"
2752 "Connection: keep-alive\r\n"
2753 "User-Agent: Chromium Ultra Awesome X Edition\r\n\r\n"),
2754 };
2755
2756 // Lastly, the server responds with the actual content.
2757 MockRead data_reads[] = {
2758 MockRead("HTTP/1.0 200 OK\r\n"),
2759 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2760 MockRead("Content-Length: 100\r\n\r\n"),
2761 MockRead(false, OK),
2762 };
2763
[email protected]69b43fe2009-06-15 09:47:372764 StaticMockSocket data(data_reads, data_writes);
[email protected]228ff742009-06-05 01:19:592765 session_deps.socket_factory.AddMockSocket(&data);
[email protected]1c773ea12009-04-28 19:58:422766
2767 TestCompletionCallback callback;
2768
2769 int rv = trans->Start(&request, &callback);
2770 EXPECT_EQ(ERR_IO_PENDING, rv);
2771
2772 rv = callback.WaitForResult();
2773 EXPECT_EQ(OK, rv);
2774}
2775
2776TEST_F(HttpNetworkTransactionTest, BuildRequest_Referer) {
[email protected]228ff742009-06-05 01:19:592777 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:402778 scoped_ptr<HttpTransaction> trans(
2779 new HttpNetworkTransaction(
[email protected]228ff742009-06-05 01:19:592780 CreateSession(&session_deps),
2781 &session_deps.socket_factory));
[email protected]1c773ea12009-04-28 19:58:422782
2783 HttpRequestInfo request;
2784 request.method = "GET";
2785 request.url = GURL("http://www.google.com/");
2786 request.load_flags = 0;
2787 request.referrer = GURL("http://the.previous.site.com/");
2788
2789 MockWrite data_writes[] = {
2790 MockWrite("GET / HTTP/1.1\r\n"
2791 "Host: www.google.com\r\n"
2792 "Connection: keep-alive\r\n"
2793 "Referer: http://the.previous.site.com/\r\n\r\n"),
2794 };
2795
2796 // Lastly, the server responds with the actual content.
2797 MockRead data_reads[] = {
2798 MockRead("HTTP/1.0 200 OK\r\n"),
2799 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2800 MockRead("Content-Length: 100\r\n\r\n"),
2801 MockRead(false, OK),
2802 };
2803
[email protected]69b43fe2009-06-15 09:47:372804 StaticMockSocket data(data_reads, data_writes);
[email protected]228ff742009-06-05 01:19:592805 session_deps.socket_factory.AddMockSocket(&data);
[email protected]1c773ea12009-04-28 19:58:422806
2807 TestCompletionCallback callback;
2808
2809 int rv = trans->Start(&request, &callback);
2810 EXPECT_EQ(ERR_IO_PENDING, rv);
2811
2812 rv = callback.WaitForResult();
2813 EXPECT_EQ(OK, rv);
2814}
2815
2816TEST_F(HttpNetworkTransactionTest, BuildRequest_PostContentLengthZero) {
[email protected]228ff742009-06-05 01:19:592817 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:402818 scoped_ptr<HttpTransaction> trans(
2819 new HttpNetworkTransaction(
[email protected]228ff742009-06-05 01:19:592820 CreateSession(&session_deps),
2821 &session_deps.socket_factory));
[email protected]1c773ea12009-04-28 19:58:422822
2823 HttpRequestInfo request;
2824 request.method = "POST";
2825 request.url = GURL("http://www.google.com/");
2826
2827 MockWrite data_writes[] = {
2828 MockWrite("POST / HTTP/1.1\r\n"
2829 "Host: www.google.com\r\n"
2830 "Connection: keep-alive\r\n"
2831 "Content-Length: 0\r\n\r\n"),
2832 };
2833
2834 // Lastly, the server responds with the actual content.
2835 MockRead data_reads[] = {
2836 MockRead("HTTP/1.0 200 OK\r\n"),
2837 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2838 MockRead("Content-Length: 100\r\n\r\n"),
2839 MockRead(false, OK),
2840 };
2841
[email protected]69b43fe2009-06-15 09:47:372842 StaticMockSocket data(data_reads, data_writes);
[email protected]228ff742009-06-05 01:19:592843 session_deps.socket_factory.AddMockSocket(&data);
[email protected]1c773ea12009-04-28 19:58:422844
2845 TestCompletionCallback callback;
2846
2847 int rv = trans->Start(&request, &callback);
2848 EXPECT_EQ(ERR_IO_PENDING, rv);
2849
2850 rv = callback.WaitForResult();
2851 EXPECT_EQ(OK, rv);
2852}
2853
2854TEST_F(HttpNetworkTransactionTest, BuildRequest_PutContentLengthZero) {
[email protected]228ff742009-06-05 01:19:592855 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:402856 scoped_ptr<HttpTransaction> trans(
2857 new HttpNetworkTransaction(
[email protected]228ff742009-06-05 01:19:592858 CreateSession(&session_deps),
2859 &session_deps.socket_factory));
[email protected]1c773ea12009-04-28 19:58:422860
2861 HttpRequestInfo request;
2862 request.method = "PUT";
2863 request.url = GURL("http://www.google.com/");
2864
2865 MockWrite data_writes[] = {
2866 MockWrite("PUT / HTTP/1.1\r\n"
2867 "Host: www.google.com\r\n"
2868 "Connection: keep-alive\r\n"
2869 "Content-Length: 0\r\n\r\n"),
2870 };
2871
2872 // Lastly, the server responds with the actual content.
2873 MockRead data_reads[] = {
2874 MockRead("HTTP/1.0 200 OK\r\n"),
2875 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2876 MockRead("Content-Length: 100\r\n\r\n"),
2877 MockRead(false, OK),
2878 };
2879
[email protected]69b43fe2009-06-15 09:47:372880 StaticMockSocket data(data_reads, data_writes);
[email protected]228ff742009-06-05 01:19:592881 session_deps.socket_factory.AddMockSocket(&data);
[email protected]1c773ea12009-04-28 19:58:422882
2883 TestCompletionCallback callback;
2884
2885 int rv = trans->Start(&request, &callback);
2886 EXPECT_EQ(ERR_IO_PENDING, rv);
2887
2888 rv = callback.WaitForResult();
2889 EXPECT_EQ(OK, rv);
2890}
2891
2892TEST_F(HttpNetworkTransactionTest, BuildRequest_HeadContentLengthZero) {
[email protected]228ff742009-06-05 01:19:592893 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:402894 scoped_ptr<HttpTransaction> trans(
2895 new HttpNetworkTransaction(
[email protected]228ff742009-06-05 01:19:592896 CreateSession(&session_deps),
2897 &session_deps.socket_factory));
[email protected]1c773ea12009-04-28 19:58:422898
2899 HttpRequestInfo request;
2900 request.method = "HEAD";
2901 request.url = GURL("http://www.google.com/");
2902
2903 MockWrite data_writes[] = {
2904 MockWrite("HEAD / HTTP/1.1\r\n"
2905 "Host: www.google.com\r\n"
2906 "Connection: keep-alive\r\n"
2907 "Content-Length: 0\r\n\r\n"),
2908 };
2909
2910 // Lastly, the server responds with the actual content.
2911 MockRead data_reads[] = {
2912 MockRead("HTTP/1.0 200 OK\r\n"),
2913 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2914 MockRead("Content-Length: 100\r\n\r\n"),
2915 MockRead(false, OK),
2916 };
2917
[email protected]69b43fe2009-06-15 09:47:372918 StaticMockSocket data(data_reads, data_writes);
[email protected]228ff742009-06-05 01:19:592919 session_deps.socket_factory.AddMockSocket(&data);
[email protected]1c773ea12009-04-28 19:58:422920
2921 TestCompletionCallback callback;
2922
2923 int rv = trans->Start(&request, &callback);
2924 EXPECT_EQ(ERR_IO_PENDING, rv);
2925
2926 rv = callback.WaitForResult();
2927 EXPECT_EQ(OK, rv);
2928}
2929
2930TEST_F(HttpNetworkTransactionTest, BuildRequest_CacheControlNoCache) {
[email protected]228ff742009-06-05 01:19:592931 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:402932 scoped_ptr<HttpTransaction> trans(
2933 new HttpNetworkTransaction(
[email protected]228ff742009-06-05 01:19:592934 CreateSession(&session_deps),
2935 &session_deps.socket_factory));
[email protected]1c773ea12009-04-28 19:58:422936
2937 HttpRequestInfo request;
2938 request.method = "GET";
2939 request.url = GURL("http://www.google.com/");
2940 request.load_flags = LOAD_BYPASS_CACHE;
2941
2942 MockWrite data_writes[] = {
2943 MockWrite("GET / HTTP/1.1\r\n"
2944 "Host: www.google.com\r\n"
2945 "Connection: keep-alive\r\n"
2946 "Pragma: no-cache\r\n"
2947 "Cache-Control: no-cache\r\n\r\n"),
2948 };
2949
2950 // Lastly, the server responds with the actual content.
2951 MockRead data_reads[] = {
2952 MockRead("HTTP/1.0 200 OK\r\n"),
2953 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2954 MockRead("Content-Length: 100\r\n\r\n"),
2955 MockRead(false, OK),
2956 };
2957
[email protected]69b43fe2009-06-15 09:47:372958 StaticMockSocket data(data_reads, data_writes);
[email protected]228ff742009-06-05 01:19:592959 session_deps.socket_factory.AddMockSocket(&data);
[email protected]1c773ea12009-04-28 19:58:422960
2961 TestCompletionCallback callback;
2962
2963 int rv = trans->Start(&request, &callback);
2964 EXPECT_EQ(ERR_IO_PENDING, rv);
2965
2966 rv = callback.WaitForResult();
2967 EXPECT_EQ(OK, rv);
2968}
2969
2970TEST_F(HttpNetworkTransactionTest,
2971 BuildRequest_CacheControlValidateCache) {
[email protected]228ff742009-06-05 01:19:592972 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:402973 scoped_ptr<HttpTransaction> trans(
2974 new HttpNetworkTransaction(
[email protected]228ff742009-06-05 01:19:592975 CreateSession(&session_deps),
2976 &session_deps.socket_factory));
[email protected]1c773ea12009-04-28 19:58:422977
2978 HttpRequestInfo request;
2979 request.method = "GET";
2980 request.url = GURL("http://www.google.com/");
2981 request.load_flags = LOAD_VALIDATE_CACHE;
2982
2983 MockWrite data_writes[] = {
2984 MockWrite("GET / HTTP/1.1\r\n"
2985 "Host: www.google.com\r\n"
2986 "Connection: keep-alive\r\n"
2987 "Cache-Control: max-age=0\r\n\r\n"),
2988 };
2989
2990 // Lastly, the server responds with the actual content.
2991 MockRead data_reads[] = {
2992 MockRead("HTTP/1.0 200 OK\r\n"),
2993 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2994 MockRead("Content-Length: 100\r\n\r\n"),
2995 MockRead(false, OK),
2996 };
2997
[email protected]69b43fe2009-06-15 09:47:372998 StaticMockSocket data(data_reads, data_writes);
[email protected]228ff742009-06-05 01:19:592999 session_deps.socket_factory.AddMockSocket(&data);
[email protected]1c773ea12009-04-28 19:58:423000
3001 TestCompletionCallback callback;
3002
3003 int rv = trans->Start(&request, &callback);
3004 EXPECT_EQ(ERR_IO_PENDING, rv);
3005
3006 rv = callback.WaitForResult();
3007 EXPECT_EQ(OK, rv);
3008}
3009
3010TEST_F(HttpNetworkTransactionTest, BuildRequest_ExtraHeaders) {
[email protected]228ff742009-06-05 01:19:593011 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:403012 scoped_ptr<HttpTransaction> trans(
3013 new HttpNetworkTransaction(
[email protected]228ff742009-06-05 01:19:593014 CreateSession(&session_deps),
3015 &session_deps.socket_factory));
[email protected]1c773ea12009-04-28 19:58:423016
3017 HttpRequestInfo request;
3018 request.method = "GET";
3019 request.url = GURL("http://www.google.com/");
3020 request.extra_headers = "FooHeader: Bar\r\n";
3021
3022 MockWrite data_writes[] = {
3023 MockWrite("GET / HTTP/1.1\r\n"
3024 "Host: www.google.com\r\n"
3025 "Connection: keep-alive\r\n"
3026 "FooHeader: Bar\r\n\r\n"),
3027 };
3028
3029 // Lastly, the server responds with the actual content.
3030 MockRead data_reads[] = {
3031 MockRead("HTTP/1.0 200 OK\r\n"),
3032 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3033 MockRead("Content-Length: 100\r\n\r\n"),
3034 MockRead(false, OK),
3035 };
3036
[email protected]69b43fe2009-06-15 09:47:373037 StaticMockSocket data(data_reads, data_writes);
[email protected]228ff742009-06-05 01:19:593038 session_deps.socket_factory.AddMockSocket(&data);
[email protected]1c773ea12009-04-28 19:58:423039
3040 TestCompletionCallback callback;
3041
3042 int rv = trans->Start(&request, &callback);
3043 EXPECT_EQ(ERR_IO_PENDING, rv);
3044
3045 rv = callback.WaitForResult();
3046 EXPECT_EQ(OK, rv);
3047}
3048
[email protected]3cd17242009-06-23 02:59:023049TEST_F(HttpNetworkTransactionTest, SOCKS4_HTTP_GET) {
3050 SessionDependencies session_deps;
3051 session_deps.proxy_service.reset(CreateFixedProxyService(
3052 "socks4://myproxy:1080"));
3053
3054 scoped_ptr<HttpTransaction> trans(
3055 new HttpNetworkTransaction(
3056 CreateSession(&session_deps),
3057 &session_deps.socket_factory));
3058
3059 HttpRequestInfo request;
3060 request.method = "GET";
3061 request.url = GURL("http://www.google.com/");
3062 request.load_flags = 0;
3063
3064 char write_buffer[] = { 0x04, 0x01, 0x00, 0x50, 127, 0, 0, 1, 0 };
3065 char read_buffer[] = { 0x00, 0x5A, 0x00, 0x00, 0, 0, 0, 0 };
3066
3067 MockWrite data_writes[] = {
[email protected]e0c27be2009-07-15 13:09:353068 MockWrite(true, write_buffer, arraysize(write_buffer)),
[email protected]3cd17242009-06-23 02:59:023069 MockWrite("GET / HTTP/1.1\r\n"
3070 "Host: www.google.com\r\n"
3071 "Connection: keep-alive\r\n\r\n")
3072 };
3073
3074 MockRead data_reads[] = {
[email protected]e0c27be2009-07-15 13:09:353075 MockWrite(true, read_buffer, arraysize(read_buffer)),
[email protected]3cd17242009-06-23 02:59:023076 MockRead("HTTP/1.0 200 OK\r\n"),
3077 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
3078 MockRead("Payload"),
3079 MockRead(false, OK)
3080 };
3081
3082 StaticMockSocket data(data_reads, data_writes);
3083 session_deps.socket_factory.AddMockSocket(&data);
3084
3085 TestCompletionCallback callback;
3086
3087 int rv = trans->Start(&request, &callback);
3088 EXPECT_EQ(ERR_IO_PENDING, rv);
3089
3090 rv = callback.WaitForResult();
3091 EXPECT_EQ(OK, rv);
3092
3093 const HttpResponseInfo* response = trans->GetResponseInfo();
3094 EXPECT_FALSE(response == NULL);
3095
3096 std::string response_text;
3097 rv = ReadTransaction(trans.get(), &response_text);
3098 EXPECT_EQ(OK, rv);
3099 EXPECT_EQ("Payload", response_text);
3100}
3101
3102TEST_F(HttpNetworkTransactionTest, SOCKS4_SSL_GET) {
3103 SessionDependencies session_deps;
3104 session_deps.proxy_service.reset(CreateFixedProxyService(
3105 "socks4://myproxy:1080"));
3106
3107 scoped_ptr<HttpTransaction> trans(
3108 new HttpNetworkTransaction(
3109 CreateSession(&session_deps),
3110 &session_deps.socket_factory));
3111
3112 HttpRequestInfo request;
3113 request.method = "GET";
3114 request.url = GURL("https://www.google.com/");
3115 request.load_flags = 0;
3116
3117 unsigned char write_buffer[] = { 0x04, 0x01, 0x01, 0xBB, 127, 0, 0, 1, 0 };
3118 unsigned char read_buffer[] = { 0x00, 0x5A, 0x00, 0x00, 0, 0, 0, 0 };
3119
3120 MockWrite data_writes[] = {
[email protected]e0c27be2009-07-15 13:09:353121 MockWrite(true, reinterpret_cast<char*>(write_buffer),
3122 arraysize(write_buffer)),
[email protected]3cd17242009-06-23 02:59:023123 MockWrite("GET / HTTP/1.1\r\n"
3124 "Host: www.google.com\r\n"
3125 "Connection: keep-alive\r\n\r\n")
3126 };
3127
3128 MockRead data_reads[] = {
[email protected]e0c27be2009-07-15 13:09:353129 MockWrite(true, reinterpret_cast<char*>(read_buffer),
3130 arraysize(read_buffer)),
3131 MockRead("HTTP/1.0 200 OK\r\n"),
3132 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
3133 MockRead("Payload"),
3134 MockRead(false, OK)
3135 };
3136
3137 StaticMockSocket data(data_reads, data_writes);
3138 session_deps.socket_factory.AddMockSocket(&data);
3139
3140 MockSSLSocket ssl(true, OK);
3141 session_deps.socket_factory.AddMockSSLSocket(&ssl);
3142
3143 TestCompletionCallback callback;
3144
3145 int rv = trans->Start(&request, &callback);
3146 EXPECT_EQ(ERR_IO_PENDING, rv);
3147
3148 rv = callback.WaitForResult();
3149 EXPECT_EQ(OK, rv);
3150
3151 const HttpResponseInfo* response = trans->GetResponseInfo();
3152 EXPECT_FALSE(response == NULL);
3153
3154 std::string response_text;
3155 rv = ReadTransaction(trans.get(), &response_text);
3156 EXPECT_EQ(OK, rv);
3157 EXPECT_EQ("Payload", response_text);
3158}
3159
3160TEST_F(HttpNetworkTransactionTest, SOCKS5_HTTP_GET) {
3161 SessionDependencies session_deps;
3162 session_deps.proxy_service.reset(CreateFixedProxyService(
3163 "socks5://myproxy:1080"));
3164
3165 scoped_ptr<HttpTransaction> trans(
3166 new HttpNetworkTransaction(
3167 CreateSession(&session_deps),
3168 &session_deps.socket_factory));
3169
3170 HttpRequestInfo request;
3171 request.method = "GET";
3172 request.url = GURL("http://www.google.com/");
3173 request.load_flags = 0;
3174
3175 const char kSOCKS5GreetRequest[] = { 0x05, 0x01, 0x00 };
3176 const char kSOCKS5GreetResponse[] = { 0x05, 0x00 };
3177 const char kSOCKS5OkRequest[] =
3178 { 0x05, 0x01, 0x00, 0x01, 127, 0, 0, 1, 0x00, 0x50 };
3179 const char kSOCKS5OkResponse[] =
3180 { 0x05, 0x00, 0x00, 0x01, 127, 0, 0, 1, 0x00, 0x50 };
3181
3182 MockWrite data_writes[] = {
3183 MockWrite(true, kSOCKS5GreetRequest, arraysize(kSOCKS5GreetRequest)),
3184 MockWrite(true, kSOCKS5OkRequest, arraysize(kSOCKS5OkRequest)),
3185 MockWrite("GET / HTTP/1.1\r\n"
3186 "Host: www.google.com\r\n"
3187 "Connection: keep-alive\r\n\r\n")
3188 };
3189
3190 MockRead data_reads[] = {
3191 MockWrite(true, kSOCKS5GreetResponse, arraysize(kSOCKS5GreetResponse)),
3192 MockWrite(true, kSOCKS5OkResponse, arraysize(kSOCKS5OkResponse)),
3193 MockRead("HTTP/1.0 200 OK\r\n"),
3194 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
3195 MockRead("Payload"),
3196 MockRead(false, OK)
3197 };
3198
3199 StaticMockSocket data(data_reads, data_writes);
3200 session_deps.socket_factory.AddMockSocket(&data);
3201
3202 TestCompletionCallback callback;
3203
3204 int rv = trans->Start(&request, &callback);
3205 EXPECT_EQ(ERR_IO_PENDING, rv);
3206
3207 rv = callback.WaitForResult();
3208 EXPECT_EQ(OK, rv);
3209
3210 const HttpResponseInfo* response = trans->GetResponseInfo();
3211 EXPECT_FALSE(response == NULL);
3212
3213 std::string response_text;
3214 rv = ReadTransaction(trans.get(), &response_text);
3215 EXPECT_EQ(OK, rv);
3216 EXPECT_EQ("Payload", response_text);
3217}
3218
3219TEST_F(HttpNetworkTransactionTest, SOCKS5_SSL_GET) {
3220 SessionDependencies session_deps;
3221 session_deps.proxy_service.reset(CreateFixedProxyService(
3222 "socks5://myproxy:1080"));
3223
3224 scoped_ptr<HttpTransaction> trans(
3225 new HttpNetworkTransaction(
3226 CreateSession(&session_deps),
3227 &session_deps.socket_factory));
3228
3229 HttpRequestInfo request;
3230 request.method = "GET";
3231 request.url = GURL("https://www.google.com/");
3232 request.load_flags = 0;
3233
3234 const char kSOCKS5GreetRequest[] = { 0x05, 0x01, 0x00 };
3235 const char kSOCKS5GreetResponse[] = { 0x05, 0x00 };
3236 const unsigned char kSOCKS5OkRequest[] =
3237 { 0x05, 0x01, 0x00, 0x01, 127, 0, 0, 1, 0x01, 0xBB };
3238 const char kSOCKS5OkResponse[] =
3239 { 0x05, 0x00, 0x00, 0x01, 0, 0, 0, 0, 0x00, 0x00 };
3240
3241 MockWrite data_writes[] = {
3242 MockWrite(true, kSOCKS5GreetRequest, arraysize(kSOCKS5GreetRequest)),
3243 MockWrite(true, reinterpret_cast<const char*>(kSOCKS5OkRequest),
3244 arraysize(kSOCKS5OkRequest)),
3245 MockWrite("GET / HTTP/1.1\r\n"
3246 "Host: www.google.com\r\n"
3247 "Connection: keep-alive\r\n\r\n")
3248 };
3249
3250 MockRead data_reads[] = {
3251 MockWrite(true, kSOCKS5GreetResponse, arraysize(kSOCKS5GreetResponse)),
3252 MockWrite(true, kSOCKS5OkResponse, arraysize(kSOCKS5OkResponse)),
[email protected]3cd17242009-06-23 02:59:023253 MockRead("HTTP/1.0 200 OK\r\n"),
3254 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
3255 MockRead("Payload"),
3256 MockRead(false, OK)
3257 };
3258
3259 StaticMockSocket data(data_reads, data_writes);
3260 session_deps.socket_factory.AddMockSocket(&data);
3261
3262 MockSSLSocket ssl(true, OK);
3263 session_deps.socket_factory.AddMockSSLSocket(&ssl);
3264
3265 TestCompletionCallback callback;
3266
3267 int rv = trans->Start(&request, &callback);
3268 EXPECT_EQ(ERR_IO_PENDING, rv);
3269
3270 rv = callback.WaitForResult();
3271 EXPECT_EQ(OK, rv);
3272
3273 const HttpResponseInfo* response = trans->GetResponseInfo();
3274 EXPECT_FALSE(response == NULL);
3275
3276 std::string response_text;
3277 rv = ReadTransaction(trans.get(), &response_text);
3278 EXPECT_EQ(OK, rv);
3279 EXPECT_EQ("Payload", response_text);
3280}
3281
[email protected]04e5be32009-06-26 20:00:313282// Tests that for connection endpoints the group names are correctly set.
3283TEST_F(HttpNetworkTransactionTest, GroupNameForProxyConnections) {
3284 const struct {
3285 const std::string proxy_server;
3286 const std::string url;
3287 const std::string expected_group_name;
3288 } tests[] = {
3289 {
3290 "", // no proxy (direct)
3291 "http://www.google.com/direct",
3292 "http://www.google.com/",
3293 },
3294 {
3295 "http_proxy",
3296 "http://www.google.com/http_proxy_normal",
3297 "proxy/http_proxy:80/",
3298 },
3299 {
3300 "socks4://socks_proxy:1080",
3301 "http://www.google.com/socks4_direct",
3302 "proxy/socks4://socks_proxy:1080/http://www.google.com/",
3303 },
3304
3305 // SSL Tests
3306 {
3307 "",
3308 "https://www.google.com/direct_ssl",
3309 "https://www.google.com/",
3310 },
3311 {
3312 "http_proxy",
3313 "https://www.google.com/http_connect_ssl",
3314 "proxy/http_proxy:80/https://www.google.com/",
3315 },
3316 {
3317 "socks4://socks_proxy:1080",
3318 "https://www.google.com/socks4_ssl",
3319 "proxy/socks4://socks_proxy:1080/https://www.google.com/",
3320 },
3321 };
3322
3323 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) {
3324 SessionDependencies session_deps;
3325 session_deps.proxy_service.reset(CreateFixedProxyService(
3326 tests[i].proxy_server));
3327
3328 scoped_refptr<CaptureGroupNameSocketPool> conn_pool(
3329 new CaptureGroupNameSocketPool());
3330
3331 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
3332 session->connection_pool_ = conn_pool.get();
3333
3334 scoped_ptr<HttpTransaction> trans(
3335 new HttpNetworkTransaction(
3336 session.get(),
3337 &session_deps.socket_factory));
3338
3339 HttpRequestInfo request;
3340 request.method = "GET";
3341 request.url = GURL(tests[i].url);
3342 request.load_flags = 0;
3343
3344 TestCompletionCallback callback;
3345
3346 // We do not complete this request, the dtor will clean the transaction up.
3347 EXPECT_EQ(ERR_IO_PENDING, trans->Start(&request, &callback));
3348 EXPECT_EQ(tests[i].expected_group_name,
3349 conn_pool->last_group_name_received());
3350 }
3351}
3352
[email protected]9172a982009-06-06 00:30:253353TEST_F(HttpNetworkTransactionTest, ReconsiderProxyAfterFailedConnection) {
[email protected]5c6a17e2009-06-10 00:54:543354 SessionDependencies session_deps(
3355 CreateFixedProxyService("myproxy:70;foobar:80"));
[email protected]b59ff372009-07-15 22:04:323356
3357 session_deps.host_resolver->rules()->AddSimulatedFailure("*");
3358
[email protected]9172a982009-06-06 00:30:253359 scoped_ptr<HttpTransaction> trans(
3360 new HttpNetworkTransaction(
3361 CreateSession(&session_deps),
3362 &session_deps.socket_factory));
3363
3364 HttpRequestInfo request;
3365 request.method = "GET";
3366 request.url = GURL("http://www.google.com/");
3367
3368 TestCompletionCallback callback;
3369
3370 int rv = trans->Start(&request, &callback);
3371 EXPECT_EQ(ERR_IO_PENDING, rv);
3372
[email protected]9172a982009-06-06 00:30:253373 rv = callback.WaitForResult();
3374 EXPECT_EQ(ERR_NAME_NOT_RESOLVED, rv);
3375}
3376
[email protected]f3e6c1e2009-06-15 20:52:123377// Host resolution observer used by
3378// HttpNetworkTransactionTest.ResolveMadeWithReferrer to check that host
3379// resovle requests are issued with a referrer of |expected_referrer|.
3380class ResolutionReferrerObserver : public HostResolver::Observer {
3381 public:
3382 explicit ResolutionReferrerObserver(const GURL& expected_referrer)
3383 : expected_referrer_(expected_referrer),
3384 called_start_with_referrer_(false),
3385 called_finish_with_referrer_(false) {
3386 }
3387
3388 virtual void OnStartResolution(int id,
3389 const HostResolver::RequestInfo& info) {
3390 if (info.referrer() == expected_referrer_)
3391 called_start_with_referrer_ = true;
3392 }
3393
3394 virtual void OnFinishResolutionWithStatus(
3395 int id, bool was_resolved, const HostResolver::RequestInfo& info ) {
3396 if (info.referrer() == expected_referrer_)
3397 called_finish_with_referrer_ = true;
3398 }
3399
[email protected]eb255d32009-06-17 02:11:033400 virtual void OnCancelResolution(int id,
3401 const HostResolver::RequestInfo& info ) {
3402 FAIL() << "Should not be cancelling any requests!";
3403 }
3404
[email protected]f3e6c1e2009-06-15 20:52:123405 bool did_complete_with_expected_referrer() const {
3406 return called_start_with_referrer_ && called_finish_with_referrer_;
3407 }
3408
3409 private:
3410 GURL expected_referrer_;
3411 bool called_start_with_referrer_;
3412 bool called_finish_with_referrer_;
3413
3414 DISALLOW_COPY_AND_ASSIGN(ResolutionReferrerObserver);
3415};
3416
3417// Make sure that when HostResolver::Resolve() is invoked, it passes through
3418// the "referrer". This is depended on by the DNS prefetch observer.
3419TEST_F(HttpNetworkTransactionTest, ResolveMadeWithReferrer) {
3420 GURL referrer = GURL("http://expected-referrer/");
3421 EXPECT_TRUE(referrer.is_valid());
3422 ResolutionReferrerObserver resolution_observer(referrer);
3423
3424 SessionDependencies session_deps;
3425 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(
3426 CreateSession(&session_deps), &session_deps.socket_factory));
3427
3428 // Attach an observer to watch the host resolutions being made.
[email protected]94a0d3d92009-06-27 01:50:143429 session_deps.host_resolver->AddObserver(&resolution_observer);
[email protected]f3e6c1e2009-06-15 20:52:123430
3431 // Connect up a mock socket which will fail when reading.
3432 MockRead data_reads[] = {
3433 MockRead(false, ERR_FAILED),
3434 };
3435 StaticMockSocket data(data_reads, NULL);
3436 session_deps.socket_factory.AddMockSocket(&data);
3437
3438 // Issue a request, containing an HTTP referrer.
3439 HttpRequestInfo request;
3440 request.method = "GET";
3441 request.referrer = referrer;
3442 request.url = GURL("http://www.google.com/");
3443
3444 // Run the request until it fails reading from the socket.
3445 TestCompletionCallback callback;
3446 int rv = trans->Start(&request, &callback);
3447 EXPECT_EQ(ERR_IO_PENDING, rv);
3448 rv = callback.WaitForResult();
3449 EXPECT_EQ(ERR_FAILED, rv);
3450
3451 // Check that the host resolution observer saw |referrer|.
3452 EXPECT_TRUE(resolution_observer.did_complete_with_expected_referrer());
3453}
3454
[email protected]3b9cca42009-06-16 01:08:283455// Make sure that when the load flags contain LOAD_BYPASS_CACHE, the resolver's
3456// host cache is bypassed.
3457TEST_F(HttpNetworkTransactionTest, BypassHostCacheOnRefresh) {
3458 SessionDependencies session_deps;
[email protected]b59ff372009-07-15 22:04:323459
[email protected]a2c2fb92009-07-18 07:31:043460 // Select a host resolver that does caching.
3461 session_deps.host_resolver = new MockCachingHostResolver;
[email protected]b59ff372009-07-15 22:04:323462
[email protected]3b9cca42009-06-16 01:08:283463 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(
3464 CreateSession(&session_deps), &session_deps.socket_factory));
3465
3466 // Warm up the host cache so it has an entry for "www.google.com" (by doing
3467 // a synchronous lookup.)
3468 AddressList addrlist;
[email protected]94a0d3d92009-06-27 01:50:143469 int rv = session_deps.host_resolver->Resolve(
[email protected]3b9cca42009-06-16 01:08:283470 HostResolver::RequestInfo("www.google.com", 80), &addrlist, NULL, NULL);
3471 EXPECT_EQ(OK, rv);
3472
3473 // Verify that it was added to host cache, by doing a subsequent async lookup
3474 // and confirming it completes synchronously.
3475 TestCompletionCallback resolve_callback;
[email protected]94a0d3d92009-06-27 01:50:143476 rv = session_deps.host_resolver->Resolve(
[email protected]3b9cca42009-06-16 01:08:283477 HostResolver::RequestInfo("www.google.com", 80), &addrlist,
3478 &resolve_callback, NULL);
[email protected]b59ff372009-07-15 22:04:323479 ASSERT_EQ(OK, rv);
[email protected]3b9cca42009-06-16 01:08:283480
3481 // Inject a failure the next time that "www.google.com" is resolved. This way
3482 // we can tell if the next lookup hit the cache, or the "network".
3483 // (cache --> success, "network" --> failure).
[email protected]b59ff372009-07-15 22:04:323484 session_deps.host_resolver->rules()->AddSimulatedFailure("www.google.com");
[email protected]3b9cca42009-06-16 01:08:283485
3486 // Connect up a mock socket which will fail with ERR_UNEXPECTED during the
3487 // first read -- this won't be reached as the host resolution will fail first.
3488 MockRead data_reads[] = { MockRead(false, ERR_UNEXPECTED) };
3489 StaticMockSocket data(data_reads, NULL);
3490 session_deps.socket_factory.AddMockSocket(&data);
3491
3492 // Issue a request, asking to bypass the cache(s).
3493 HttpRequestInfo request;
3494 request.method = "GET";
3495 request.load_flags = LOAD_BYPASS_CACHE;
3496 request.url = GURL("http://www.google.com/");
3497
3498 // Run the request.
3499 TestCompletionCallback callback;
3500 rv = trans->Start(&request, &callback);
3501 ASSERT_EQ(ERR_IO_PENDING, rv);
3502 rv = callback.WaitForResult();
3503
3504 // If we bypassed the cache, we would have gotten a failure while resolving
3505 // "www.google.com".
3506 EXPECT_EQ(ERR_NAME_NOT_RESOLVED, rv);
3507}
3508
[email protected]89ceba9a2009-03-21 03:46:063509} // namespace net