blob: ac10c9958830dd458fe4cbe86046c7d0254bcb54 [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]80d6524d2009-08-18 03:58:0946 scoped_refptr<ProxyService> proxy_service;
[email protected]228ff742009-06-05 01:19:5947 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]80d6524d2009-08-18 03:58:0959 session_deps->proxy_service,
[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]684970b2009-08-14 04:54:4699 int rv = trans->Start(&request, &callback, NULL);
[email protected]ff007e162009-05-23 09:13:15100 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 }
[email protected]d80a4322009-08-14 07:07:49172 const std::string last_group_name_received() const {
173 return last_group_name_;
174 }
175
[email protected]684970b2009-08-14 04:54:46176 virtual int RequestSocket(const std::string& group_name,
[email protected]d80a4322009-08-14 07:07:49177 const void* socket_params,
[email protected]04e5be32009-06-26 20:00:31178 int priority,
179 ClientSocketHandle* handle,
[email protected]684970b2009-08-14 04:54:46180 CompletionCallback* callback,
181 LoadLog* load_log) {
[email protected]04e5be32009-06-26 20:00:31182 last_group_name_ = group_name;
183 return ERR_IO_PENDING;
184 }
[email protected]04e5be32009-06-26 20:00:31185 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 }
[email protected]d80a4322009-08-14 07:07:49203
204 private:
[email protected]04e5be32009-06-26 20:00:31205 std::string last_group_name_;
206};
207
[email protected]231d5a32008-09-13 00:45:27208//-----------------------------------------------------------------------------
209
210TEST_F(HttpNetworkTransactionTest, Basic) {
[email protected]228ff742009-06-05 01:19:59211 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:40212 scoped_ptr<HttpTransaction> trans(
213 new HttpNetworkTransaction(
[email protected]228ff742009-06-05 01:19:59214 CreateSession(&session_deps),
215 &session_deps.socket_factory));
[email protected]231d5a32008-09-13 00:45:27216}
217
218TEST_F(HttpNetworkTransactionTest, SimpleGET) {
219 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35220 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
221 MockRead("hello world"),
[email protected]1c773ea12009-04-28 19:58:42222 MockRead(false, OK),
[email protected]231d5a32008-09-13 00:45:27223 };
[email protected]231d5a32008-09-13 00:45:27224 SimpleGetHelperResult out = SimpleGetHelper(data_reads);
[email protected]1c773ea12009-04-28 19:58:42225 EXPECT_EQ(OK, out.rv);
[email protected]231d5a32008-09-13 00:45:27226 EXPECT_EQ("HTTP/1.0 200 OK", out.status_line);
227 EXPECT_EQ("hello world", out.response_data);
228}
229
230// Response with no status line.
231TEST_F(HttpNetworkTransactionTest, SimpleGETNoHeaders) {
232 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35233 MockRead("hello world"),
[email protected]1c773ea12009-04-28 19:58:42234 MockRead(false, OK),
[email protected]231d5a32008-09-13 00:45:27235 };
[email protected]231d5a32008-09-13 00:45:27236 SimpleGetHelperResult out = SimpleGetHelper(data_reads);
[email protected]1c773ea12009-04-28 19:58:42237 EXPECT_EQ(OK, out.rv);
[email protected]231d5a32008-09-13 00:45:27238 EXPECT_EQ("HTTP/0.9 200 OK", out.status_line);
239 EXPECT_EQ("hello world", out.response_data);
240}
241
242// Allow up to 4 bytes of junk to precede status line.
243TEST_F(HttpNetworkTransactionTest, StatusLineJunk2Bytes) {
244 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35245 MockRead("xxxHTTP/1.0 404 Not Found\nServer: blah\n\nDATA"),
[email protected]1c773ea12009-04-28 19:58:42246 MockRead(false, OK),
[email protected]231d5a32008-09-13 00:45:27247 };
248 SimpleGetHelperResult out = SimpleGetHelper(data_reads);
[email protected]1c773ea12009-04-28 19:58:42249 EXPECT_EQ(OK, out.rv);
[email protected]231d5a32008-09-13 00:45:27250 EXPECT_EQ("HTTP/1.0 404 Not Found", out.status_line);
251 EXPECT_EQ("DATA", out.response_data);
252}
253
254// Allow up to 4 bytes of junk to precede status line.
255TEST_F(HttpNetworkTransactionTest, StatusLineJunk4Bytes) {
256 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35257 MockRead("\n\nQJHTTP/1.0 404 Not Found\nServer: blah\n\nDATA"),
[email protected]1c773ea12009-04-28 19:58:42258 MockRead(false, OK),
[email protected]231d5a32008-09-13 00:45:27259 };
260 SimpleGetHelperResult out = SimpleGetHelper(data_reads);
[email protected]1c773ea12009-04-28 19:58:42261 EXPECT_EQ(OK, out.rv);
[email protected]231d5a32008-09-13 00:45:27262 EXPECT_EQ("HTTP/1.0 404 Not Found", out.status_line);
263 EXPECT_EQ("DATA", out.response_data);
264}
265
266// Beyond 4 bytes of slop and it should fail to find a status line.
267TEST_F(HttpNetworkTransactionTest, StatusLineJunk5Bytes) {
268 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35269 MockRead("xxxxxHTTP/1.1 404 Not Found\nServer: blah"),
[email protected]1c773ea12009-04-28 19:58:42270 MockRead(false, OK),
[email protected]231d5a32008-09-13 00:45:27271 };
272 SimpleGetHelperResult out = SimpleGetHelper(data_reads);
[email protected]1c773ea12009-04-28 19:58:42273 EXPECT_EQ(OK, out.rv);
[email protected]3d2a59b2008-09-26 19:44:25274 EXPECT_EQ("HTTP/0.9 200 OK", out.status_line);
275 EXPECT_EQ("xxxxxHTTP/1.1 404 Not Found\nServer: blah", out.response_data);
[email protected]231d5a32008-09-13 00:45:27276}
277
278// Same as StatusLineJunk4Bytes, except the read chunks are smaller.
279TEST_F(HttpNetworkTransactionTest, StatusLineJunk4Bytes_Slow) {
280 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35281 MockRead("\n"),
282 MockRead("\n"),
283 MockRead("Q"),
284 MockRead("J"),
285 MockRead("HTTP/1.0 404 Not Found\nServer: blah\n\nDATA"),
[email protected]1c773ea12009-04-28 19:58:42286 MockRead(false, OK),
[email protected]231d5a32008-09-13 00:45:27287 };
288 SimpleGetHelperResult out = SimpleGetHelper(data_reads);
[email protected]1c773ea12009-04-28 19:58:42289 EXPECT_EQ(OK, out.rv);
[email protected]231d5a32008-09-13 00:45:27290 EXPECT_EQ("HTTP/1.0 404 Not Found", out.status_line);
291 EXPECT_EQ("DATA", out.response_data);
292}
293
294// Close the connection before enough bytes to have a status line.
295TEST_F(HttpNetworkTransactionTest, StatusLinePartial) {
296 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35297 MockRead("HTT"),
[email protected]1c773ea12009-04-28 19:58:42298 MockRead(false, OK),
[email protected]231d5a32008-09-13 00:45:27299 };
300 SimpleGetHelperResult out = SimpleGetHelper(data_reads);
[email protected]1c773ea12009-04-28 19:58:42301 EXPECT_EQ(OK, out.rv);
[email protected]231d5a32008-09-13 00:45:27302 EXPECT_EQ("HTTP/0.9 200 OK", out.status_line);
303 EXPECT_EQ("HTT", out.response_data);
initial.commit586acc5fe2008-07-26 22:42:52304}
305
[email protected]f9d44aa2008-09-23 23:57:17306// Simulate a 204 response, lacking a Content-Length header, sent over a
307// persistent connection. The response should still terminate since a 204
308// cannot have a response body.
309TEST_F(HttpNetworkTransactionTest, StopsReading204) {
310 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35311 MockRead("HTTP/1.1 204 No Content\r\n\r\n"),
312 MockRead("junk"), // Should not be read!!
[email protected]1c773ea12009-04-28 19:58:42313 MockRead(false, OK),
[email protected]f9d44aa2008-09-23 23:57:17314 };
315 SimpleGetHelperResult out = SimpleGetHelper(data_reads);
[email protected]1c773ea12009-04-28 19:58:42316 EXPECT_EQ(OK, out.rv);
[email protected]f9d44aa2008-09-23 23:57:17317 EXPECT_EQ("HTTP/1.1 204 No Content", out.status_line);
318 EXPECT_EQ("", out.response_data);
319}
320
[email protected]ef0faf2e72009-03-05 23:27:23321// Do a request using the HEAD method. Verify that we don't try to read the
322// message body (since HEAD has none).
323TEST_F(HttpNetworkTransactionTest, Head) {
[email protected]228ff742009-06-05 01:19:59324 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:40325 scoped_ptr<HttpTransaction> trans(
326 new HttpNetworkTransaction(
[email protected]228ff742009-06-05 01:19:59327 CreateSession(&session_deps),
328 &session_deps.socket_factory));
[email protected]ef0faf2e72009-03-05 23:27:23329
[email protected]1c773ea12009-04-28 19:58:42330 HttpRequestInfo request;
[email protected]ef0faf2e72009-03-05 23:27:23331 request.method = "HEAD";
332 request.url = GURL("http://www.google.com/");
333 request.load_flags = 0;
334
335 MockWrite data_writes1[] = {
336 MockWrite("HEAD / HTTP/1.1\r\n"
337 "Host: www.google.com\r\n"
338 "Connection: keep-alive\r\n"
339 "Content-Length: 0\r\n\r\n"),
340 };
341 MockRead data_reads1[] = {
342 MockRead("HTTP/1.1 404 Not Found\r\n"),
343 MockRead("Server: Blah\r\n"),
344 MockRead("Content-Length: 1234\r\n\r\n"),
345
346 // No response body because the test stops reading here.
[email protected]1c773ea12009-04-28 19:58:42347 MockRead(false, ERR_UNEXPECTED), // Should not be reached.
[email protected]ef0faf2e72009-03-05 23:27:23348 };
349
[email protected]69b43fe2009-06-15 09:47:37350 StaticMockSocket data1(data_reads1, data_writes1);
[email protected]228ff742009-06-05 01:19:59351 session_deps.socket_factory.AddMockSocket(&data1);
[email protected]ef0faf2e72009-03-05 23:27:23352
353 TestCompletionCallback callback1;
354
[email protected]684970b2009-08-14 04:54:46355 int rv = trans->Start(&request, &callback1, NULL);
[email protected]1c773ea12009-04-28 19:58:42356 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]ef0faf2e72009-03-05 23:27:23357
358 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42359 EXPECT_EQ(OK, rv);
[email protected]ef0faf2e72009-03-05 23:27:23360
[email protected]1c773ea12009-04-28 19:58:42361 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]ef0faf2e72009-03-05 23:27:23362 EXPECT_FALSE(response == NULL);
363
364 // Check that the headers got parsed.
365 EXPECT_TRUE(response->headers != NULL);
366 EXPECT_EQ(1234, response->headers->GetContentLength());
367 EXPECT_EQ("HTTP/1.1 404 Not Found", response->headers->GetStatusLine());
368
369 std::string server_header;
370 void* iter = NULL;
371 bool has_server_header = response->headers->EnumerateHeader(
372 &iter, "Server", &server_header);
373 EXPECT_TRUE(has_server_header);
374 EXPECT_EQ("Blah", server_header);
375
376 // Reading should give EOF right away, since there is no message body
377 // (despite non-zero content-length).
378 std::string response_data;
379 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:42380 EXPECT_EQ(OK, rv);
[email protected]ef0faf2e72009-03-05 23:27:23381 EXPECT_EQ("", response_data);
382}
383
initial.commit586acc5fe2008-07-26 22:42:52384TEST_F(HttpNetworkTransactionTest, ReuseConnection) {
[email protected]228ff742009-06-05 01:19:59385 SessionDependencies session_deps;
386 scoped_refptr<HttpNetworkSession> session = CreateSession(&session_deps);
initial.commit586acc5fe2008-07-26 22:42:52387
388 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35389 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
390 MockRead("hello"),
391 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
392 MockRead("world"),
[email protected]1c773ea12009-04-28 19:58:42393 MockRead(false, OK),
initial.commit586acc5fe2008-07-26 22:42:52394 };
[email protected]69b43fe2009-06-15 09:47:37395 StaticMockSocket data(data_reads, NULL);
[email protected]228ff742009-06-05 01:19:59396 session_deps.socket_factory.AddMockSocket(&data);
initial.commit586acc5fe2008-07-26 22:42:52397
398 const char* kExpectedResponseData[] = {
399 "hello", "world"
400 };
401
402 for (int i = 0; i < 2; ++i) {
[email protected]1c773ea12009-04-28 19:58:42403 scoped_ptr<HttpTransaction> trans(
[email protected]228ff742009-06-05 01:19:59404 new HttpNetworkTransaction(session, &session_deps.socket_factory));
initial.commit586acc5fe2008-07-26 22:42:52405
[email protected]1c773ea12009-04-28 19:58:42406 HttpRequestInfo request;
initial.commit586acc5fe2008-07-26 22:42:52407 request.method = "GET";
408 request.url = GURL("http://www.google.com/");
409 request.load_flags = 0;
410
411 TestCompletionCallback callback;
412
[email protected]684970b2009-08-14 04:54:46413 int rv = trans->Start(&request, &callback, NULL);
[email protected]1c773ea12009-04-28 19:58:42414 EXPECT_EQ(ERR_IO_PENDING, rv);
initial.commit586acc5fe2008-07-26 22:42:52415
416 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42417 EXPECT_EQ(OK, rv);
initial.commit586acc5fe2008-07-26 22:42:52418
[email protected]1c773ea12009-04-28 19:58:42419 const HttpResponseInfo* response = trans->GetResponseInfo();
initial.commit586acc5fe2008-07-26 22:42:52420 EXPECT_TRUE(response != NULL);
421
422 EXPECT_TRUE(response->headers != NULL);
[email protected]3d2a59b2008-09-26 19:44:25423 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
initial.commit586acc5fe2008-07-26 22:42:52424
425 std::string response_data;
[email protected]af4876d2008-10-21 23:10:57426 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:42427 EXPECT_EQ(OK, rv);
[email protected]3d2a59b2008-09-26 19:44:25428 EXPECT_EQ(kExpectedResponseData[i], response_data);
initial.commit586acc5fe2008-07-26 22:42:52429 }
430}
431
432TEST_F(HttpNetworkTransactionTest, Ignores100) {
[email protected]228ff742009-06-05 01:19:59433 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:40434 scoped_ptr<HttpTransaction> trans(
435 new HttpNetworkTransaction(
[email protected]228ff742009-06-05 01:19:59436 CreateSession(&session_deps),
437 &session_deps.socket_factory));
initial.commit586acc5fe2008-07-26 22:42:52438
[email protected]1c773ea12009-04-28 19:58:42439 HttpRequestInfo request;
initial.commit586acc5fe2008-07-26 22:42:52440 request.method = "POST";
441 request.url = GURL("http://www.foo.com/");
[email protected]1c773ea12009-04-28 19:58:42442 request.upload_data = new UploadData;
initial.commit586acc5fe2008-07-26 22:42:52443 request.upload_data->AppendBytes("foo", 3);
444 request.load_flags = 0;
445
446 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35447 MockRead("HTTP/1.0 100 Continue\r\n\r\n"),
448 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
449 MockRead("hello world"),
[email protected]1c773ea12009-04-28 19:58:42450 MockRead(false, OK),
initial.commit586acc5fe2008-07-26 22:42:52451 };
[email protected]69b43fe2009-06-15 09:47:37452 StaticMockSocket data(data_reads, NULL);
[email protected]228ff742009-06-05 01:19:59453 session_deps.socket_factory.AddMockSocket(&data);
initial.commit586acc5fe2008-07-26 22:42:52454
455 TestCompletionCallback callback;
456
[email protected]684970b2009-08-14 04:54:46457 int rv = trans->Start(&request, &callback, NULL);
[email protected]1c773ea12009-04-28 19:58:42458 EXPECT_EQ(ERR_IO_PENDING, rv);
initial.commit586acc5fe2008-07-26 22:42:52459
460 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42461 EXPECT_EQ(OK, rv);
initial.commit586acc5fe2008-07-26 22:42:52462
[email protected]1c773ea12009-04-28 19:58:42463 const HttpResponseInfo* response = trans->GetResponseInfo();
initial.commit586acc5fe2008-07-26 22:42:52464 EXPECT_TRUE(response != NULL);
465
466 EXPECT_TRUE(response->headers != NULL);
[email protected]3d2a59b2008-09-26 19:44:25467 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
initial.commit586acc5fe2008-07-26 22:42:52468
469 std::string response_data;
[email protected]af4876d2008-10-21 23:10:57470 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:42471 EXPECT_EQ(OK, rv);
[email protected]3d2a59b2008-09-26 19:44:25472 EXPECT_EQ("hello world", response_data);
initial.commit586acc5fe2008-07-26 22:42:52473}
474
[email protected]3a2d3662009-03-27 03:49:14475// This test is almost the same as Ignores100 above, but the response contains
476// a 102 instead of a 100. Also, instead of HTTP/1.0 the response is
477// HTTP/1.1.
478TEST_F(HttpNetworkTransactionTest, Ignores1xx) {
[email protected]228ff742009-06-05 01:19:59479 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:40480 scoped_ptr<HttpTransaction> trans(
481 new HttpNetworkTransaction(
[email protected]228ff742009-06-05 01:19:59482 CreateSession(&session_deps),
483 &session_deps.socket_factory));
[email protected]3a2d3662009-03-27 03:49:14484
[email protected]1c773ea12009-04-28 19:58:42485 HttpRequestInfo request;
[email protected]3a2d3662009-03-27 03:49:14486 request.method = "GET";
487 request.url = GURL("http://www.foo.com/");
488 request.load_flags = 0;
489
490 MockRead data_reads[] = {
491 MockRead("HTTP/1.1 102 Unspecified status code\r\n\r\n"),
492 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
493 MockRead("hello world"),
[email protected]1c773ea12009-04-28 19:58:42494 MockRead(false, OK),
[email protected]3a2d3662009-03-27 03:49:14495 };
[email protected]69b43fe2009-06-15 09:47:37496 StaticMockSocket data(data_reads, NULL);
[email protected]228ff742009-06-05 01:19:59497 session_deps.socket_factory.AddMockSocket(&data);
[email protected]3a2d3662009-03-27 03:49:14498
499 TestCompletionCallback callback;
500
[email protected]684970b2009-08-14 04:54:46501 int rv = trans->Start(&request, &callback, NULL);
[email protected]1c773ea12009-04-28 19:58:42502 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]3a2d3662009-03-27 03:49:14503
504 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42505 EXPECT_EQ(OK, rv);
[email protected]3a2d3662009-03-27 03:49:14506
[email protected]1c773ea12009-04-28 19:58:42507 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]3a2d3662009-03-27 03:49:14508 EXPECT_TRUE(response != NULL);
509
510 EXPECT_TRUE(response->headers != NULL);
511 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
512
513 std::string response_data;
514 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:42515 EXPECT_EQ(OK, rv);
[email protected]3a2d3662009-03-27 03:49:14516 EXPECT_EQ("hello world", response_data);
517}
518
[email protected]3d2a59b2008-09-26 19:44:25519// read_failure specifies a read failure that should cause the network
520// transaction to resend the request.
521void HttpNetworkTransactionTest::KeepAliveConnectionResendRequestTest(
522 const MockRead& read_failure) {
[email protected]228ff742009-06-05 01:19:59523 SessionDependencies session_deps;
524 scoped_refptr<HttpNetworkSession> session = CreateSession(&session_deps);
initial.commit586acc5fe2008-07-26 22:42:52525
[email protected]1c773ea12009-04-28 19:58:42526 HttpRequestInfo request;
initial.commit586acc5fe2008-07-26 22:42:52527 request.method = "GET";
528 request.url = GURL("http://www.foo.com/");
529 request.load_flags = 0;
530
531 MockRead data1_reads[] = {
[email protected]217e6022008-09-29 18:18:35532 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
533 MockRead("hello"),
[email protected]3d2a59b2008-09-26 19:44:25534 read_failure, // Now, we reuse the connection and fail the first read.
initial.commit586acc5fe2008-07-26 22:42:52535 };
[email protected]69b43fe2009-06-15 09:47:37536 StaticMockSocket data1(data1_reads, NULL);
[email protected]228ff742009-06-05 01:19:59537 session_deps.socket_factory.AddMockSocket(&data1);
initial.commit586acc5fe2008-07-26 22:42:52538
539 MockRead data2_reads[] = {
[email protected]217e6022008-09-29 18:18:35540 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
541 MockRead("world"),
[email protected]1c773ea12009-04-28 19:58:42542 MockRead(true, OK),
initial.commit586acc5fe2008-07-26 22:42:52543 };
[email protected]69b43fe2009-06-15 09:47:37544 StaticMockSocket data2(data2_reads, NULL);
[email protected]228ff742009-06-05 01:19:59545 session_deps.socket_factory.AddMockSocket(&data2);
initial.commit586acc5fe2008-07-26 22:42:52546
547 const char* kExpectedResponseData[] = {
548 "hello", "world"
549 };
550
551 for (int i = 0; i < 2; ++i) {
552 TestCompletionCallback callback;
553
[email protected]1c773ea12009-04-28 19:58:42554 scoped_ptr<HttpTransaction> trans(
[email protected]228ff742009-06-05 01:19:59555 new HttpNetworkTransaction(session, &session_deps.socket_factory));
initial.commit586acc5fe2008-07-26 22:42:52556
[email protected]684970b2009-08-14 04:54:46557 int rv = trans->Start(&request, &callback, NULL);
[email protected]1c773ea12009-04-28 19:58:42558 EXPECT_EQ(ERR_IO_PENDING, rv);
initial.commit586acc5fe2008-07-26 22:42:52559
560 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42561 EXPECT_EQ(OK, rv);
initial.commit586acc5fe2008-07-26 22:42:52562
[email protected]1c773ea12009-04-28 19:58:42563 const HttpResponseInfo* response = trans->GetResponseInfo();
initial.commit586acc5fe2008-07-26 22:42:52564 EXPECT_TRUE(response != NULL);
565
566 EXPECT_TRUE(response->headers != NULL);
[email protected]3d2a59b2008-09-26 19:44:25567 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
initial.commit586acc5fe2008-07-26 22:42:52568
569 std::string response_data;
[email protected]af4876d2008-10-21 23:10:57570 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:42571 EXPECT_EQ(OK, rv);
[email protected]3d2a59b2008-09-26 19:44:25572 EXPECT_EQ(kExpectedResponseData[i], response_data);
initial.commit586acc5fe2008-07-26 22:42:52573 }
574}
[email protected]3d2a59b2008-09-26 19:44:25575
576TEST_F(HttpNetworkTransactionTest, KeepAliveConnectionReset) {
[email protected]1c773ea12009-04-28 19:58:42577 MockRead read_failure(true, ERR_CONNECTION_RESET);
[email protected]3d2a59b2008-09-26 19:44:25578 KeepAliveConnectionResendRequestTest(read_failure);
579}
580
581TEST_F(HttpNetworkTransactionTest, KeepAliveConnectionEOF) {
[email protected]1c773ea12009-04-28 19:58:42582 MockRead read_failure(false, OK); // EOF
[email protected]3d2a59b2008-09-26 19:44:25583 KeepAliveConnectionResendRequestTest(read_failure);
584}
585
586TEST_F(HttpNetworkTransactionTest, NonKeepAliveConnectionReset) {
[email protected]228ff742009-06-05 01:19:59587 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:40588 scoped_ptr<HttpTransaction> trans(
589 new HttpNetworkTransaction(
[email protected]228ff742009-06-05 01:19:59590 CreateSession(&session_deps),
591 &session_deps.socket_factory));
[email protected]3d2a59b2008-09-26 19:44:25592
[email protected]1c773ea12009-04-28 19:58:42593 HttpRequestInfo request;
[email protected]3d2a59b2008-09-26 19:44:25594 request.method = "GET";
595 request.url = GURL("http://www.google.com/");
596 request.load_flags = 0;
597
598 MockRead data_reads[] = {
[email protected]1c773ea12009-04-28 19:58:42599 MockRead(true, ERR_CONNECTION_RESET),
[email protected]217e6022008-09-29 18:18:35600 MockRead("HTTP/1.0 200 OK\r\n\r\n"), // Should not be used
601 MockRead("hello world"),
[email protected]1c773ea12009-04-28 19:58:42602 MockRead(false, OK),
[email protected]3d2a59b2008-09-26 19:44:25603 };
[email protected]69b43fe2009-06-15 09:47:37604 StaticMockSocket data(data_reads, NULL);
[email protected]228ff742009-06-05 01:19:59605 session_deps.socket_factory.AddMockSocket(&data);
[email protected]3d2a59b2008-09-26 19:44:25606
607 TestCompletionCallback callback;
608
[email protected]684970b2009-08-14 04:54:46609 int rv = trans->Start(&request, &callback, NULL);
[email protected]1c773ea12009-04-28 19:58:42610 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]3d2a59b2008-09-26 19:44:25611
612 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42613 EXPECT_EQ(ERR_CONNECTION_RESET, rv);
[email protected]3d2a59b2008-09-26 19:44:25614
[email protected]1c773ea12009-04-28 19:58:42615 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]3d2a59b2008-09-26 19:44:25616 EXPECT_TRUE(response == NULL);
[email protected]3d2a59b2008-09-26 19:44:25617}
618
619// What do various browsers do when the server closes a non-keepalive
620// connection without sending any response header or body?
621//
622// IE7: error page
623// Safari 3.1.2 (Windows): error page
624// Firefox 3.0.1: blank page
625// Opera 9.52: after five attempts, blank page
[email protected]1c773ea12009-04-28 19:58:42626// Us with WinHTTP: error page (ERR_INVALID_RESPONSE)
627// Us: error page (EMPTY_RESPONSE)
[email protected]3d2a59b2008-09-26 19:44:25628TEST_F(HttpNetworkTransactionTest, NonKeepAliveConnectionEOF) {
629 MockRead data_reads[] = {
[email protected]1c773ea12009-04-28 19:58:42630 MockRead(false, OK), // EOF
[email protected]217e6022008-09-29 18:18:35631 MockRead("HTTP/1.0 200 OK\r\n\r\n"), // Should not be used
632 MockRead("hello world"),
[email protected]1c773ea12009-04-28 19:58:42633 MockRead(false, OK),
[email protected]3d2a59b2008-09-26 19:44:25634 };
635 SimpleGetHelperResult out = SimpleGetHelper(data_reads);
[email protected]1c773ea12009-04-28 19:58:42636 EXPECT_EQ(ERR_EMPTY_RESPONSE, out.rv);
[email protected]3d2a59b2008-09-26 19:44:25637}
[email protected]038e9a32008-10-08 22:40:16638
639// Test the request-challenge-retry sequence for basic auth.
640// (basic auth is the easiest to mock, because it has no randomness).
641TEST_F(HttpNetworkTransactionTest, BasicAuth) {
[email protected]228ff742009-06-05 01:19:59642 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:40643 scoped_ptr<HttpTransaction> trans(
644 new HttpNetworkTransaction(
[email protected]228ff742009-06-05 01:19:59645 CreateSession(&session_deps),
646 &session_deps.socket_factory));
[email protected]038e9a32008-10-08 22:40:16647
[email protected]1c773ea12009-04-28 19:58:42648 HttpRequestInfo request;
[email protected]038e9a32008-10-08 22:40:16649 request.method = "GET";
650 request.url = GURL("http://www.google.com/");
651 request.load_flags = 0;
652
[email protected]f9ee6b52008-11-08 06:46:23653 MockWrite data_writes1[] = {
654 MockWrite("GET / HTTP/1.1\r\n"
655 "Host: www.google.com\r\n"
656 "Connection: keep-alive\r\n\r\n"),
657 };
658
[email protected]038e9a32008-10-08 22:40:16659 MockRead data_reads1[] = {
660 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
661 // Give a couple authenticate options (only the middle one is actually
662 // supported).
[email protected]aaead502008-10-15 00:20:11663 MockRead("WWW-Authenticate: Basic\r\n"), // Malformed
[email protected]038e9a32008-10-08 22:40:16664 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
665 MockRead("WWW-Authenticate: UNSUPPORTED realm=\"FOO\"\r\n"),
666 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
667 // Large content-length -- won't matter, as connection will be reset.
668 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:42669 MockRead(false, ERR_FAILED),
[email protected]038e9a32008-10-08 22:40:16670 };
671
672 // After calling trans->RestartWithAuth(), this is the request we should
673 // be issuing -- the final header line contains the credentials.
674 MockWrite data_writes2[] = {
675 MockWrite("GET / HTTP/1.1\r\n"
676 "Host: www.google.com\r\n"
677 "Connection: keep-alive\r\n"
678 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
679 };
680
681 // Lastly, the server responds with the actual content.
682 MockRead data_reads2[] = {
683 MockRead("HTTP/1.0 200 OK\r\n"),
684 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
685 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:42686 MockRead(false, OK),
[email protected]038e9a32008-10-08 22:40:16687 };
688
[email protected]69b43fe2009-06-15 09:47:37689 StaticMockSocket data1(data_reads1, data_writes1);
690 StaticMockSocket data2(data_reads2, data_writes2);
[email protected]228ff742009-06-05 01:19:59691 session_deps.socket_factory.AddMockSocket(&data1);
692 session_deps.socket_factory.AddMockSocket(&data2);
[email protected]038e9a32008-10-08 22:40:16693
694 TestCompletionCallback callback1;
695
[email protected]684970b2009-08-14 04:54:46696 int rv = trans->Start(&request, &callback1, NULL);
[email protected]1c773ea12009-04-28 19:58:42697 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]038e9a32008-10-08 22:40:16698
699 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42700 EXPECT_EQ(OK, rv);
[email protected]038e9a32008-10-08 22:40:16701
[email protected]1c773ea12009-04-28 19:58:42702 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]038e9a32008-10-08 22:40:16703 EXPECT_FALSE(response == NULL);
704
705 // The password prompt info should have been set in response->auth_challenge.
706 EXPECT_FALSE(response->auth_challenge.get() == NULL);
707
[email protected]71e4573a2009-05-21 22:03:00708 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
[email protected]038e9a32008-10-08 22:40:16709 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
710 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
711
712 TestCompletionCallback callback2;
713
714 rv = trans->RestartWithAuth(L"foo", L"bar", &callback2);
[email protected]1c773ea12009-04-28 19:58:42715 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]038e9a32008-10-08 22:40:16716
717 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42718 EXPECT_EQ(OK, rv);
[email protected]038e9a32008-10-08 22:40:16719
720 response = trans->GetResponseInfo();
721 EXPECT_FALSE(response == NULL);
722 EXPECT_TRUE(response->auth_challenge.get() == NULL);
723 EXPECT_EQ(100, response->headers->GetContentLength());
[email protected]038e9a32008-10-08 22:40:16724}
725
[email protected]2d2697f92009-02-18 21:00:32726// Test the request-challenge-retry sequence for basic auth, over a keep-alive
727// connection.
728TEST_F(HttpNetworkTransactionTest, BasicAuthKeepAlive) {
[email protected]228ff742009-06-05 01:19:59729 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:40730 scoped_ptr<HttpTransaction> trans(
731 new HttpNetworkTransaction(
[email protected]228ff742009-06-05 01:19:59732 CreateSession(&session_deps),
733 &session_deps.socket_factory));
[email protected]2d2697f92009-02-18 21:00:32734
[email protected]1c773ea12009-04-28 19:58:42735 HttpRequestInfo request;
[email protected]2d2697f92009-02-18 21:00:32736 request.method = "GET";
737 request.url = GURL("http://www.google.com/");
738 request.load_flags = 0;
739
740 MockWrite data_writes1[] = {
741 MockWrite("GET / HTTP/1.1\r\n"
742 "Host: www.google.com\r\n"
743 "Connection: keep-alive\r\n\r\n"),
744
745 // After calling trans->RestartWithAuth(), this is the request we should
746 // be issuing -- the final header line contains the credentials.
747 MockWrite("GET / HTTP/1.1\r\n"
748 "Host: www.google.com\r\n"
749 "Connection: keep-alive\r\n"
750 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
751 };
752
753 MockRead data_reads1[] = {
754 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
755 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
756 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
757 MockRead("Content-Length: 14\r\n\r\n"),
758 MockRead("Unauthorized\r\n"),
759
760 // Lastly, the server responds with the actual content.
761 MockRead("HTTP/1.1 200 OK\r\n"),
762 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
763 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:42764 MockRead(false, OK),
[email protected]2d2697f92009-02-18 21:00:32765 };
766
[email protected]69b43fe2009-06-15 09:47:37767 StaticMockSocket data1(data_reads1, data_writes1);
[email protected]228ff742009-06-05 01:19:59768 session_deps.socket_factory.AddMockSocket(&data1);
[email protected]2d2697f92009-02-18 21:00:32769
770 TestCompletionCallback callback1;
771
[email protected]684970b2009-08-14 04:54:46772 int rv = trans->Start(&request, &callback1, NULL);
[email protected]1c773ea12009-04-28 19:58:42773 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:32774
775 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42776 EXPECT_EQ(OK, rv);
[email protected]2d2697f92009-02-18 21:00:32777
[email protected]1c773ea12009-04-28 19:58:42778 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]2d2697f92009-02-18 21:00:32779 EXPECT_FALSE(response == NULL);
780
781 // The password prompt info should have been set in response->auth_challenge.
782 EXPECT_FALSE(response->auth_challenge.get() == NULL);
783
[email protected]71e4573a2009-05-21 22:03:00784 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
[email protected]2d2697f92009-02-18 21:00:32785 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
786 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
787
788 TestCompletionCallback callback2;
789
790 rv = trans->RestartWithAuth(L"foo", L"bar", &callback2);
[email protected]1c773ea12009-04-28 19:58:42791 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:32792
793 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42794 EXPECT_EQ(OK, rv);
[email protected]2d2697f92009-02-18 21:00:32795
796 response = trans->GetResponseInfo();
797 EXPECT_FALSE(response == NULL);
798 EXPECT_TRUE(response->auth_challenge.get() == NULL);
799 EXPECT_EQ(100, response->headers->GetContentLength());
800}
801
802// Test the request-challenge-retry sequence for basic auth, over a keep-alive
803// connection and with no response body to drain.
804TEST_F(HttpNetworkTransactionTest, BasicAuthKeepAliveNoBody) {
[email protected]228ff742009-06-05 01:19:59805 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:40806 scoped_ptr<HttpTransaction> trans(
807 new HttpNetworkTransaction(
[email protected]228ff742009-06-05 01:19:59808 CreateSession(&session_deps),
809 &session_deps.socket_factory));
[email protected]2d2697f92009-02-18 21:00:32810
[email protected]1c773ea12009-04-28 19:58:42811 HttpRequestInfo request;
[email protected]2d2697f92009-02-18 21:00:32812 request.method = "GET";
813 request.url = GURL("http://www.google.com/");
814 request.load_flags = 0;
815
816 MockWrite data_writes1[] = {
817 MockWrite("GET / HTTP/1.1\r\n"
818 "Host: www.google.com\r\n"
819 "Connection: keep-alive\r\n\r\n"),
820
821 // After calling trans->RestartWithAuth(), this is the request we should
822 // be issuing -- the final header line contains the credentials.
823 MockWrite("GET / HTTP/1.1\r\n"
824 "Host: www.google.com\r\n"
825 "Connection: keep-alive\r\n"
826 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
827 };
828
829 // Respond with 5 kb of response body.
830 std::string large_body_string("Unauthorized");
831 large_body_string.append(5 * 1024, ' ');
832 large_body_string.append("\r\n");
833
834 MockRead data_reads1[] = {
835 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
836 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
837 MockRead("Content-Length: 0\r\n\r\n"),
838
839 // Lastly, the server responds with the actual content.
840 MockRead("HTTP/1.1 200 OK\r\n"),
841 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
842 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:42843 MockRead(false, OK),
[email protected]2d2697f92009-02-18 21:00:32844 };
845
[email protected]69b43fe2009-06-15 09:47:37846 StaticMockSocket data1(data_reads1, data_writes1);
[email protected]228ff742009-06-05 01:19:59847 session_deps.socket_factory.AddMockSocket(&data1);
[email protected]2d2697f92009-02-18 21:00:32848
849 TestCompletionCallback callback1;
850
[email protected]684970b2009-08-14 04:54:46851 int rv = trans->Start(&request, &callback1, NULL);
[email protected]1c773ea12009-04-28 19:58:42852 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:32853
854 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42855 EXPECT_EQ(OK, rv);
[email protected]2d2697f92009-02-18 21:00:32856
[email protected]1c773ea12009-04-28 19:58:42857 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]2d2697f92009-02-18 21:00:32858 EXPECT_FALSE(response == NULL);
859
860 // The password prompt info should have been set in response->auth_challenge.
861 EXPECT_FALSE(response->auth_challenge.get() == NULL);
862
[email protected]71e4573a2009-05-21 22:03:00863 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
[email protected]2d2697f92009-02-18 21:00:32864 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
865 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
866
867 TestCompletionCallback callback2;
868
869 rv = trans->RestartWithAuth(L"foo", L"bar", &callback2);
[email protected]1c773ea12009-04-28 19:58:42870 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:32871
872 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42873 EXPECT_EQ(OK, rv);
[email protected]2d2697f92009-02-18 21:00:32874
875 response = trans->GetResponseInfo();
876 EXPECT_FALSE(response == NULL);
877 EXPECT_TRUE(response->auth_challenge.get() == NULL);
878 EXPECT_EQ(100, response->headers->GetContentLength());
879}
880
881// Test the request-challenge-retry sequence for basic auth, over a keep-alive
882// connection and with a large response body to drain.
883TEST_F(HttpNetworkTransactionTest, BasicAuthKeepAliveLargeBody) {
[email protected]228ff742009-06-05 01:19:59884 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:40885 scoped_ptr<HttpTransaction> trans(
886 new HttpNetworkTransaction(
[email protected]228ff742009-06-05 01:19:59887 CreateSession(&session_deps),
888 &session_deps.socket_factory));
[email protected]2d2697f92009-02-18 21:00:32889
[email protected]1c773ea12009-04-28 19:58:42890 HttpRequestInfo request;
[email protected]2d2697f92009-02-18 21:00:32891 request.method = "GET";
892 request.url = GURL("http://www.google.com/");
893 request.load_flags = 0;
894
895 MockWrite data_writes1[] = {
896 MockWrite("GET / HTTP/1.1\r\n"
897 "Host: www.google.com\r\n"
898 "Connection: keep-alive\r\n\r\n"),
899
900 // After calling trans->RestartWithAuth(), this is the request we should
901 // be issuing -- the final header line contains the credentials.
902 MockWrite("GET / HTTP/1.1\r\n"
903 "Host: www.google.com\r\n"
904 "Connection: keep-alive\r\n"
905 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
906 };
907
908 // Respond with 5 kb of response body.
909 std::string large_body_string("Unauthorized");
910 large_body_string.append(5 * 1024, ' ');
911 large_body_string.append("\r\n");
912
913 MockRead data_reads1[] = {
914 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
915 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
916 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
917 // 5134 = 12 + 5 * 1024 + 2
918 MockRead("Content-Length: 5134\r\n\r\n"),
919 MockRead(true, large_body_string.data(), large_body_string.size()),
920
921 // Lastly, the server responds with the actual content.
922 MockRead("HTTP/1.1 200 OK\r\n"),
923 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
924 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:42925 MockRead(false, OK),
[email protected]2d2697f92009-02-18 21:00:32926 };
927
[email protected]69b43fe2009-06-15 09:47:37928 StaticMockSocket data1(data_reads1, data_writes1);
[email protected]228ff742009-06-05 01:19:59929 session_deps.socket_factory.AddMockSocket(&data1);
[email protected]2d2697f92009-02-18 21:00:32930
931 TestCompletionCallback callback1;
932
[email protected]684970b2009-08-14 04:54:46933 int rv = trans->Start(&request, &callback1, NULL);
[email protected]1c773ea12009-04-28 19:58:42934 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:32935
936 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42937 EXPECT_EQ(OK, rv);
[email protected]2d2697f92009-02-18 21:00:32938
[email protected]1c773ea12009-04-28 19:58:42939 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]2d2697f92009-02-18 21:00:32940 EXPECT_FALSE(response == NULL);
941
942 // The password prompt info should have been set in response->auth_challenge.
943 EXPECT_FALSE(response->auth_challenge.get() == NULL);
944
[email protected]71e4573a2009-05-21 22:03:00945 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
[email protected]2d2697f92009-02-18 21:00:32946 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
947 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
948
949 TestCompletionCallback callback2;
950
951 rv = trans->RestartWithAuth(L"foo", L"bar", &callback2);
[email protected]1c773ea12009-04-28 19:58:42952 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:32953
954 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42955 EXPECT_EQ(OK, rv);
[email protected]2d2697f92009-02-18 21:00:32956
957 response = trans->GetResponseInfo();
958 EXPECT_FALSE(response == NULL);
959 EXPECT_TRUE(response->auth_challenge.get() == NULL);
960 EXPECT_EQ(100, response->headers->GetContentLength());
961}
962
963// Test the request-challenge-retry sequence for basic auth, over a keep-alive
964// proxy connection, when setting up an SSL tunnel.
965TEST_F(HttpNetworkTransactionTest, BasicAuthProxyKeepAlive) {
966 // Configure against proxy server "myproxy:70".
[email protected]228ff742009-06-05 01:19:59967 SessionDependencies session_deps(CreateFixedProxyService("myproxy:70"));
968 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]2d2697f92009-02-18 21:00:32969
[email protected]1c773ea12009-04-28 19:58:42970 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(
[email protected]228ff742009-06-05 01:19:59971 session.get(), &session_deps.socket_factory));
[email protected]2d2697f92009-02-18 21:00:32972
[email protected]1c773ea12009-04-28 19:58:42973 HttpRequestInfo request;
[email protected]2d2697f92009-02-18 21:00:32974 request.method = "GET";
975 request.url = GURL("https://www.google.com/");
976 request.load_flags = 0;
977
978 // Since we have proxy, should try to establish tunnel.
979 MockWrite data_writes1[] = {
980 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
[email protected]e44de5d2009-06-05 20:12:45981 "Host: www.google.com\r\n"
982 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]2d2697f92009-02-18 21:00:32983
984 // After calling trans->RestartWithAuth(), this is the request we should
985 // be issuing -- the final header line contains the credentials.
986 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
987 "Host: www.google.com\r\n"
[email protected]e44de5d2009-06-05 20:12:45988 "Proxy-Connection: keep-alive\r\n"
[email protected]2d2697f92009-02-18 21:00:32989 "Proxy-Authorization: Basic Zm9vOmJheg==\r\n\r\n"),
990 };
991
992 // The proxy responds to the connect with a 407, using a persistent
993 // connection.
994 MockRead data_reads1[] = {
995 // No credentials.
996 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
997 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
998 MockRead("Content-Length: 10\r\n\r\n"),
999 MockRead("0123456789"),
1000
1001 // Wrong credentials (wrong password).
1002 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
1003 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1004 MockRead("Content-Length: 10\r\n\r\n"),
1005 // No response body because the test stops reading here.
[email protected]1c773ea12009-04-28 19:58:421006 MockRead(false, ERR_UNEXPECTED), // Should not be reached.
[email protected]2d2697f92009-02-18 21:00:321007 };
1008
[email protected]69b43fe2009-06-15 09:47:371009 StaticMockSocket data1(data_reads1, data_writes1);
[email protected]228ff742009-06-05 01:19:591010 session_deps.socket_factory.AddMockSocket(&data1);
[email protected]2d2697f92009-02-18 21:00:321011
1012 TestCompletionCallback callback1;
1013
[email protected]684970b2009-08-14 04:54:461014 int rv = trans->Start(&request, &callback1, NULL);
[email protected]1c773ea12009-04-28 19:58:421015 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:321016
1017 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421018 EXPECT_EQ(OK, rv);
[email protected]2d2697f92009-02-18 21:00:321019
[email protected]1c773ea12009-04-28 19:58:421020 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]2d2697f92009-02-18 21:00:321021 EXPECT_FALSE(response == NULL);
1022
1023 EXPECT_TRUE(response->headers->IsKeepAlive());
1024 EXPECT_EQ(407, response->headers->response_code());
1025 EXPECT_EQ(10, response->headers->GetContentLength());
[email protected]1c773ea12009-04-28 19:58:421026 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
[email protected]2d2697f92009-02-18 21:00:321027
1028 // The password prompt info should have been set in response->auth_challenge.
1029 EXPECT_FALSE(response->auth_challenge.get() == NULL);
1030
[email protected]71e4573a2009-05-21 22:03:001031 EXPECT_EQ(L"myproxy:70", response->auth_challenge->host_and_port);
[email protected]2d2697f92009-02-18 21:00:321032 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
1033 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
1034
1035 TestCompletionCallback callback2;
1036
1037 // Wrong password (should be "bar").
1038 rv = trans->RestartWithAuth(L"foo", L"baz", &callback2);
[email protected]1c773ea12009-04-28 19:58:421039 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:321040
1041 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421042 EXPECT_EQ(OK, rv);
[email protected]2d2697f92009-02-18 21:00:321043
1044 response = trans->GetResponseInfo();
1045 EXPECT_FALSE(response == NULL);
1046
1047 EXPECT_TRUE(response->headers->IsKeepAlive());
1048 EXPECT_EQ(407, response->headers->response_code());
1049 EXPECT_EQ(10, response->headers->GetContentLength());
[email protected]1c773ea12009-04-28 19:58:421050 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
[email protected]2d2697f92009-02-18 21:00:321051
1052 // The password prompt info should have been set in response->auth_challenge.
1053 EXPECT_FALSE(response->auth_challenge.get() == NULL);
1054
[email protected]71e4573a2009-05-21 22:03:001055 EXPECT_EQ(L"myproxy:70", response->auth_challenge->host_and_port);
[email protected]2d2697f92009-02-18 21:00:321056 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
1057 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
1058}
1059
[email protected]a8e9b162009-03-12 00:06:441060// Test that we don't read the response body when we fail to establish a tunnel,
1061// even if the user cancels the proxy's auth attempt.
1062TEST_F(HttpNetworkTransactionTest, BasicAuthProxyCancelTunnel) {
1063 // Configure against proxy server "myproxy:70".
[email protected]228ff742009-06-05 01:19:591064 SessionDependencies session_deps(CreateFixedProxyService("myproxy:70"));
[email protected]a8e9b162009-03-12 00:06:441065
[email protected]e44de5d2009-06-05 20:12:451066 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]a8e9b162009-03-12 00:06:441067
[email protected]1c773ea12009-04-28 19:58:421068 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(
[email protected]228ff742009-06-05 01:19:591069 session.get(), &session_deps.socket_factory));
[email protected]a8e9b162009-03-12 00:06:441070
[email protected]1c773ea12009-04-28 19:58:421071 HttpRequestInfo request;
[email protected]a8e9b162009-03-12 00:06:441072 request.method = "GET";
1073 request.url = GURL("https://www.google.com/");
1074 request.load_flags = 0;
1075
1076 // Since we have proxy, should try to establish tunnel.
1077 MockWrite data_writes[] = {
1078 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
[email protected]e44de5d2009-06-05 20:12:451079 "Host: www.google.com\r\n"
1080 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]a8e9b162009-03-12 00:06:441081 };
1082
1083 // The proxy responds to the connect with a 407.
1084 MockRead data_reads[] = {
1085 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
1086 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1087 MockRead("Content-Length: 10\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:421088 MockRead(false, ERR_UNEXPECTED), // Should not be reached.
[email protected]a8e9b162009-03-12 00:06:441089 };
1090
[email protected]69b43fe2009-06-15 09:47:371091 StaticMockSocket data(data_reads, data_writes);
[email protected]228ff742009-06-05 01:19:591092 session_deps.socket_factory.AddMockSocket(&data);
[email protected]a8e9b162009-03-12 00:06:441093
1094 TestCompletionCallback callback;
1095
[email protected]684970b2009-08-14 04:54:461096 int rv = trans->Start(&request, &callback, NULL);
[email protected]1c773ea12009-04-28 19:58:421097 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]a8e9b162009-03-12 00:06:441098
1099 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421100 EXPECT_EQ(OK, rv);
[email protected]a8e9b162009-03-12 00:06:441101
[email protected]1c773ea12009-04-28 19:58:421102 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]a8e9b162009-03-12 00:06:441103 EXPECT_FALSE(response == NULL);
1104
1105 EXPECT_TRUE(response->headers->IsKeepAlive());
1106 EXPECT_EQ(407, response->headers->response_code());
1107 EXPECT_EQ(10, response->headers->GetContentLength());
[email protected]1c773ea12009-04-28 19:58:421108 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
[email protected]a8e9b162009-03-12 00:06:441109
1110 std::string response_data;
1111 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:421112 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED, rv);
[email protected]a8e9b162009-03-12 00:06:441113}
1114
[email protected]ff007e162009-05-23 09:13:151115void HttpNetworkTransactionTest::ConnectStatusHelperWithExpectedStatus(
[email protected]c744cf22009-02-27 07:28:081116 const MockRead& status, int expected_status) {
1117 // Configure against proxy server "myproxy:70".
[email protected]228ff742009-06-05 01:19:591118 SessionDependencies session_deps(CreateFixedProxyService("myproxy:70"));
[email protected]c744cf22009-02-27 07:28:081119
[email protected]228ff742009-06-05 01:19:591120 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]c744cf22009-02-27 07:28:081121
[email protected]1c773ea12009-04-28 19:58:421122 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(
[email protected]228ff742009-06-05 01:19:591123 session.get(), &session_deps.socket_factory));
[email protected]c744cf22009-02-27 07:28:081124
[email protected]1c773ea12009-04-28 19:58:421125 HttpRequestInfo request;
[email protected]c744cf22009-02-27 07:28:081126 request.method = "GET";
1127 request.url = GURL("https://www.google.com/");
1128 request.load_flags = 0;
1129
1130 // Since we have proxy, should try to establish tunnel.
1131 MockWrite data_writes[] = {
1132 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
[email protected]e44de5d2009-06-05 20:12:451133 "Host: www.google.com\r\n"
1134 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]c744cf22009-02-27 07:28:081135 };
1136
1137 MockRead data_reads[] = {
1138 status,
1139 MockRead("Content-Length: 10\r\n\r\n"),
1140 // No response body because the test stops reading here.
[email protected]1c773ea12009-04-28 19:58:421141 MockRead(false, ERR_UNEXPECTED), // Should not be reached.
[email protected]c744cf22009-02-27 07:28:081142 };
1143
[email protected]69b43fe2009-06-15 09:47:371144 StaticMockSocket data(data_reads, data_writes);
[email protected]228ff742009-06-05 01:19:591145 session_deps.socket_factory.AddMockSocket(&data);
[email protected]c744cf22009-02-27 07:28:081146
1147 TestCompletionCallback callback;
1148
[email protected]684970b2009-08-14 04:54:461149 int rv = trans->Start(&request, &callback, NULL);
[email protected]1c773ea12009-04-28 19:58:421150 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]c744cf22009-02-27 07:28:081151
1152 rv = callback.WaitForResult();
1153 EXPECT_EQ(expected_status, rv);
1154}
1155
[email protected]ff007e162009-05-23 09:13:151156void HttpNetworkTransactionTest::ConnectStatusHelper(const MockRead& status) {
[email protected]c744cf22009-02-27 07:28:081157 ConnectStatusHelperWithExpectedStatus(
[email protected]1c773ea12009-04-28 19:58:421158 status, ERR_TUNNEL_CONNECTION_FAILED);
[email protected]c744cf22009-02-27 07:28:081159}
1160
1161TEST_F(HttpNetworkTransactionTest, ConnectStatus100) {
1162 ConnectStatusHelper(MockRead("HTTP/1.1 100 Continue\r\n"));
1163}
1164
1165TEST_F(HttpNetworkTransactionTest, ConnectStatus101) {
1166 ConnectStatusHelper(MockRead("HTTP/1.1 101 Switching Protocols\r\n"));
1167}
1168
1169TEST_F(HttpNetworkTransactionTest, ConnectStatus201) {
1170 ConnectStatusHelper(MockRead("HTTP/1.1 201 Created\r\n"));
1171}
1172
1173TEST_F(HttpNetworkTransactionTest, ConnectStatus202) {
1174 ConnectStatusHelper(MockRead("HTTP/1.1 202 Accepted\r\n"));
1175}
1176
1177TEST_F(HttpNetworkTransactionTest, ConnectStatus203) {
1178 ConnectStatusHelper(
1179 MockRead("HTTP/1.1 203 Non-Authoritative Information\r\n"));
1180}
1181
1182TEST_F(HttpNetworkTransactionTest, ConnectStatus204) {
1183 ConnectStatusHelper(MockRead("HTTP/1.1 204 No Content\r\n"));
1184}
1185
1186TEST_F(HttpNetworkTransactionTest, ConnectStatus205) {
1187 ConnectStatusHelper(MockRead("HTTP/1.1 205 Reset Content\r\n"));
1188}
1189
1190TEST_F(HttpNetworkTransactionTest, ConnectStatus206) {
1191 ConnectStatusHelper(MockRead("HTTP/1.1 206 Partial Content\r\n"));
1192}
1193
1194TEST_F(HttpNetworkTransactionTest, ConnectStatus300) {
1195 ConnectStatusHelper(MockRead("HTTP/1.1 300 Multiple Choices\r\n"));
1196}
1197
1198TEST_F(HttpNetworkTransactionTest, ConnectStatus301) {
1199 ConnectStatusHelper(MockRead("HTTP/1.1 301 Moved Permanently\r\n"));
1200}
1201
1202TEST_F(HttpNetworkTransactionTest, ConnectStatus302) {
1203 ConnectStatusHelper(MockRead("HTTP/1.1 302 Found\r\n"));
1204}
1205
1206TEST_F(HttpNetworkTransactionTest, ConnectStatus303) {
1207 ConnectStatusHelper(MockRead("HTTP/1.1 303 See Other\r\n"));
1208}
1209
1210TEST_F(HttpNetworkTransactionTest, ConnectStatus304) {
1211 ConnectStatusHelper(MockRead("HTTP/1.1 304 Not Modified\r\n"));
1212}
1213
1214TEST_F(HttpNetworkTransactionTest, ConnectStatus305) {
1215 ConnectStatusHelper(MockRead("HTTP/1.1 305 Use Proxy\r\n"));
1216}
1217
1218TEST_F(HttpNetworkTransactionTest, ConnectStatus306) {
1219 ConnectStatusHelper(MockRead("HTTP/1.1 306\r\n"));
1220}
1221
1222TEST_F(HttpNetworkTransactionTest, ConnectStatus307) {
1223 ConnectStatusHelper(MockRead("HTTP/1.1 307 Temporary Redirect\r\n"));
1224}
1225
1226TEST_F(HttpNetworkTransactionTest, ConnectStatus400) {
1227 ConnectStatusHelper(MockRead("HTTP/1.1 400 Bad Request\r\n"));
1228}
1229
1230TEST_F(HttpNetworkTransactionTest, ConnectStatus401) {
1231 ConnectStatusHelper(MockRead("HTTP/1.1 401 Unauthorized\r\n"));
1232}
1233
1234TEST_F(HttpNetworkTransactionTest, ConnectStatus402) {
1235 ConnectStatusHelper(MockRead("HTTP/1.1 402 Payment Required\r\n"));
1236}
1237
1238TEST_F(HttpNetworkTransactionTest, ConnectStatus403) {
1239 ConnectStatusHelper(MockRead("HTTP/1.1 403 Forbidden\r\n"));
1240}
1241
1242TEST_F(HttpNetworkTransactionTest, ConnectStatus404) {
1243 ConnectStatusHelper(MockRead("HTTP/1.1 404 Not Found\r\n"));
1244}
1245
1246TEST_F(HttpNetworkTransactionTest, ConnectStatus405) {
1247 ConnectStatusHelper(MockRead("HTTP/1.1 405 Method Not Allowed\r\n"));
1248}
1249
1250TEST_F(HttpNetworkTransactionTest, ConnectStatus406) {
1251 ConnectStatusHelper(MockRead("HTTP/1.1 406 Not Acceptable\r\n"));
1252}
1253
1254TEST_F(HttpNetworkTransactionTest, ConnectStatus407) {
1255 ConnectStatusHelperWithExpectedStatus(
1256 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
[email protected]1c773ea12009-04-28 19:58:421257 ERR_PROXY_AUTH_REQUESTED);
[email protected]c744cf22009-02-27 07:28:081258}
1259
1260TEST_F(HttpNetworkTransactionTest, ConnectStatus408) {
1261 ConnectStatusHelper(MockRead("HTTP/1.1 408 Request Timeout\r\n"));
1262}
1263
1264TEST_F(HttpNetworkTransactionTest, ConnectStatus409) {
1265 ConnectStatusHelper(MockRead("HTTP/1.1 409 Conflict\r\n"));
1266}
1267
1268TEST_F(HttpNetworkTransactionTest, ConnectStatus410) {
1269 ConnectStatusHelper(MockRead("HTTP/1.1 410 Gone\r\n"));
1270}
1271
1272TEST_F(HttpNetworkTransactionTest, ConnectStatus411) {
1273 ConnectStatusHelper(MockRead("HTTP/1.1 411 Length Required\r\n"));
1274}
1275
1276TEST_F(HttpNetworkTransactionTest, ConnectStatus412) {
1277 ConnectStatusHelper(MockRead("HTTP/1.1 412 Precondition Failed\r\n"));
1278}
1279
1280TEST_F(HttpNetworkTransactionTest, ConnectStatus413) {
1281 ConnectStatusHelper(MockRead("HTTP/1.1 413 Request Entity Too Large\r\n"));
1282}
1283
1284TEST_F(HttpNetworkTransactionTest, ConnectStatus414) {
1285 ConnectStatusHelper(MockRead("HTTP/1.1 414 Request-URI Too Long\r\n"));
1286}
1287
1288TEST_F(HttpNetworkTransactionTest, ConnectStatus415) {
1289 ConnectStatusHelper(MockRead("HTTP/1.1 415 Unsupported Media Type\r\n"));
1290}
1291
1292TEST_F(HttpNetworkTransactionTest, ConnectStatus416) {
1293 ConnectStatusHelper(
1294 MockRead("HTTP/1.1 416 Requested Range Not Satisfiable\r\n"));
1295}
1296
1297TEST_F(HttpNetworkTransactionTest, ConnectStatus417) {
1298 ConnectStatusHelper(MockRead("HTTP/1.1 417 Expectation Failed\r\n"));
1299}
1300
1301TEST_F(HttpNetworkTransactionTest, ConnectStatus500) {
1302 ConnectStatusHelper(MockRead("HTTP/1.1 500 Internal Server Error\r\n"));
1303}
1304
1305TEST_F(HttpNetworkTransactionTest, ConnectStatus501) {
1306 ConnectStatusHelper(MockRead("HTTP/1.1 501 Not Implemented\r\n"));
1307}
1308
1309TEST_F(HttpNetworkTransactionTest, ConnectStatus502) {
1310 ConnectStatusHelper(MockRead("HTTP/1.1 502 Bad Gateway\r\n"));
1311}
1312
1313TEST_F(HttpNetworkTransactionTest, ConnectStatus503) {
1314 ConnectStatusHelper(MockRead("HTTP/1.1 503 Service Unavailable\r\n"));
1315}
1316
1317TEST_F(HttpNetworkTransactionTest, ConnectStatus504) {
1318 ConnectStatusHelper(MockRead("HTTP/1.1 504 Gateway Timeout\r\n"));
1319}
1320
1321TEST_F(HttpNetworkTransactionTest, ConnectStatus505) {
1322 ConnectStatusHelper(MockRead("HTTP/1.1 505 HTTP Version Not Supported\r\n"));
1323}
1324
[email protected]038e9a32008-10-08 22:40:161325// Test the flow when both the proxy server AND origin server require
1326// authentication. Again, this uses basic auth for both since that is
1327// the simplest to mock.
1328TEST_F(HttpNetworkTransactionTest, BasicAuthProxyThenServer) {
[email protected]228ff742009-06-05 01:19:591329 SessionDependencies session_deps(CreateFixedProxyService("myproxy:70"));
[email protected]db8f44c2008-12-13 04:52:011330
[email protected]038e9a32008-10-08 22:40:161331 // Configure against proxy server "myproxy:70".
[email protected]1c773ea12009-04-28 19:58:421332 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(
[email protected]228ff742009-06-05 01:19:591333 CreateSession(&session_deps),
1334 &session_deps.socket_factory));
[email protected]038e9a32008-10-08 22:40:161335
[email protected]1c773ea12009-04-28 19:58:421336 HttpRequestInfo request;
[email protected]038e9a32008-10-08 22:40:161337 request.method = "GET";
1338 request.url = GURL("http://www.google.com/");
1339 request.load_flags = 0;
1340
[email protected]f9ee6b52008-11-08 06:46:231341 MockWrite data_writes1[] = {
1342 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
1343 "Host: www.google.com\r\n"
1344 "Proxy-Connection: keep-alive\r\n\r\n"),
1345 };
1346
[email protected]038e9a32008-10-08 22:40:161347 MockRead data_reads1[] = {
1348 MockRead("HTTP/1.0 407 Unauthorized\r\n"),
1349 // Give a couple authenticate options (only the middle one is actually
1350 // supported).
[email protected]aaead502008-10-15 00:20:111351 MockRead("Proxy-Authenticate: Basic\r\n"), // Malformed
[email protected]038e9a32008-10-08 22:40:161352 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1353 MockRead("Proxy-Authenticate: UNSUPPORTED realm=\"FOO\"\r\n"),
1354 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1355 // Large content-length -- won't matter, as connection will be reset.
1356 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:421357 MockRead(false, ERR_FAILED),
[email protected]038e9a32008-10-08 22:40:161358 };
1359
1360 // After calling trans->RestartWithAuth() the first time, this is the
1361 // request we should be issuing -- the final header line contains the
1362 // proxy's credentials.
1363 MockWrite data_writes2[] = {
1364 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
1365 "Host: www.google.com\r\n"
1366 "Proxy-Connection: keep-alive\r\n"
1367 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
1368 };
1369
1370 // Now the proxy server lets the request pass through to origin server.
1371 // The origin server responds with a 401.
1372 MockRead data_reads2[] = {
1373 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
1374 // Note: We are using the same realm-name as the proxy server. This is
1375 // completely valid, as realms are unique across hosts.
1376 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1377 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1378 MockRead("Content-Length: 2000\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:421379 MockRead(false, ERR_FAILED), // Won't be reached.
[email protected]038e9a32008-10-08 22:40:161380 };
1381
1382 // After calling trans->RestartWithAuth() the second time, we should send
1383 // the credentials for both the proxy and origin server.
1384 MockWrite data_writes3[] = {
1385 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
1386 "Host: www.google.com\r\n"
1387 "Proxy-Connection: keep-alive\r\n"
1388 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n"
1389 "Authorization: Basic Zm9vMjpiYXIy\r\n\r\n"),
1390 };
1391
1392 // Lastly we get the desired content.
1393 MockRead data_reads3[] = {
1394 MockRead("HTTP/1.0 200 OK\r\n"),
1395 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1396 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:421397 MockRead(false, OK),
[email protected]038e9a32008-10-08 22:40:161398 };
1399
[email protected]69b43fe2009-06-15 09:47:371400 StaticMockSocket data1(data_reads1, data_writes1);
1401 StaticMockSocket data2(data_reads2, data_writes2);
1402 StaticMockSocket data3(data_reads3, data_writes3);
[email protected]228ff742009-06-05 01:19:591403 session_deps.socket_factory.AddMockSocket(&data1);
1404 session_deps.socket_factory.AddMockSocket(&data2);
1405 session_deps.socket_factory.AddMockSocket(&data3);
[email protected]038e9a32008-10-08 22:40:161406
1407 TestCompletionCallback callback1;
1408
[email protected]684970b2009-08-14 04:54:461409 int rv = trans->Start(&request, &callback1, NULL);
[email protected]1c773ea12009-04-28 19:58:421410 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]038e9a32008-10-08 22:40:161411
1412 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421413 EXPECT_EQ(OK, rv);
[email protected]038e9a32008-10-08 22:40:161414
[email protected]1c773ea12009-04-28 19:58:421415 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]038e9a32008-10-08 22:40:161416 EXPECT_FALSE(response == NULL);
1417
1418 // The password prompt info should have been set in response->auth_challenge.
1419 EXPECT_FALSE(response->auth_challenge.get() == NULL);
1420
[email protected]71e4573a2009-05-21 22:03:001421 EXPECT_EQ(L"myproxy:70", response->auth_challenge->host_and_port);
[email protected]038e9a32008-10-08 22:40:161422 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
1423 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
1424
1425 TestCompletionCallback callback2;
1426
1427 rv = trans->RestartWithAuth(L"foo", L"bar", &callback2);
[email protected]1c773ea12009-04-28 19:58:421428 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]038e9a32008-10-08 22:40:161429
1430 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421431 EXPECT_EQ(OK, rv);
[email protected]038e9a32008-10-08 22:40:161432
1433 response = trans->GetResponseInfo();
1434 EXPECT_FALSE(response == NULL);
1435 EXPECT_FALSE(response->auth_challenge.get() == NULL);
1436
[email protected]71e4573a2009-05-21 22:03:001437 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
[email protected]038e9a32008-10-08 22:40:161438 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
1439 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
1440
1441 TestCompletionCallback callback3;
1442
1443 rv = trans->RestartWithAuth(L"foo2", L"bar2", &callback3);
[email protected]1c773ea12009-04-28 19:58:421444 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]038e9a32008-10-08 22:40:161445
1446 rv = callback3.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421447 EXPECT_EQ(OK, rv);
[email protected]038e9a32008-10-08 22:40:161448
1449 response = trans->GetResponseInfo();
1450 EXPECT_TRUE(response->auth_challenge.get() == NULL);
1451 EXPECT_EQ(100, response->headers->GetContentLength());
[email protected]038e9a32008-10-08 22:40:161452}
[email protected]4ddaf2502008-10-23 18:26:191453
[email protected]385a4672009-03-11 22:21:291454// The NTLM authentication unit tests were generated by capturing the HTTP
1455// requests and responses using Fiddler 2 and inspecting the generated random
1456// bytes in the debugger.
1457
1458// Enter the correct password and authenticate successfully.
1459TEST_F(HttpNetworkTransactionTest, NTLMAuth1) {
[email protected]1c773ea12009-04-28 19:58:421460 HttpAuthHandlerNTLM::ScopedProcSetter proc_setter(MockGenerateRandom1,
[email protected]fe2bc6a2009-03-23 16:52:201461 MockGetHostName);
[email protected]228ff742009-06-05 01:19:591462 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:401463 scoped_ptr<HttpTransaction> trans(
1464 new HttpNetworkTransaction(
[email protected]228ff742009-06-05 01:19:591465 CreateSession(&session_deps),
1466 &session_deps.socket_factory));
[email protected]3f918782009-02-28 01:29:241467
[email protected]1c773ea12009-04-28 19:58:421468 HttpRequestInfo request;
[email protected]3f918782009-02-28 01:29:241469 request.method = "GET";
1470 request.url = GURL("http://172.22.68.17/kids/login.aspx");
1471 request.load_flags = 0;
1472
1473 MockWrite data_writes1[] = {
1474 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
1475 "Host: 172.22.68.17\r\n"
1476 "Connection: keep-alive\r\n\r\n"),
1477 };
1478
1479 MockRead data_reads1[] = {
1480 MockRead("HTTP/1.1 401 Access Denied\r\n"),
1481 // Negotiate and NTLM are often requested together. We only support NTLM.
1482 MockRead("WWW-Authenticate: Negotiate\r\n"),
1483 MockRead("WWW-Authenticate: NTLM\r\n"),
1484 MockRead("Connection: close\r\n"),
1485 MockRead("Content-Length: 42\r\n"),
[email protected]076c85082009-04-10 23:21:361486 MockRead("Content-Type: text/html\r\n\r\n"),
[email protected]3f918782009-02-28 01:29:241487 // Missing content -- won't matter, as connection will be reset.
[email protected]1c773ea12009-04-28 19:58:421488 MockRead(false, ERR_UNEXPECTED),
[email protected]3f918782009-02-28 01:29:241489 };
1490
1491 MockWrite data_writes2[] = {
[email protected]0757e7702009-03-27 04:00:221492 // After restarting with a null identity, this is the
[email protected]3f918782009-02-28 01:29:241493 // request we should be issuing -- the final header line contains a Type
1494 // 1 message.
1495 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
1496 "Host: 172.22.68.17\r\n"
1497 "Connection: keep-alive\r\n"
1498 "Authorization: NTLM "
1499 "TlRMTVNTUAABAAAAB4IIAAAAAAAAAAAAAAAAAAAAAAA=\r\n\r\n"),
1500
1501 // After calling trans->RestartWithAuth(), we should send a Type 3 message
1502 // (the credentials for the origin server). The second request continues
1503 // on the same connection.
1504 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
1505 "Host: 172.22.68.17\r\n"
1506 "Connection: keep-alive\r\n"
[email protected]385a4672009-03-11 22:21:291507 "Authorization: NTLM TlRMTVNTUAADAAAAGAAYAGgAAAAYABgAgA"
1508 "AAAAAAAABAAAAAGAAYAEAAAAAQABAAWAAAAAAAAAAAAAAABYIIAHQA"
1509 "ZQBzAHQAaQBuAGcALQBuAHQAbABtAFcAVABDAC0AVwBJAE4ANwBVKW"
1510 "Yma5xzVAAAAAAAAAAAAAAAAAAAAACH+gWcm+YsP9Tqb9zCR3WAeZZX"
1511 "ahlhx5I=\r\n\r\n"),
[email protected]3f918782009-02-28 01:29:241512 };
1513
1514 MockRead data_reads2[] = {
1515 // The origin server responds with a Type 2 message.
1516 MockRead("HTTP/1.1 401 Access Denied\r\n"),
1517 MockRead("WWW-Authenticate: NTLM "
[email protected]385a4672009-03-11 22:21:291518 "TlRMTVNTUAACAAAADAAMADgAAAAFgokCjGpMpPGlYKkAAAAAAAAAALo"
[email protected]3f918782009-02-28 01:29:241519 "AugBEAAAABQEoCgAAAA9HAE8ATwBHAEwARQACAAwARwBPAE8ARwBMAE"
1520 "UAAQAaAEEASwBFAEUAUwBBAFIAQQAtAEMATwBSAFAABAAeAGMAbwByA"
1521 "HAALgBnAG8AbwBnAGwAZQAuAGMAbwBtAAMAQABhAGsAZQBlAHMAYQBy"
1522 "AGEALQBjAG8AcgBwAC4AYQBkAC4AYwBvAHIAcAAuAGcAbwBvAGcAbAB"
1523 "lAC4AYwBvAG0ABQAeAGMAbwByAHAALgBnAG8AbwBnAGwAZQAuAGMAbw"
1524 "BtAAAAAAA=\r\n"),
1525 MockRead("Content-Length: 42\r\n"),
[email protected]076c85082009-04-10 23:21:361526 MockRead("Content-Type: text/html\r\n\r\n"),
[email protected]3f918782009-02-28 01:29:241527 MockRead("You are not authorized to view this page\r\n"),
1528
1529 // Lastly we get the desired content.
1530 MockRead("HTTP/1.1 200 OK\r\n"),
1531 MockRead("Content-Type: text/html; charset=utf-8\r\n"),
1532 MockRead("Content-Length: 13\r\n\r\n"),
1533 MockRead("Please Login\r\n"),
[email protected]1c773ea12009-04-28 19:58:421534 MockRead(false, OK),
[email protected]3f918782009-02-28 01:29:241535 };
1536
[email protected]69b43fe2009-06-15 09:47:371537 StaticMockSocket data1(data_reads1, data_writes1);
1538 StaticMockSocket data2(data_reads2, data_writes2);
[email protected]228ff742009-06-05 01:19:591539 session_deps.socket_factory.AddMockSocket(&data1);
1540 session_deps.socket_factory.AddMockSocket(&data2);
[email protected]3f918782009-02-28 01:29:241541
1542 TestCompletionCallback callback1;
1543
[email protected]684970b2009-08-14 04:54:461544 int rv = trans->Start(&request, &callback1, NULL);
[email protected]1c773ea12009-04-28 19:58:421545 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]3f918782009-02-28 01:29:241546
1547 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421548 EXPECT_EQ(OK, rv);
[email protected]3f918782009-02-28 01:29:241549
[email protected]0757e7702009-03-27 04:00:221550 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
1551 TestCompletionCallback callback2;
1552 rv = trans->RestartWithAuth(std::wstring(), std::wstring(), &callback2);
[email protected]1c773ea12009-04-28 19:58:421553 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]0757e7702009-03-27 04:00:221554 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421555 EXPECT_EQ(OK, rv);
[email protected]0757e7702009-03-27 04:00:221556 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
1557
[email protected]1c773ea12009-04-28 19:58:421558 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]3f918782009-02-28 01:29:241559 EXPECT_FALSE(response == NULL);
1560
1561 // The password prompt info should have been set in response->auth_challenge.
1562 EXPECT_FALSE(response->auth_challenge.get() == NULL);
1563
[email protected]71e4573a2009-05-21 22:03:001564 EXPECT_EQ(L"172.22.68.17:80", response->auth_challenge->host_and_port);
[email protected]3f918782009-02-28 01:29:241565 EXPECT_EQ(L"", response->auth_challenge->realm);
1566 EXPECT_EQ(L"ntlm", response->auth_challenge->scheme);
1567
[email protected]0757e7702009-03-27 04:00:221568 TestCompletionCallback callback3;
[email protected]3f918782009-02-28 01:29:241569
[email protected]0757e7702009-03-27 04:00:221570 rv = trans->RestartWithAuth(L"testing-ntlm", L"testing-ntlm", &callback3);
[email protected]1c773ea12009-04-28 19:58:421571 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]3f918782009-02-28 01:29:241572
[email protected]0757e7702009-03-27 04:00:221573 rv = callback3.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421574 EXPECT_EQ(OK, rv);
[email protected]3f918782009-02-28 01:29:241575
1576 response = trans->GetResponseInfo();
1577 EXPECT_TRUE(response->auth_challenge.get() == NULL);
1578 EXPECT_EQ(13, response->headers->GetContentLength());
1579}
1580
[email protected]385a4672009-03-11 22:21:291581// Enter a wrong password, and then the correct one.
1582TEST_F(HttpNetworkTransactionTest, NTLMAuth2) {
[email protected]1c773ea12009-04-28 19:58:421583 HttpAuthHandlerNTLM::ScopedProcSetter proc_setter(MockGenerateRandom2,
[email protected]fe2bc6a2009-03-23 16:52:201584 MockGetHostName);
[email protected]228ff742009-06-05 01:19:591585 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:401586 scoped_ptr<HttpTransaction> trans(
1587 new HttpNetworkTransaction(
[email protected]228ff742009-06-05 01:19:591588 CreateSession(&session_deps),
1589 &session_deps.socket_factory));
[email protected]385a4672009-03-11 22:21:291590
[email protected]1c773ea12009-04-28 19:58:421591 HttpRequestInfo request;
[email protected]385a4672009-03-11 22:21:291592 request.method = "GET";
1593 request.url = GURL("http://172.22.68.17/kids/login.aspx");
1594 request.load_flags = 0;
1595
1596 MockWrite data_writes1[] = {
1597 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
1598 "Host: 172.22.68.17\r\n"
1599 "Connection: keep-alive\r\n\r\n"),
1600 };
1601
1602 MockRead data_reads1[] = {
1603 MockRead("HTTP/1.1 401 Access Denied\r\n"),
1604 // Negotiate and NTLM are often requested together. We only support NTLM.
1605 MockRead("WWW-Authenticate: Negotiate\r\n"),
1606 MockRead("WWW-Authenticate: NTLM\r\n"),
1607 MockRead("Connection: close\r\n"),
1608 MockRead("Content-Length: 42\r\n"),
[email protected]076c85082009-04-10 23:21:361609 MockRead("Content-Type: text/html\r\n\r\n"),
[email protected]385a4672009-03-11 22:21:291610 // Missing content -- won't matter, as connection will be reset.
[email protected]1c773ea12009-04-28 19:58:421611 MockRead(false, ERR_UNEXPECTED),
[email protected]385a4672009-03-11 22:21:291612 };
1613
1614 MockWrite data_writes2[] = {
[email protected]0757e7702009-03-27 04:00:221615 // After restarting with a null identity, this is the
[email protected]385a4672009-03-11 22:21:291616 // request we should be issuing -- the final header line contains a Type
1617 // 1 message.
1618 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
1619 "Host: 172.22.68.17\r\n"
1620 "Connection: keep-alive\r\n"
1621 "Authorization: NTLM "
1622 "TlRMTVNTUAABAAAAB4IIAAAAAAAAAAAAAAAAAAAAAAA=\r\n\r\n"),
1623
1624 // After calling trans->RestartWithAuth(), we should send a Type 3 message
1625 // (the credentials for the origin server). The second request continues
1626 // on the same connection.
1627 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
1628 "Host: 172.22.68.17\r\n"
1629 "Connection: keep-alive\r\n"
1630 "Authorization: NTLM TlRMTVNTUAADAAAAGAAYAGgAAAAYABgAgA"
1631 "AAAAAAAABAAAAAGAAYAEAAAAAQABAAWAAAAAAAAAAAAAAABYIIAHQA"
1632 "ZQBzAHQAaQBuAGcALQBuAHQAbABtAFcAVABDAC0AVwBJAE4ANwCWeY"
1633 "XnSZNwoQAAAAAAAAAAAAAAAAAAAADLa34/phTTKzNTWdub+uyFleOj"
1634 "4Ww7b7E=\r\n\r\n"),
1635 };
1636
1637 MockRead data_reads2[] = {
1638 // The origin server responds with a Type 2 message.
1639 MockRead("HTTP/1.1 401 Access Denied\r\n"),
1640 MockRead("WWW-Authenticate: NTLM "
1641 "TlRMTVNTUAACAAAADAAMADgAAAAFgokCbVWUZezVGpAAAAAAAAAAALo"
1642 "AugBEAAAABQEoCgAAAA9HAE8ATwBHAEwARQACAAwARwBPAE8ARwBMAE"
1643 "UAAQAaAEEASwBFAEUAUwBBAFIAQQAtAEMATwBSAFAABAAeAGMAbwByA"
1644 "HAALgBnAG8AbwBnAGwAZQAuAGMAbwBtAAMAQABhAGsAZQBlAHMAYQBy"
1645 "AGEALQBjAG8AcgBwAC4AYQBkAC4AYwBvAHIAcAAuAGcAbwBvAGcAbAB"
1646 "lAC4AYwBvAG0ABQAeAGMAbwByAHAALgBnAG8AbwBnAGwAZQAuAGMAbw"
1647 "BtAAAAAAA=\r\n"),
1648 MockRead("Content-Length: 42\r\n"),
[email protected]076c85082009-04-10 23:21:361649 MockRead("Content-Type: text/html\r\n\r\n"),
[email protected]385a4672009-03-11 22:21:291650 MockRead("You are not authorized to view this page\r\n"),
1651
1652 // Wrong password.
1653 MockRead("HTTP/1.1 401 Access Denied\r\n"),
1654 MockRead("WWW-Authenticate: Negotiate\r\n"),
1655 MockRead("WWW-Authenticate: NTLM\r\n"),
1656 MockRead("Connection: close\r\n"),
1657 MockRead("Content-Length: 42\r\n"),
[email protected]076c85082009-04-10 23:21:361658 MockRead("Content-Type: text/html\r\n\r\n"),
[email protected]385a4672009-03-11 22:21:291659 // Missing content -- won't matter, as connection will be reset.
[email protected]1c773ea12009-04-28 19:58:421660 MockRead(false, ERR_UNEXPECTED),
[email protected]385a4672009-03-11 22:21:291661 };
1662
1663 MockWrite data_writes3[] = {
[email protected]0757e7702009-03-27 04:00:221664 // After restarting with a null identity, this is the
[email protected]385a4672009-03-11 22:21:291665 // request we should be issuing -- the final header line contains a Type
1666 // 1 message.
1667 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
1668 "Host: 172.22.68.17\r\n"
1669 "Connection: keep-alive\r\n"
1670 "Authorization: NTLM "
1671 "TlRMTVNTUAABAAAAB4IIAAAAAAAAAAAAAAAAAAAAAAA=\r\n\r\n"),
1672
1673 // After calling trans->RestartWithAuth(), we should send a Type 3 message
1674 // (the credentials for the origin server). The second request continues
1675 // on the same connection.
1676 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
1677 "Host: 172.22.68.17\r\n"
1678 "Connection: keep-alive\r\n"
1679 "Authorization: NTLM TlRMTVNTUAADAAAAGAAYAGgAAAAYABgAgA"
1680 "AAAAAAAABAAAAAGAAYAEAAAAAQABAAWAAAAAAAAAAAAAAABYIIAHQA"
1681 "ZQBzAHQAaQBuAGcALQBuAHQAbABtAFcAVABDAC0AVwBJAE4ANwBO54"
1682 "dFMVvTHwAAAAAAAAAAAAAAAAAAAACS7sT6Uzw7L0L//WUqlIaVWpbI"
1683 "+4MUm7c=\r\n\r\n"),
1684 };
1685
1686 MockRead data_reads3[] = {
1687 // The origin server responds with a Type 2 message.
1688 MockRead("HTTP/1.1 401 Access Denied\r\n"),
1689 MockRead("WWW-Authenticate: NTLM "
1690 "TlRMTVNTUAACAAAADAAMADgAAAAFgokCL24VN8dgOR8AAAAAAAAAALo"
1691 "AugBEAAAABQEoCgAAAA9HAE8ATwBHAEwARQACAAwARwBPAE8ARwBMAE"
1692 "UAAQAaAEEASwBFAEUAUwBBAFIAQQAtAEMATwBSAFAABAAeAGMAbwByA"
1693 "HAALgBnAG8AbwBnAGwAZQAuAGMAbwBtAAMAQABhAGsAZQBlAHMAYQBy"
1694 "AGEALQBjAG8AcgBwAC4AYQBkAC4AYwBvAHIAcAAuAGcAbwBvAGcAbAB"
1695 "lAC4AYwBvAG0ABQAeAGMAbwByAHAALgBnAG8AbwBnAGwAZQAuAGMAbw"
1696 "BtAAAAAAA=\r\n"),
1697 MockRead("Content-Length: 42\r\n"),
[email protected]076c85082009-04-10 23:21:361698 MockRead("Content-Type: text/html\r\n\r\n"),
[email protected]385a4672009-03-11 22:21:291699 MockRead("You are not authorized to view this page\r\n"),
1700
1701 // Lastly we get the desired content.
1702 MockRead("HTTP/1.1 200 OK\r\n"),
1703 MockRead("Content-Type: text/html; charset=utf-8\r\n"),
1704 MockRead("Content-Length: 13\r\n\r\n"),
1705 MockRead("Please Login\r\n"),
[email protected]1c773ea12009-04-28 19:58:421706 MockRead(false, OK),
[email protected]385a4672009-03-11 22:21:291707 };
1708
[email protected]69b43fe2009-06-15 09:47:371709 StaticMockSocket data1(data_reads1, data_writes1);
1710 StaticMockSocket data2(data_reads2, data_writes2);
1711 StaticMockSocket data3(data_reads3, data_writes3);
[email protected]228ff742009-06-05 01:19:591712 session_deps.socket_factory.AddMockSocket(&data1);
1713 session_deps.socket_factory.AddMockSocket(&data2);
1714 session_deps.socket_factory.AddMockSocket(&data3);
[email protected]385a4672009-03-11 22:21:291715
1716 TestCompletionCallback callback1;
1717
[email protected]684970b2009-08-14 04:54:461718 int rv = trans->Start(&request, &callback1, NULL);
[email protected]1c773ea12009-04-28 19:58:421719 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]385a4672009-03-11 22:21:291720
1721 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421722 EXPECT_EQ(OK, rv);
[email protected]385a4672009-03-11 22:21:291723
[email protected]0757e7702009-03-27 04:00:221724 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
[email protected]385a4672009-03-11 22:21:291725 TestCompletionCallback callback2;
[email protected]0757e7702009-03-27 04:00:221726 rv = trans->RestartWithAuth(std::wstring(), std::wstring(), &callback2);
[email protected]1c773ea12009-04-28 19:58:421727 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]385a4672009-03-11 22:21:291728 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421729 EXPECT_EQ(OK, rv);
[email protected]0757e7702009-03-27 04:00:221730 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
[email protected]385a4672009-03-11 22:21:291731
[email protected]1c773ea12009-04-28 19:58:421732 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]385a4672009-03-11 22:21:291733 EXPECT_FALSE(response == NULL);
1734
1735 // The password prompt info should have been set in response->auth_challenge.
1736 EXPECT_FALSE(response->auth_challenge.get() == NULL);
1737
[email protected]71e4573a2009-05-21 22:03:001738 EXPECT_EQ(L"172.22.68.17:80", response->auth_challenge->host_and_port);
[email protected]385a4672009-03-11 22:21:291739 EXPECT_EQ(L"", response->auth_challenge->realm);
1740 EXPECT_EQ(L"ntlm", response->auth_challenge->scheme);
1741
1742 TestCompletionCallback callback3;
1743
[email protected]0757e7702009-03-27 04:00:221744 // Enter the wrong password.
1745 rv = trans->RestartWithAuth(L"testing-ntlm", L"wrongpassword", &callback3);
[email protected]1c773ea12009-04-28 19:58:421746 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]385a4672009-03-11 22:21:291747
1748 rv = callback3.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421749 EXPECT_EQ(OK, rv);
[email protected]385a4672009-03-11 22:21:291750
[email protected]0757e7702009-03-27 04:00:221751 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
1752 TestCompletionCallback callback4;
1753 rv = trans->RestartWithAuth(std::wstring(), std::wstring(), &callback4);
[email protected]1c773ea12009-04-28 19:58:421754 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]0757e7702009-03-27 04:00:221755 rv = callback4.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421756 EXPECT_EQ(OK, rv);
[email protected]0757e7702009-03-27 04:00:221757 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
1758
1759 response = trans->GetResponseInfo();
1760 EXPECT_FALSE(response == NULL);
1761
1762 // The password prompt info should have been set in response->auth_challenge.
1763 EXPECT_FALSE(response->auth_challenge.get() == NULL);
1764
[email protected]71e4573a2009-05-21 22:03:001765 EXPECT_EQ(L"172.22.68.17:80", response->auth_challenge->host_and_port);
[email protected]0757e7702009-03-27 04:00:221766 EXPECT_EQ(L"", response->auth_challenge->realm);
1767 EXPECT_EQ(L"ntlm", response->auth_challenge->scheme);
1768
1769 TestCompletionCallback callback5;
1770
1771 // Now enter the right password.
1772 rv = trans->RestartWithAuth(L"testing-ntlm", L"testing-ntlm", &callback5);
[email protected]1c773ea12009-04-28 19:58:421773 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]0757e7702009-03-27 04:00:221774
1775 rv = callback5.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421776 EXPECT_EQ(OK, rv);
[email protected]0757e7702009-03-27 04:00:221777
[email protected]385a4672009-03-11 22:21:291778 response = trans->GetResponseInfo();
1779 EXPECT_TRUE(response->auth_challenge.get() == NULL);
1780 EXPECT_EQ(13, response->headers->GetContentLength());
1781}
1782
[email protected]4ddaf2502008-10-23 18:26:191783// Test reading a server response which has only headers, and no body.
1784// After some maximum number of bytes is consumed, the transaction should
1785// fail with ERR_RESPONSE_HEADERS_TOO_BIG.
1786TEST_F(HttpNetworkTransactionTest, LargeHeadersNoBody) {
[email protected]228ff742009-06-05 01:19:591787 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:401788 scoped_ptr<HttpTransaction> trans(
1789 new HttpNetworkTransaction(
[email protected]228ff742009-06-05 01:19:591790 CreateSession(&session_deps),
1791 &session_deps.socket_factory));
[email protected]4ddaf2502008-10-23 18:26:191792
[email protected]1c773ea12009-04-28 19:58:421793 HttpRequestInfo request;
[email protected]4ddaf2502008-10-23 18:26:191794 request.method = "GET";
1795 request.url = GURL("http://www.google.com/");
1796 request.load_flags = 0;
1797
1798 // Respond with 50 kb of headers (we should fail after 32 kb).
[email protected]15a5ccf82008-10-23 19:57:431799 std::string large_headers_string;
1800 FillLargeHeadersString(&large_headers_string, 50 * 1024);
[email protected]4ddaf2502008-10-23 18:26:191801
1802 MockRead data_reads[] = {
1803 MockRead("HTTP/1.0 200 OK\r\n"),
[email protected]15a5ccf82008-10-23 19:57:431804 MockRead(true, large_headers_string.data(), large_headers_string.size()),
[email protected]4ddaf2502008-10-23 18:26:191805 MockRead("\r\nBODY"),
[email protected]1c773ea12009-04-28 19:58:421806 MockRead(false, OK),
[email protected]4ddaf2502008-10-23 18:26:191807 };
[email protected]69b43fe2009-06-15 09:47:371808 StaticMockSocket data(data_reads, NULL);
[email protected]228ff742009-06-05 01:19:591809 session_deps.socket_factory.AddMockSocket(&data);
[email protected]4ddaf2502008-10-23 18:26:191810
1811 TestCompletionCallback callback;
1812
[email protected]684970b2009-08-14 04:54:461813 int rv = trans->Start(&request, &callback, NULL);
[email protected]1c773ea12009-04-28 19:58:421814 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]4ddaf2502008-10-23 18:26:191815
1816 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421817 EXPECT_EQ(ERR_RESPONSE_HEADERS_TOO_BIG, rv);
[email protected]4ddaf2502008-10-23 18:26:191818
[email protected]1c773ea12009-04-28 19:58:421819 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]4ddaf2502008-10-23 18:26:191820 EXPECT_TRUE(response == NULL);
1821}
[email protected]f4e426b2008-11-05 00:24:491822
1823// Make sure that we don't try to reuse a TCPClientSocket when failing to
1824// establish tunnel.
1825// http://code.google.com/p/chromium/issues/detail?id=3772
1826TEST_F(HttpNetworkTransactionTest, DontRecycleTCPSocketForSSLTunnel) {
1827 // Configure against proxy server "myproxy:70".
[email protected]228ff742009-06-05 01:19:591828 SessionDependencies session_deps(CreateFixedProxyService("myproxy:70"));
[email protected]db8f44c2008-12-13 04:52:011829
[email protected]228ff742009-06-05 01:19:591830 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]f4e426b2008-11-05 00:24:491831
[email protected]1c773ea12009-04-28 19:58:421832 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(
[email protected]228ff742009-06-05 01:19:591833 session.get(), &session_deps.socket_factory));
[email protected]f4e426b2008-11-05 00:24:491834
[email protected]1c773ea12009-04-28 19:58:421835 HttpRequestInfo request;
[email protected]f4e426b2008-11-05 00:24:491836 request.method = "GET";
1837 request.url = GURL("https://www.google.com/");
1838 request.load_flags = 0;
1839
1840 // Since we have proxy, should try to establish tunnel.
1841 MockWrite data_writes1[] = {
1842 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
[email protected]e44de5d2009-06-05 20:12:451843 "Host: www.google.com\r\n"
1844 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]f4e426b2008-11-05 00:24:491845 };
1846
[email protected]77848d12008-11-14 00:00:221847 // The proxy responds to the connect with a 404, using a persistent
[email protected]f4e426b2008-11-05 00:24:491848 // connection. Usually a proxy would return 501 (not implemented),
1849 // or 200 (tunnel established).
1850 MockRead data_reads1[] = {
1851 MockRead("HTTP/1.1 404 Not Found\r\n"),
1852 MockRead("Content-Length: 10\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:421853 MockRead(false, ERR_UNEXPECTED), // Should not be reached.
[email protected]f4e426b2008-11-05 00:24:491854 };
1855
[email protected]69b43fe2009-06-15 09:47:371856 StaticMockSocket data1(data_reads1, data_writes1);
[email protected]228ff742009-06-05 01:19:591857 session_deps.socket_factory.AddMockSocket(&data1);
[email protected]f4e426b2008-11-05 00:24:491858
1859 TestCompletionCallback callback1;
1860
[email protected]684970b2009-08-14 04:54:461861 int rv = trans->Start(&request, &callback1, NULL);
[email protected]1c773ea12009-04-28 19:58:421862 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f4e426b2008-11-05 00:24:491863
1864 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421865 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED, rv);
[email protected]f4e426b2008-11-05 00:24:491866
[email protected]1c773ea12009-04-28 19:58:421867 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]c744cf22009-02-27 07:28:081868 EXPECT_TRUE(response == NULL);
[email protected]f4e426b2008-11-05 00:24:491869
[email protected]b4404c02009-04-10 16:38:521870 // Empty the current queue. This is necessary because idle sockets are
1871 // added to the connection pool asynchronously with a PostTask.
1872 MessageLoop::current()->RunAllPending();
1873
[email protected]f4e426b2008-11-05 00:24:491874 // We now check to make sure the TCPClientSocket was not added back to
1875 // the pool.
[email protected]df0c05c62009-06-17 15:50:581876 EXPECT_EQ(0, session->connection_pool()->IdleSocketCount());
[email protected]f4e426b2008-11-05 00:24:491877 trans.reset();
[email protected]b4404c02009-04-10 16:38:521878 MessageLoop::current()->RunAllPending();
[email protected]f4e426b2008-11-05 00:24:491879 // Make sure that the socket didn't get recycled after calling the destructor.
[email protected]df0c05c62009-06-17 15:50:581880 EXPECT_EQ(0, session->connection_pool()->IdleSocketCount());
[email protected]f4e426b2008-11-05 00:24:491881}
[email protected]372d34a2008-11-05 21:30:511882
[email protected]1b157c02009-04-21 01:55:401883// Make sure that we recycle a socket after reading all of the response body.
1884TEST_F(HttpNetworkTransactionTest, RecycleSocket) {
[email protected]228ff742009-06-05 01:19:591885 SessionDependencies session_deps;
1886 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]1b157c02009-04-21 01:55:401887
[email protected]1c773ea12009-04-28 19:58:421888 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(
[email protected]228ff742009-06-05 01:19:591889 session.get(), &session_deps.socket_factory));
[email protected]1b157c02009-04-21 01:55:401890
[email protected]1c773ea12009-04-28 19:58:421891 HttpRequestInfo request;
[email protected]1b157c02009-04-21 01:55:401892 request.method = "GET";
1893 request.url = GURL("http://www.google.com/");
1894 request.load_flags = 0;
1895
1896 MockRead data_reads[] = {
1897 // A part of the response body is received with the response headers.
1898 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 11\r\n\r\nhel"),
1899 // The rest of the response body is received in two parts.
1900 MockRead("lo"),
1901 MockRead(" world"),
1902 MockRead("junk"), // Should not be read!!
[email protected]1c773ea12009-04-28 19:58:421903 MockRead(false, OK),
[email protected]1b157c02009-04-21 01:55:401904 };
1905
[email protected]69b43fe2009-06-15 09:47:371906 StaticMockSocket data(data_reads, NULL);
[email protected]228ff742009-06-05 01:19:591907 session_deps.socket_factory.AddMockSocket(&data);
[email protected]1b157c02009-04-21 01:55:401908
1909 TestCompletionCallback callback;
1910
[email protected]684970b2009-08-14 04:54:461911 int rv = trans->Start(&request, &callback, NULL);
[email protected]1c773ea12009-04-28 19:58:421912 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]1b157c02009-04-21 01:55:401913
1914 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421915 EXPECT_EQ(OK, rv);
[email protected]1b157c02009-04-21 01:55:401916
[email protected]1c773ea12009-04-28 19:58:421917 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]1b157c02009-04-21 01:55:401918 EXPECT_TRUE(response != NULL);
1919
1920 EXPECT_TRUE(response->headers != NULL);
1921 std::string status_line = response->headers->GetStatusLine();
1922 EXPECT_EQ("HTTP/1.1 200 OK", status_line);
1923
[email protected]df0c05c62009-06-17 15:50:581924 EXPECT_EQ(0, session->connection_pool()->IdleSocketCount());
[email protected]1b157c02009-04-21 01:55:401925
1926 std::string response_data;
1927 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:421928 EXPECT_EQ(OK, rv);
[email protected]1b157c02009-04-21 01:55:401929 EXPECT_EQ("hello world", response_data);
1930
1931 // Empty the current queue. This is necessary because idle sockets are
1932 // added to the connection pool asynchronously with a PostTask.
1933 MessageLoop::current()->RunAllPending();
1934
1935 // We now check to make sure the socket was added back to the pool.
[email protected]df0c05c62009-06-17 15:50:581936 EXPECT_EQ(1, session->connection_pool()->IdleSocketCount());
[email protected]1b157c02009-04-21 01:55:401937}
1938
[email protected]b4404c02009-04-10 16:38:521939// Make sure that we recycle a socket after a zero-length response.
1940// http://crbug.com/9880
1941TEST_F(HttpNetworkTransactionTest, RecycleSocketAfterZeroContentLength) {
[email protected]228ff742009-06-05 01:19:591942 SessionDependencies session_deps;
1943 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]b4404c02009-04-10 16:38:521944
[email protected]1c773ea12009-04-28 19:58:421945 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(
[email protected]228ff742009-06-05 01:19:591946 session.get(), &session_deps.socket_factory));
[email protected]b4404c02009-04-10 16:38:521947
[email protected]1c773ea12009-04-28 19:58:421948 HttpRequestInfo request;
[email protected]b4404c02009-04-10 16:38:521949 request.method = "GET";
1950 request.url = GURL("http://www.google.com/csi?v=3&s=web&action=&"
1951 "tran=undefined&ei=mAXcSeegAo-SMurloeUN&"
1952 "e=17259,18167,19592,19773,19981,20133,20173,20233&"
1953 "rt=prt.2642,ol.2649,xjs.2951");
1954 request.load_flags = 0;
1955
1956 MockRead data_reads[] = {
1957 MockRead("HTTP/1.1 204 No Content\r\n"
1958 "Content-Length: 0\r\n"
1959 "Content-Type: text/html\r\n\r\n"),
1960 MockRead("junk"), // Should not be read!!
[email protected]1c773ea12009-04-28 19:58:421961 MockRead(false, OK),
[email protected]b4404c02009-04-10 16:38:521962 };
1963
[email protected]69b43fe2009-06-15 09:47:371964 StaticMockSocket data(data_reads, NULL);
[email protected]228ff742009-06-05 01:19:591965 session_deps.socket_factory.AddMockSocket(&data);
[email protected]b4404c02009-04-10 16:38:521966
1967 TestCompletionCallback callback;
1968
[email protected]684970b2009-08-14 04:54:461969 int rv = trans->Start(&request, &callback, NULL);
[email protected]1c773ea12009-04-28 19:58:421970 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]b4404c02009-04-10 16:38:521971
1972 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421973 EXPECT_EQ(OK, rv);
[email protected]b4404c02009-04-10 16:38:521974
[email protected]1c773ea12009-04-28 19:58:421975 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]b4404c02009-04-10 16:38:521976 EXPECT_TRUE(response != NULL);
1977
1978 EXPECT_TRUE(response->headers != NULL);
1979 std::string status_line = response->headers->GetStatusLine();
1980 EXPECT_EQ("HTTP/1.1 204 No Content", status_line);
1981
[email protected]df0c05c62009-06-17 15:50:581982 EXPECT_EQ(0, session->connection_pool()->IdleSocketCount());
[email protected]b4404c02009-04-10 16:38:521983
1984 std::string response_data;
1985 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:421986 EXPECT_EQ(OK, rv);
[email protected]b4404c02009-04-10 16:38:521987 EXPECT_EQ("", response_data);
1988
1989 // Empty the current queue. This is necessary because idle sockets are
1990 // added to the connection pool asynchronously with a PostTask.
1991 MessageLoop::current()->RunAllPending();
1992
1993 // We now check to make sure the socket was added back to the pool.
[email protected]df0c05c62009-06-17 15:50:581994 EXPECT_EQ(1, session->connection_pool()->IdleSocketCount());
[email protected]b4404c02009-04-10 16:38:521995}
1996
[email protected]372d34a2008-11-05 21:30:511997TEST_F(HttpNetworkTransactionTest, ResendRequestOnWriteBodyError) {
[email protected]1c773ea12009-04-28 19:58:421998 HttpRequestInfo request[2];
[email protected]372d34a2008-11-05 21:30:511999 // Transaction 1: a GET request that succeeds. The socket is recycled
2000 // after use.
2001 request[0].method = "GET";
2002 request[0].url = GURL("http://www.google.com/");
2003 request[0].load_flags = 0;
2004 // Transaction 2: a POST request. Reuses the socket kept alive from
2005 // transaction 1. The first attempts fails when writing the POST data.
2006 // This causes the transaction to retry with a new socket. The second
2007 // attempt succeeds.
2008 request[1].method = "POST";
2009 request[1].url = GURL("http://www.google.com/login.cgi");
[email protected]1c773ea12009-04-28 19:58:422010 request[1].upload_data = new UploadData;
[email protected]372d34a2008-11-05 21:30:512011 request[1].upload_data->AppendBytes("foo", 3);
2012 request[1].load_flags = 0;
2013
[email protected]228ff742009-06-05 01:19:592014 SessionDependencies session_deps;
2015 scoped_refptr<HttpNetworkSession> session = CreateSession(&session_deps);
[email protected]372d34a2008-11-05 21:30:512016
2017 // The first socket is used for transaction 1 and the first attempt of
2018 // transaction 2.
2019
2020 // The response of transaction 1.
2021 MockRead data_reads1[] = {
2022 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 11\r\n\r\n"),
2023 MockRead("hello world"),
[email protected]1c773ea12009-04-28 19:58:422024 MockRead(false, OK),
[email protected]372d34a2008-11-05 21:30:512025 };
2026 // The mock write results of transaction 1 and the first attempt of
2027 // transaction 2.
2028 MockWrite data_writes1[] = {
2029 MockWrite(false, 64), // GET
2030 MockWrite(false, 93), // POST
[email protected]1c773ea12009-04-28 19:58:422031 MockWrite(false, ERR_CONNECTION_ABORTED), // POST data
[email protected]372d34a2008-11-05 21:30:512032 };
[email protected]69b43fe2009-06-15 09:47:372033 StaticMockSocket data1(data_reads1, data_writes1);
[email protected]372d34a2008-11-05 21:30:512034
2035 // The second socket is used for the second attempt of transaction 2.
2036
2037 // The response of transaction 2.
2038 MockRead data_reads2[] = {
2039 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 7\r\n\r\n"),
2040 MockRead("welcome"),
[email protected]1c773ea12009-04-28 19:58:422041 MockRead(false, OK),
[email protected]372d34a2008-11-05 21:30:512042 };
2043 // The mock write results of the second attempt of transaction 2.
2044 MockWrite data_writes2[] = {
2045 MockWrite(false, 93), // POST
2046 MockWrite(false, 3), // POST data
2047 };
[email protected]69b43fe2009-06-15 09:47:372048 StaticMockSocket data2(data_reads2, data_writes2);
[email protected]372d34a2008-11-05 21:30:512049
[email protected]228ff742009-06-05 01:19:592050 session_deps.socket_factory.AddMockSocket(&data1);
2051 session_deps.socket_factory.AddMockSocket(&data2);
[email protected]372d34a2008-11-05 21:30:512052
2053 const char* kExpectedResponseData[] = {
2054 "hello world", "welcome"
2055 };
2056
2057 for (int i = 0; i < 2; ++i) {
[email protected]1c773ea12009-04-28 19:58:422058 scoped_ptr<HttpTransaction> trans(
[email protected]228ff742009-06-05 01:19:592059 new HttpNetworkTransaction(session, &session_deps.socket_factory));
[email protected]372d34a2008-11-05 21:30:512060
2061 TestCompletionCallback callback;
2062
[email protected]684970b2009-08-14 04:54:462063 int rv = trans->Start(&request[i], &callback, NULL);
[email protected]1c773ea12009-04-28 19:58:422064 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]372d34a2008-11-05 21:30:512065
2066 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422067 EXPECT_EQ(OK, rv);
[email protected]372d34a2008-11-05 21:30:512068
[email protected]1c773ea12009-04-28 19:58:422069 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]372d34a2008-11-05 21:30:512070 EXPECT_TRUE(response != NULL);
2071
2072 EXPECT_TRUE(response->headers != NULL);
2073 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
2074
2075 std::string response_data;
2076 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:422077 EXPECT_EQ(OK, rv);
[email protected]372d34a2008-11-05 21:30:512078 EXPECT_EQ(kExpectedResponseData[i], response_data);
2079 }
2080}
[email protected]f9ee6b52008-11-08 06:46:232081
2082// Test the request-challenge-retry sequence for basic auth when there is
2083// an identity in the URL. The request should be sent as normal, but when
2084// it fails the identity from the URL is used to answer the challenge.
2085TEST_F(HttpNetworkTransactionTest, AuthIdentityInUrl) {
[email protected]228ff742009-06-05 01:19:592086 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:402087 scoped_ptr<HttpTransaction> trans(
2088 new HttpNetworkTransaction(
[email protected]228ff742009-06-05 01:19:592089 CreateSession(&session_deps),
2090 &session_deps.socket_factory));
[email protected]f9ee6b52008-11-08 06:46:232091
[email protected]1c773ea12009-04-28 19:58:422092 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:232093 request.method = "GET";
2094 // Note: the URL has a username:password in it.
[email protected]a97cca42009-08-14 01:00:292095 request.url = GURL("http://foo:b@[email protected]/");
2096
2097 // The password contains an escaped character -- for this test to pass it
2098 // will need to be unescaped by HttpNetworkTransaction.
2099 EXPECT_EQ("b%40r", request.url.password());
2100
[email protected]f9ee6b52008-11-08 06:46:232101 request.load_flags = 0;
2102
2103 MockWrite data_writes1[] = {
2104 MockWrite("GET / HTTP/1.1\r\n"
2105 "Host: www.google.com\r\n"
2106 "Connection: keep-alive\r\n\r\n"),
2107 };
2108
2109 MockRead data_reads1[] = {
2110 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
2111 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2112 MockRead("Content-Length: 10\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422113 MockRead(false, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:232114 };
2115
2116 // After the challenge above, the transaction will be restarted using the
2117 // identity from the url (foo, bar) to answer the challenge.
2118 MockWrite data_writes2[] = {
2119 MockWrite("GET / HTTP/1.1\r\n"
2120 "Host: www.google.com\r\n"
2121 "Connection: keep-alive\r\n"
[email protected]a97cca42009-08-14 01:00:292122 "Authorization: Basic Zm9vOmJAcg==\r\n\r\n"),
[email protected]f9ee6b52008-11-08 06:46:232123 };
2124
2125 MockRead data_reads2[] = {
2126 MockRead("HTTP/1.0 200 OK\r\n"),
2127 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422128 MockRead(false, OK),
[email protected]f9ee6b52008-11-08 06:46:232129 };
2130
[email protected]69b43fe2009-06-15 09:47:372131 StaticMockSocket data1(data_reads1, data_writes1);
2132 StaticMockSocket data2(data_reads2, data_writes2);
[email protected]228ff742009-06-05 01:19:592133 session_deps.socket_factory.AddMockSocket(&data1);
2134 session_deps.socket_factory.AddMockSocket(&data2);
[email protected]f9ee6b52008-11-08 06:46:232135
2136 TestCompletionCallback callback1;
2137
[email protected]684970b2009-08-14 04:54:462138 int rv = trans->Start(&request, &callback1, NULL);
[email protected]1c773ea12009-04-28 19:58:422139 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:232140
2141 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422142 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:232143
[email protected]0757e7702009-03-27 04:00:222144 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
2145 TestCompletionCallback callback2;
2146 rv = trans->RestartWithAuth(std::wstring(), std::wstring(), &callback2);
[email protected]1c773ea12009-04-28 19:58:422147 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]0757e7702009-03-27 04:00:222148 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422149 EXPECT_EQ(OK, rv);
[email protected]0757e7702009-03-27 04:00:222150 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
2151
[email protected]1c773ea12009-04-28 19:58:422152 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]f9ee6b52008-11-08 06:46:232153 EXPECT_FALSE(response == NULL);
2154
2155 // There is no challenge info, since the identity in URL worked.
2156 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2157
2158 EXPECT_EQ(100, response->headers->GetContentLength());
2159
2160 // Empty the current queue.
2161 MessageLoop::current()->RunAllPending();
2162}
2163
2164// Test that previously tried username/passwords for a realm get re-used.
2165TEST_F(HttpNetworkTransactionTest, BasicAuthCacheAndPreauth) {
[email protected]228ff742009-06-05 01:19:592166 SessionDependencies session_deps;
2167 scoped_refptr<HttpNetworkSession> session = CreateSession(&session_deps);
[email protected]f9ee6b52008-11-08 06:46:232168
2169 // Transaction 1: authenticate (foo, bar) on MyRealm1
2170 {
[email protected]1c773ea12009-04-28 19:58:422171 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(
[email protected]228ff742009-06-05 01:19:592172 session, &session_deps.socket_factory));
[email protected]f9ee6b52008-11-08 06:46:232173
[email protected]1c773ea12009-04-28 19:58:422174 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:232175 request.method = "GET";
2176 request.url = GURL("http://www.google.com/x/y/z");
2177 request.load_flags = 0;
2178
2179 MockWrite data_writes1[] = {
2180 MockWrite("GET /x/y/z HTTP/1.1\r\n"
2181 "Host: www.google.com\r\n"
2182 "Connection: keep-alive\r\n\r\n"),
2183 };
2184
2185 MockRead data_reads1[] = {
2186 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
2187 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2188 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422189 MockRead(false, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:232190 };
2191
2192 // Resend with authorization (username=foo, password=bar)
2193 MockWrite data_writes2[] = {
2194 MockWrite("GET /x/y/z HTTP/1.1\r\n"
2195 "Host: www.google.com\r\n"
2196 "Connection: keep-alive\r\n"
2197 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2198 };
2199
2200 // Sever accepts the authorization.
2201 MockRead data_reads2[] = {
2202 MockRead("HTTP/1.0 200 OK\r\n"),
2203 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422204 MockRead(false, OK),
[email protected]f9ee6b52008-11-08 06:46:232205 };
2206
[email protected]69b43fe2009-06-15 09:47:372207 StaticMockSocket data1(data_reads1, data_writes1);
2208 StaticMockSocket data2(data_reads2, data_writes2);
[email protected]228ff742009-06-05 01:19:592209 session_deps.socket_factory.AddMockSocket(&data1);
2210 session_deps.socket_factory.AddMockSocket(&data2);
[email protected]f9ee6b52008-11-08 06:46:232211
2212 TestCompletionCallback callback1;
2213
[email protected]684970b2009-08-14 04:54:462214 int rv = trans->Start(&request, &callback1, NULL);
[email protected]1c773ea12009-04-28 19:58:422215 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:232216
2217 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422218 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:232219
[email protected]1c773ea12009-04-28 19:58:422220 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]f9ee6b52008-11-08 06:46:232221 EXPECT_FALSE(response == NULL);
2222
2223 // The password prompt info should have been set in
2224 // response->auth_challenge.
2225 EXPECT_FALSE(response->auth_challenge.get() == NULL);
2226
[email protected]71e4573a2009-05-21 22:03:002227 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
[email protected]f9ee6b52008-11-08 06:46:232228 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
2229 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
2230
2231 TestCompletionCallback callback2;
2232
2233 rv = trans->RestartWithAuth(L"foo", L"bar", &callback2);
[email protected]1c773ea12009-04-28 19:58:422234 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:232235
2236 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422237 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:232238
2239 response = trans->GetResponseInfo();
2240 EXPECT_FALSE(response == NULL);
2241 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2242 EXPECT_EQ(100, response->headers->GetContentLength());
2243 }
2244
2245 // ------------------------------------------------------------------------
2246
2247 // Transaction 2: authenticate (foo2, bar2) on MyRealm2
2248 {
[email protected]1c773ea12009-04-28 19:58:422249 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(
[email protected]228ff742009-06-05 01:19:592250 session, &session_deps.socket_factory));
[email protected]f9ee6b52008-11-08 06:46:232251
[email protected]1c773ea12009-04-28 19:58:422252 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:232253 request.method = "GET";
2254 // Note that Transaction 1 was at /x/y/z, so this is in the same
2255 // protection space as MyRealm1.
2256 request.url = GURL("http://www.google.com/x/y/a/b");
2257 request.load_flags = 0;
2258
2259 MockWrite data_writes1[] = {
2260 MockWrite("GET /x/y/a/b HTTP/1.1\r\n"
2261 "Host: www.google.com\r\n"
2262 "Connection: keep-alive\r\n"
2263 // Send preemptive authorization for MyRealm1
2264 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2265 };
2266
2267 // The server didn't like the preemptive authorization, and
2268 // challenges us for a different realm (MyRealm2).
2269 MockRead data_reads1[] = {
2270 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
2271 MockRead("WWW-Authenticate: Basic realm=\"MyRealm2\"\r\n"),
2272 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422273 MockRead(false, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:232274 };
2275
2276 // Resend with authorization for MyRealm2 (username=foo2, password=bar2)
2277 MockWrite data_writes2[] = {
2278 MockWrite("GET /x/y/a/b HTTP/1.1\r\n"
2279 "Host: www.google.com\r\n"
2280 "Connection: keep-alive\r\n"
2281 "Authorization: Basic Zm9vMjpiYXIy\r\n\r\n"),
2282 };
2283
2284 // Sever accepts the authorization.
2285 MockRead data_reads2[] = {
2286 MockRead("HTTP/1.0 200 OK\r\n"),
2287 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422288 MockRead(false, OK),
[email protected]f9ee6b52008-11-08 06:46:232289 };
2290
[email protected]69b43fe2009-06-15 09:47:372291 StaticMockSocket data1(data_reads1, data_writes1);
2292 StaticMockSocket data2(data_reads2, data_writes2);
[email protected]228ff742009-06-05 01:19:592293 session_deps.socket_factory.AddMockSocket(&data1);
2294 session_deps.socket_factory.AddMockSocket(&data2);
[email protected]f9ee6b52008-11-08 06:46:232295
2296 TestCompletionCallback callback1;
2297
[email protected]684970b2009-08-14 04:54:462298 int rv = trans->Start(&request, &callback1, NULL);
[email protected]1c773ea12009-04-28 19:58:422299 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:232300
2301 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422302 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:232303
[email protected]1c773ea12009-04-28 19:58:422304 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]f9ee6b52008-11-08 06:46:232305 EXPECT_FALSE(response == NULL);
2306
2307 // The password prompt info should have been set in
2308 // response->auth_challenge.
2309 EXPECT_FALSE(response->auth_challenge.get() == NULL);
2310
[email protected]71e4573a2009-05-21 22:03:002311 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
[email protected]f9ee6b52008-11-08 06:46:232312 EXPECT_EQ(L"MyRealm2", response->auth_challenge->realm);
2313 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
2314
2315 TestCompletionCallback callback2;
2316
2317 rv = trans->RestartWithAuth(L"foo2", L"bar2", &callback2);
[email protected]1c773ea12009-04-28 19:58:422318 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:232319
2320 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422321 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:232322
2323 response = trans->GetResponseInfo();
2324 EXPECT_FALSE(response == NULL);
2325 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2326 EXPECT_EQ(100, response->headers->GetContentLength());
2327 }
2328
2329 // ------------------------------------------------------------------------
2330
2331 // Transaction 3: Resend a request in MyRealm's protection space --
2332 // succeed with preemptive authorization.
2333 {
[email protected]1c773ea12009-04-28 19:58:422334 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(
[email protected]228ff742009-06-05 01:19:592335 session, &session_deps.socket_factory));
[email protected]f9ee6b52008-11-08 06:46:232336
[email protected]1c773ea12009-04-28 19:58:422337 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:232338 request.method = "GET";
2339 request.url = GURL("http://www.google.com/x/y/z2");
2340 request.load_flags = 0;
2341
2342 MockWrite data_writes1[] = {
2343 MockWrite("GET /x/y/z2 HTTP/1.1\r\n"
2344 "Host: www.google.com\r\n"
2345 "Connection: keep-alive\r\n"
2346 // The authorization for MyRealm1 gets sent preemptively
2347 // (since the url is in the same protection space)
2348 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2349 };
2350
2351 // Sever accepts the preemptive authorization
2352 MockRead data_reads1[] = {
2353 MockRead("HTTP/1.0 200 OK\r\n"),
2354 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422355 MockRead(false, OK),
[email protected]f9ee6b52008-11-08 06:46:232356 };
2357
[email protected]69b43fe2009-06-15 09:47:372358 StaticMockSocket data1(data_reads1, data_writes1);
[email protected]228ff742009-06-05 01:19:592359 session_deps.socket_factory.AddMockSocket(&data1);
[email protected]f9ee6b52008-11-08 06:46:232360
2361 TestCompletionCallback callback1;
2362
[email protected]684970b2009-08-14 04:54:462363 int rv = trans->Start(&request, &callback1, NULL);
[email protected]1c773ea12009-04-28 19:58:422364 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:232365
2366 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422367 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:232368
[email protected]1c773ea12009-04-28 19:58:422369 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]f9ee6b52008-11-08 06:46:232370 EXPECT_FALSE(response == NULL);
2371
2372 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2373 EXPECT_EQ(100, response->headers->GetContentLength());
2374 }
2375
2376 // ------------------------------------------------------------------------
2377
2378 // Transaction 4: request another URL in MyRealm (however the
2379 // url is not known to belong to the protection space, so no pre-auth).
2380 {
[email protected]1c773ea12009-04-28 19:58:422381 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(
[email protected]228ff742009-06-05 01:19:592382 session, &session_deps.socket_factory));
[email protected]f9ee6b52008-11-08 06:46:232383
[email protected]1c773ea12009-04-28 19:58:422384 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:232385 request.method = "GET";
2386 request.url = GURL("http://www.google.com/x/1");
2387 request.load_flags = 0;
2388
2389 MockWrite data_writes1[] = {
2390 MockWrite("GET /x/1 HTTP/1.1\r\n"
2391 "Host: www.google.com\r\n"
2392 "Connection: keep-alive\r\n\r\n"),
2393 };
2394
2395 MockRead data_reads1[] = {
2396 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
2397 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2398 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422399 MockRead(false, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:232400 };
2401
2402 // Resend with authorization from MyRealm's cache.
2403 MockWrite data_writes2[] = {
2404 MockWrite("GET /x/1 HTTP/1.1\r\n"
2405 "Host: www.google.com\r\n"
2406 "Connection: keep-alive\r\n"
2407 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2408 };
2409
2410 // Sever accepts the authorization.
2411 MockRead data_reads2[] = {
2412 MockRead("HTTP/1.0 200 OK\r\n"),
2413 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422414 MockRead(false, OK),
[email protected]f9ee6b52008-11-08 06:46:232415 };
2416
[email protected]69b43fe2009-06-15 09:47:372417 StaticMockSocket data1(data_reads1, data_writes1);
2418 StaticMockSocket data2(data_reads2, data_writes2);
[email protected]228ff742009-06-05 01:19:592419 session_deps.socket_factory.AddMockSocket(&data1);
2420 session_deps.socket_factory.AddMockSocket(&data2);
[email protected]f9ee6b52008-11-08 06:46:232421
2422 TestCompletionCallback callback1;
2423
[email protected]684970b2009-08-14 04:54:462424 int rv = trans->Start(&request, &callback1, NULL);
[email protected]1c773ea12009-04-28 19:58:422425 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:232426
2427 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422428 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:232429
[email protected]0757e7702009-03-27 04:00:222430 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
2431 TestCompletionCallback callback2;
2432 rv = trans->RestartWithAuth(std::wstring(), std::wstring(), &callback2);
[email protected]1c773ea12009-04-28 19:58:422433 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]0757e7702009-03-27 04:00:222434 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422435 EXPECT_EQ(OK, rv);
[email protected]0757e7702009-03-27 04:00:222436 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
2437
[email protected]1c773ea12009-04-28 19:58:422438 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]f9ee6b52008-11-08 06:46:232439 EXPECT_FALSE(response == NULL);
2440 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2441 EXPECT_EQ(100, response->headers->GetContentLength());
2442 }
2443
2444 // ------------------------------------------------------------------------
2445
2446 // Transaction 5: request a URL in MyRealm, but the server rejects the
2447 // cached identity. Should invalidate and re-prompt.
2448 {
[email protected]1c773ea12009-04-28 19:58:422449 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(
[email protected]228ff742009-06-05 01:19:592450 session, &session_deps.socket_factory));
[email protected]f9ee6b52008-11-08 06:46:232451
[email protected]1c773ea12009-04-28 19:58:422452 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:232453 request.method = "GET";
2454 request.url = GURL("http://www.google.com/p/q/t");
2455 request.load_flags = 0;
2456
2457 MockWrite data_writes1[] = {
2458 MockWrite("GET /p/q/t HTTP/1.1\r\n"
2459 "Host: www.google.com\r\n"
2460 "Connection: keep-alive\r\n\r\n"),
2461 };
2462
2463 MockRead data_reads1[] = {
2464 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
2465 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2466 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422467 MockRead(false, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:232468 };
2469
2470 // Resend with authorization from cache for MyRealm.
2471 MockWrite data_writes2[] = {
2472 MockWrite("GET /p/q/t HTTP/1.1\r\n"
2473 "Host: www.google.com\r\n"
2474 "Connection: keep-alive\r\n"
2475 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2476 };
2477
2478 // Sever rejects the authorization.
2479 MockRead data_reads2[] = {
2480 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
2481 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2482 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422483 MockRead(false, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:232484 };
2485
2486 // At this point we should prompt for new credentials for MyRealm.
2487 // Restart with username=foo3, password=foo4.
2488 MockWrite data_writes3[] = {
2489 MockWrite("GET /p/q/t HTTP/1.1\r\n"
2490 "Host: www.google.com\r\n"
2491 "Connection: keep-alive\r\n"
2492 "Authorization: Basic Zm9vMzpiYXIz\r\n\r\n"),
2493 };
2494
2495 // Sever accepts the authorization.
2496 MockRead data_reads3[] = {
2497 MockRead("HTTP/1.0 200 OK\r\n"),
2498 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422499 MockRead(false, OK),
[email protected]f9ee6b52008-11-08 06:46:232500 };
2501
[email protected]69b43fe2009-06-15 09:47:372502 StaticMockSocket data1(data_reads1, data_writes1);
2503 StaticMockSocket data2(data_reads2, data_writes2);
2504 StaticMockSocket data3(data_reads3, data_writes3);
[email protected]228ff742009-06-05 01:19:592505 session_deps.socket_factory.AddMockSocket(&data1);
2506 session_deps.socket_factory.AddMockSocket(&data2);
2507 session_deps.socket_factory.AddMockSocket(&data3);
[email protected]f9ee6b52008-11-08 06:46:232508
2509 TestCompletionCallback callback1;
2510
[email protected]684970b2009-08-14 04:54:462511 int rv = trans->Start(&request, &callback1, NULL);
[email protected]1c773ea12009-04-28 19:58:422512 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:232513
2514 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422515 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:232516
[email protected]0757e7702009-03-27 04:00:222517 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
2518 TestCompletionCallback callback2;
2519 rv = trans->RestartWithAuth(std::wstring(), std::wstring(), &callback2);
[email protected]1c773ea12009-04-28 19:58:422520 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]0757e7702009-03-27 04:00:222521 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422522 EXPECT_EQ(OK, rv);
[email protected]0757e7702009-03-27 04:00:222523 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
2524
[email protected]1c773ea12009-04-28 19:58:422525 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]f9ee6b52008-11-08 06:46:232526 EXPECT_FALSE(response == NULL);
2527
2528 // The password prompt info should have been set in
2529 // response->auth_challenge.
2530 EXPECT_FALSE(response->auth_challenge.get() == NULL);
2531
[email protected]71e4573a2009-05-21 22:03:002532 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
[email protected]f9ee6b52008-11-08 06:46:232533 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
2534 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
2535
[email protected]0757e7702009-03-27 04:00:222536 TestCompletionCallback callback3;
[email protected]f9ee6b52008-11-08 06:46:232537
[email protected]0757e7702009-03-27 04:00:222538 rv = trans->RestartWithAuth(L"foo3", L"bar3", &callback3);
[email protected]1c773ea12009-04-28 19:58:422539 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:232540
[email protected]0757e7702009-03-27 04:00:222541 rv = callback3.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422542 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:232543
2544 response = trans->GetResponseInfo();
2545 EXPECT_FALSE(response == NULL);
2546 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2547 EXPECT_EQ(100, response->headers->GetContentLength());
2548 }
2549}
[email protected]89ceba9a2009-03-21 03:46:062550
2551// Test the ResetStateForRestart() private method.
2552TEST_F(HttpNetworkTransactionTest, ResetStateForRestart) {
2553 // Create a transaction (the dependencies aren't important).
[email protected]228ff742009-06-05 01:19:592554 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:402555 scoped_ptr<HttpNetworkTransaction> trans(
2556 new HttpNetworkTransaction(
[email protected]228ff742009-06-05 01:19:592557 CreateSession(&session_deps),
2558 &session_deps.socket_factory));
[email protected]89ceba9a2009-03-21 03:46:062559
2560 // Setup some state (which we expect ResetStateForRestart() will clear).
[email protected]ffeb0882009-04-30 21:51:252561 trans->header_buf_->Realloc(10);
[email protected]89ceba9a2009-03-21 03:46:062562 trans->header_buf_capacity_ = 10;
2563 trans->header_buf_len_ = 3;
2564 trans->header_buf_body_offset_ = 11;
2565 trans->header_buf_http_offset_ = 0;
2566 trans->response_body_length_ = 100;
2567 trans->response_body_read_ = 1;
2568 trans->read_buf_ = new IOBuffer(15);
2569 trans->read_buf_len_ = 15;
[email protected]ffeb0882009-04-30 21:51:252570 trans->request_headers_->headers_ = "Authorization: NTLM";
[email protected]89ceba9a2009-03-21 03:46:062571 trans->request_headers_bytes_sent_ = 3;
2572
2573 // Setup state in response_
2574 trans->response_.auth_challenge = new AuthChallengeInfo();
2575 trans->response_.ssl_info.cert_status = -15;
2576 trans->response_.response_time = base::Time::Now();
[email protected]b4404c02009-04-10 16:38:522577 trans->response_.was_cached = true; // (Wouldn't ever actually be true...)
[email protected]89ceba9a2009-03-21 03:46:062578
2579 { // Setup state for response_.vary_data
2580 HttpRequestInfo request;
2581 std::string temp("HTTP/1.1 200 OK\nVary: foo, bar\n\n");
2582 std::replace(temp.begin(), temp.end(), '\n', '\0');
2583 scoped_refptr<HttpResponseHeaders> response = new HttpResponseHeaders(temp);
2584 request.extra_headers = "Foo: 1\nbar: 23";
2585 EXPECT_TRUE(trans->response_.vary_data.Init(request, *response));
2586 }
2587
2588 // Cause the above state to be reset.
2589 trans->ResetStateForRestart();
2590
2591 // Verify that the state that needed to be reset, has been reset.
[email protected]ffeb0882009-04-30 21:51:252592 EXPECT_EQ(NULL, trans->header_buf_->headers());
[email protected]89ceba9a2009-03-21 03:46:062593 EXPECT_EQ(0, trans->header_buf_capacity_);
2594 EXPECT_EQ(0, trans->header_buf_len_);
2595 EXPECT_EQ(-1, trans->header_buf_body_offset_);
2596 EXPECT_EQ(-1, trans->header_buf_http_offset_);
2597 EXPECT_EQ(-1, trans->response_body_length_);
2598 EXPECT_EQ(0, trans->response_body_read_);
2599 EXPECT_EQ(NULL, trans->read_buf_.get());
2600 EXPECT_EQ(0, trans->read_buf_len_);
[email protected]ffeb0882009-04-30 21:51:252601 EXPECT_EQ("", trans->request_headers_->headers_);
[email protected]89ceba9a2009-03-21 03:46:062602 EXPECT_EQ(0U, trans->request_headers_bytes_sent_);
2603 EXPECT_EQ(NULL, trans->response_.auth_challenge.get());
2604 EXPECT_EQ(NULL, trans->response_.headers.get());
2605 EXPECT_EQ(false, trans->response_.was_cached);
[email protected]89ceba9a2009-03-21 03:46:062606 EXPECT_EQ(0, trans->response_.ssl_info.cert_status);
2607 EXPECT_FALSE(trans->response_.vary_data.is_valid());
2608}
2609
[email protected]bacff652009-03-31 17:50:332610// Test HTTPS connections to a site with a bad certificate
2611TEST_F(HttpNetworkTransactionTest, HTTPSBadCertificate) {
[email protected]228ff742009-06-05 01:19:592612 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:402613 scoped_ptr<HttpTransaction> trans(
2614 new HttpNetworkTransaction(
[email protected]228ff742009-06-05 01:19:592615 CreateSession(&session_deps),
2616 &session_deps.socket_factory));
[email protected]bacff652009-03-31 17:50:332617
2618 HttpRequestInfo request;
2619 request.method = "GET";
2620 request.url = GURL("https://www.google.com/");
2621 request.load_flags = 0;
2622
2623 MockWrite data_writes[] = {
2624 MockWrite("GET / HTTP/1.1\r\n"
2625 "Host: www.google.com\r\n"
2626 "Connection: keep-alive\r\n\r\n"),
2627 };
2628
2629 MockRead data_reads[] = {
2630 MockRead("HTTP/1.0 200 OK\r\n"),
2631 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2632 MockRead("Content-Length: 100\r\n\r\n"),
2633 MockRead(false, OK),
2634 };
2635
[email protected]69b43fe2009-06-15 09:47:372636 StaticMockSocket ssl_bad_certificate;
2637 StaticMockSocket data(data_reads, data_writes);
[email protected]bacff652009-03-31 17:50:332638 MockSSLSocket ssl_bad(true, ERR_CERT_AUTHORITY_INVALID);
2639 MockSSLSocket ssl(true, OK);
2640
[email protected]228ff742009-06-05 01:19:592641 session_deps.socket_factory.AddMockSocket(&ssl_bad_certificate);
2642 session_deps.socket_factory.AddMockSocket(&data);
2643 session_deps.socket_factory.AddMockSSLSocket(&ssl_bad);
2644 session_deps.socket_factory.AddMockSSLSocket(&ssl);
[email protected]bacff652009-03-31 17:50:332645
2646 TestCompletionCallback callback;
2647
[email protected]684970b2009-08-14 04:54:462648 int rv = trans->Start(&request, &callback, NULL);
[email protected]bacff652009-03-31 17:50:332649 EXPECT_EQ(ERR_IO_PENDING, rv);
2650
2651 rv = callback.WaitForResult();
2652 EXPECT_EQ(ERR_CERT_AUTHORITY_INVALID, rv);
2653
2654 rv = trans->RestartIgnoringLastError(&callback);
2655 EXPECT_EQ(ERR_IO_PENDING, rv);
2656
2657 rv = callback.WaitForResult();
2658 EXPECT_EQ(OK, rv);
2659
2660 const HttpResponseInfo* response = trans->GetResponseInfo();
2661
2662 EXPECT_FALSE(response == NULL);
2663 EXPECT_EQ(100, response->headers->GetContentLength());
2664}
2665
2666// Test HTTPS connections to a site with a bad certificate, going through a
2667// proxy
2668TEST_F(HttpNetworkTransactionTest, HTTPSBadCertificateViaProxy) {
[email protected]228ff742009-06-05 01:19:592669 SessionDependencies session_deps(CreateFixedProxyService("myproxy:70"));
[email protected]bacff652009-03-31 17:50:332670
2671 HttpRequestInfo request;
2672 request.method = "GET";
2673 request.url = GURL("https://www.google.com/");
2674 request.load_flags = 0;
2675
2676 MockWrite proxy_writes[] = {
2677 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
[email protected]e44de5d2009-06-05 20:12:452678 "Host: www.google.com\r\n"
2679 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]bacff652009-03-31 17:50:332680 };
2681
2682 MockRead proxy_reads[] = {
2683 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422684 MockRead(false, OK)
[email protected]bacff652009-03-31 17:50:332685 };
2686
2687 MockWrite data_writes[] = {
2688 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
[email protected]e44de5d2009-06-05 20:12:452689 "Host: www.google.com\r\n"
2690 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]bacff652009-03-31 17:50:332691 MockWrite("GET / HTTP/1.1\r\n"
2692 "Host: www.google.com\r\n"
2693 "Connection: keep-alive\r\n\r\n"),
2694 };
2695
2696 MockRead data_reads[] = {
2697 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
2698 MockRead("HTTP/1.0 200 OK\r\n"),
2699 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2700 MockRead("Content-Length: 100\r\n\r\n"),
2701 MockRead(false, OK),
2702 };
2703
[email protected]69b43fe2009-06-15 09:47:372704 StaticMockSocket ssl_bad_certificate(proxy_reads, proxy_writes);
2705 StaticMockSocket data(data_reads, data_writes);
[email protected]bacff652009-03-31 17:50:332706 MockSSLSocket ssl_bad(true, ERR_CERT_AUTHORITY_INVALID);
2707 MockSSLSocket ssl(true, OK);
2708
[email protected]228ff742009-06-05 01:19:592709 session_deps.socket_factory.AddMockSocket(&ssl_bad_certificate);
2710 session_deps.socket_factory.AddMockSocket(&data);
2711 session_deps.socket_factory.AddMockSSLSocket(&ssl_bad);
2712 session_deps.socket_factory.AddMockSSLSocket(&ssl);
[email protected]bacff652009-03-31 17:50:332713
2714 TestCompletionCallback callback;
2715
2716 for (int i = 0; i < 2; i++) {
[email protected]228ff742009-06-05 01:19:592717 session_deps.socket_factory.ResetNextMockIndexes();
[email protected]bacff652009-03-31 17:50:332718
[email protected]d207a5f2009-06-04 05:28:402719 scoped_ptr<HttpTransaction> trans(
2720 new HttpNetworkTransaction(
[email protected]228ff742009-06-05 01:19:592721 CreateSession(&session_deps),
2722 &session_deps.socket_factory));
[email protected]bacff652009-03-31 17:50:332723
[email protected]684970b2009-08-14 04:54:462724 int rv = trans->Start(&request, &callback, NULL);
[email protected]bacff652009-03-31 17:50:332725 EXPECT_EQ(ERR_IO_PENDING, rv);
2726
2727 rv = callback.WaitForResult();
2728 EXPECT_EQ(ERR_CERT_AUTHORITY_INVALID, rv);
2729
2730 rv = trans->RestartIgnoringLastError(&callback);
2731 EXPECT_EQ(ERR_IO_PENDING, rv);
2732
2733 rv = callback.WaitForResult();
2734 EXPECT_EQ(OK, rv);
2735
2736 const HttpResponseInfo* response = trans->GetResponseInfo();
2737
2738 EXPECT_FALSE(response == NULL);
2739 EXPECT_EQ(100, response->headers->GetContentLength());
2740 }
2741}
2742
[email protected]1c773ea12009-04-28 19:58:422743TEST_F(HttpNetworkTransactionTest, BuildRequest_UserAgent) {
[email protected]228ff742009-06-05 01:19:592744 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:402745 scoped_ptr<HttpTransaction> trans(
2746 new HttpNetworkTransaction(
[email protected]228ff742009-06-05 01:19:592747 CreateSession(&session_deps),
2748 &session_deps.socket_factory));
[email protected]1c773ea12009-04-28 19:58:422749
2750 HttpRequestInfo request;
2751 request.method = "GET";
2752 request.url = GURL("http://www.google.com/");
2753 request.user_agent = "Chromium Ultra Awesome X Edition";
2754
2755 MockWrite data_writes[] = {
2756 MockWrite("GET / HTTP/1.1\r\n"
2757 "Host: www.google.com\r\n"
2758 "Connection: keep-alive\r\n"
2759 "User-Agent: Chromium Ultra Awesome X Edition\r\n\r\n"),
2760 };
2761
2762 // Lastly, the server responds with the actual content.
2763 MockRead data_reads[] = {
2764 MockRead("HTTP/1.0 200 OK\r\n"),
2765 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2766 MockRead("Content-Length: 100\r\n\r\n"),
2767 MockRead(false, OK),
2768 };
2769
[email protected]69b43fe2009-06-15 09:47:372770 StaticMockSocket data(data_reads, data_writes);
[email protected]228ff742009-06-05 01:19:592771 session_deps.socket_factory.AddMockSocket(&data);
[email protected]1c773ea12009-04-28 19:58:422772
2773 TestCompletionCallback callback;
2774
[email protected]684970b2009-08-14 04:54:462775 int rv = trans->Start(&request, &callback, NULL);
[email protected]1c773ea12009-04-28 19:58:422776 EXPECT_EQ(ERR_IO_PENDING, rv);
2777
2778 rv = callback.WaitForResult();
2779 EXPECT_EQ(OK, rv);
2780}
2781
2782TEST_F(HttpNetworkTransactionTest, BuildRequest_Referer) {
[email protected]228ff742009-06-05 01:19:592783 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:402784 scoped_ptr<HttpTransaction> trans(
2785 new HttpNetworkTransaction(
[email protected]228ff742009-06-05 01:19:592786 CreateSession(&session_deps),
2787 &session_deps.socket_factory));
[email protected]1c773ea12009-04-28 19:58:422788
2789 HttpRequestInfo request;
2790 request.method = "GET";
2791 request.url = GURL("http://www.google.com/");
2792 request.load_flags = 0;
2793 request.referrer = GURL("http://the.previous.site.com/");
2794
2795 MockWrite data_writes[] = {
2796 MockWrite("GET / HTTP/1.1\r\n"
2797 "Host: www.google.com\r\n"
2798 "Connection: keep-alive\r\n"
2799 "Referer: http://the.previous.site.com/\r\n\r\n"),
2800 };
2801
2802 // Lastly, the server responds with the actual content.
2803 MockRead data_reads[] = {
2804 MockRead("HTTP/1.0 200 OK\r\n"),
2805 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2806 MockRead("Content-Length: 100\r\n\r\n"),
2807 MockRead(false, OK),
2808 };
2809
[email protected]69b43fe2009-06-15 09:47:372810 StaticMockSocket data(data_reads, data_writes);
[email protected]228ff742009-06-05 01:19:592811 session_deps.socket_factory.AddMockSocket(&data);
[email protected]1c773ea12009-04-28 19:58:422812
2813 TestCompletionCallback callback;
2814
[email protected]684970b2009-08-14 04:54:462815 int rv = trans->Start(&request, &callback, NULL);
[email protected]1c773ea12009-04-28 19:58:422816 EXPECT_EQ(ERR_IO_PENDING, rv);
2817
2818 rv = callback.WaitForResult();
2819 EXPECT_EQ(OK, rv);
2820}
2821
2822TEST_F(HttpNetworkTransactionTest, BuildRequest_PostContentLengthZero) {
[email protected]228ff742009-06-05 01:19:592823 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:402824 scoped_ptr<HttpTransaction> trans(
2825 new HttpNetworkTransaction(
[email protected]228ff742009-06-05 01:19:592826 CreateSession(&session_deps),
2827 &session_deps.socket_factory));
[email protected]1c773ea12009-04-28 19:58:422828
2829 HttpRequestInfo request;
2830 request.method = "POST";
2831 request.url = GURL("http://www.google.com/");
2832
2833 MockWrite data_writes[] = {
2834 MockWrite("POST / HTTP/1.1\r\n"
2835 "Host: www.google.com\r\n"
2836 "Connection: keep-alive\r\n"
2837 "Content-Length: 0\r\n\r\n"),
2838 };
2839
2840 // Lastly, the server responds with the actual content.
2841 MockRead data_reads[] = {
2842 MockRead("HTTP/1.0 200 OK\r\n"),
2843 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2844 MockRead("Content-Length: 100\r\n\r\n"),
2845 MockRead(false, OK),
2846 };
2847
[email protected]69b43fe2009-06-15 09:47:372848 StaticMockSocket data(data_reads, data_writes);
[email protected]228ff742009-06-05 01:19:592849 session_deps.socket_factory.AddMockSocket(&data);
[email protected]1c773ea12009-04-28 19:58:422850
2851 TestCompletionCallback callback;
2852
[email protected]684970b2009-08-14 04:54:462853 int rv = trans->Start(&request, &callback, NULL);
[email protected]1c773ea12009-04-28 19:58:422854 EXPECT_EQ(ERR_IO_PENDING, rv);
2855
2856 rv = callback.WaitForResult();
2857 EXPECT_EQ(OK, rv);
2858}
2859
2860TEST_F(HttpNetworkTransactionTest, BuildRequest_PutContentLengthZero) {
[email protected]228ff742009-06-05 01:19:592861 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:402862 scoped_ptr<HttpTransaction> trans(
2863 new HttpNetworkTransaction(
[email protected]228ff742009-06-05 01:19:592864 CreateSession(&session_deps),
2865 &session_deps.socket_factory));
[email protected]1c773ea12009-04-28 19:58:422866
2867 HttpRequestInfo request;
2868 request.method = "PUT";
2869 request.url = GURL("http://www.google.com/");
2870
2871 MockWrite data_writes[] = {
2872 MockWrite("PUT / HTTP/1.1\r\n"
2873 "Host: www.google.com\r\n"
2874 "Connection: keep-alive\r\n"
2875 "Content-Length: 0\r\n\r\n"),
2876 };
2877
2878 // Lastly, the server responds with the actual content.
2879 MockRead data_reads[] = {
2880 MockRead("HTTP/1.0 200 OK\r\n"),
2881 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2882 MockRead("Content-Length: 100\r\n\r\n"),
2883 MockRead(false, OK),
2884 };
2885
[email protected]69b43fe2009-06-15 09:47:372886 StaticMockSocket data(data_reads, data_writes);
[email protected]228ff742009-06-05 01:19:592887 session_deps.socket_factory.AddMockSocket(&data);
[email protected]1c773ea12009-04-28 19:58:422888
2889 TestCompletionCallback callback;
2890
[email protected]684970b2009-08-14 04:54:462891 int rv = trans->Start(&request, &callback, NULL);
[email protected]1c773ea12009-04-28 19:58:422892 EXPECT_EQ(ERR_IO_PENDING, rv);
2893
2894 rv = callback.WaitForResult();
2895 EXPECT_EQ(OK, rv);
2896}
2897
2898TEST_F(HttpNetworkTransactionTest, BuildRequest_HeadContentLengthZero) {
[email protected]228ff742009-06-05 01:19:592899 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:402900 scoped_ptr<HttpTransaction> trans(
2901 new HttpNetworkTransaction(
[email protected]228ff742009-06-05 01:19:592902 CreateSession(&session_deps),
2903 &session_deps.socket_factory));
[email protected]1c773ea12009-04-28 19:58:422904
2905 HttpRequestInfo request;
2906 request.method = "HEAD";
2907 request.url = GURL("http://www.google.com/");
2908
2909 MockWrite data_writes[] = {
2910 MockWrite("HEAD / HTTP/1.1\r\n"
2911 "Host: www.google.com\r\n"
2912 "Connection: keep-alive\r\n"
2913 "Content-Length: 0\r\n\r\n"),
2914 };
2915
2916 // Lastly, the server responds with the actual content.
2917 MockRead data_reads[] = {
2918 MockRead("HTTP/1.0 200 OK\r\n"),
2919 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2920 MockRead("Content-Length: 100\r\n\r\n"),
2921 MockRead(false, OK),
2922 };
2923
[email protected]69b43fe2009-06-15 09:47:372924 StaticMockSocket data(data_reads, data_writes);
[email protected]228ff742009-06-05 01:19:592925 session_deps.socket_factory.AddMockSocket(&data);
[email protected]1c773ea12009-04-28 19:58:422926
2927 TestCompletionCallback callback;
2928
[email protected]684970b2009-08-14 04:54:462929 int rv = trans->Start(&request, &callback, NULL);
[email protected]1c773ea12009-04-28 19:58:422930 EXPECT_EQ(ERR_IO_PENDING, rv);
2931
2932 rv = callback.WaitForResult();
2933 EXPECT_EQ(OK, rv);
2934}
2935
2936TEST_F(HttpNetworkTransactionTest, BuildRequest_CacheControlNoCache) {
[email protected]228ff742009-06-05 01:19:592937 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:402938 scoped_ptr<HttpTransaction> trans(
2939 new HttpNetworkTransaction(
[email protected]228ff742009-06-05 01:19:592940 CreateSession(&session_deps),
2941 &session_deps.socket_factory));
[email protected]1c773ea12009-04-28 19:58:422942
2943 HttpRequestInfo request;
2944 request.method = "GET";
2945 request.url = GURL("http://www.google.com/");
2946 request.load_flags = LOAD_BYPASS_CACHE;
2947
2948 MockWrite data_writes[] = {
2949 MockWrite("GET / HTTP/1.1\r\n"
2950 "Host: www.google.com\r\n"
2951 "Connection: keep-alive\r\n"
2952 "Pragma: no-cache\r\n"
2953 "Cache-Control: no-cache\r\n\r\n"),
2954 };
2955
2956 // Lastly, the server responds with the actual content.
2957 MockRead data_reads[] = {
2958 MockRead("HTTP/1.0 200 OK\r\n"),
2959 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2960 MockRead("Content-Length: 100\r\n\r\n"),
2961 MockRead(false, OK),
2962 };
2963
[email protected]69b43fe2009-06-15 09:47:372964 StaticMockSocket data(data_reads, data_writes);
[email protected]228ff742009-06-05 01:19:592965 session_deps.socket_factory.AddMockSocket(&data);
[email protected]1c773ea12009-04-28 19:58:422966
2967 TestCompletionCallback callback;
2968
[email protected]684970b2009-08-14 04:54:462969 int rv = trans->Start(&request, &callback, NULL);
[email protected]1c773ea12009-04-28 19:58:422970 EXPECT_EQ(ERR_IO_PENDING, rv);
2971
2972 rv = callback.WaitForResult();
2973 EXPECT_EQ(OK, rv);
2974}
2975
2976TEST_F(HttpNetworkTransactionTest,
2977 BuildRequest_CacheControlValidateCache) {
[email protected]228ff742009-06-05 01:19:592978 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:402979 scoped_ptr<HttpTransaction> trans(
2980 new HttpNetworkTransaction(
[email protected]228ff742009-06-05 01:19:592981 CreateSession(&session_deps),
2982 &session_deps.socket_factory));
[email protected]1c773ea12009-04-28 19:58:422983
2984 HttpRequestInfo request;
2985 request.method = "GET";
2986 request.url = GURL("http://www.google.com/");
2987 request.load_flags = LOAD_VALIDATE_CACHE;
2988
2989 MockWrite data_writes[] = {
2990 MockWrite("GET / HTTP/1.1\r\n"
2991 "Host: www.google.com\r\n"
2992 "Connection: keep-alive\r\n"
2993 "Cache-Control: max-age=0\r\n\r\n"),
2994 };
2995
2996 // Lastly, the server responds with the actual content.
2997 MockRead data_reads[] = {
2998 MockRead("HTTP/1.0 200 OK\r\n"),
2999 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3000 MockRead("Content-Length: 100\r\n\r\n"),
3001 MockRead(false, OK),
3002 };
3003
[email protected]69b43fe2009-06-15 09:47:373004 StaticMockSocket data(data_reads, data_writes);
[email protected]228ff742009-06-05 01:19:593005 session_deps.socket_factory.AddMockSocket(&data);
[email protected]1c773ea12009-04-28 19:58:423006
3007 TestCompletionCallback callback;
3008
[email protected]684970b2009-08-14 04:54:463009 int rv = trans->Start(&request, &callback, NULL);
[email protected]1c773ea12009-04-28 19:58:423010 EXPECT_EQ(ERR_IO_PENDING, rv);
3011
3012 rv = callback.WaitForResult();
3013 EXPECT_EQ(OK, rv);
3014}
3015
3016TEST_F(HttpNetworkTransactionTest, BuildRequest_ExtraHeaders) {
[email protected]228ff742009-06-05 01:19:593017 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:403018 scoped_ptr<HttpTransaction> trans(
3019 new HttpNetworkTransaction(
[email protected]228ff742009-06-05 01:19:593020 CreateSession(&session_deps),
3021 &session_deps.socket_factory));
[email protected]1c773ea12009-04-28 19:58:423022
3023 HttpRequestInfo request;
3024 request.method = "GET";
3025 request.url = GURL("http://www.google.com/");
3026 request.extra_headers = "FooHeader: Bar\r\n";
3027
3028 MockWrite data_writes[] = {
3029 MockWrite("GET / HTTP/1.1\r\n"
3030 "Host: www.google.com\r\n"
3031 "Connection: keep-alive\r\n"
3032 "FooHeader: Bar\r\n\r\n"),
3033 };
3034
3035 // Lastly, the server responds with the actual content.
3036 MockRead data_reads[] = {
3037 MockRead("HTTP/1.0 200 OK\r\n"),
3038 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3039 MockRead("Content-Length: 100\r\n\r\n"),
3040 MockRead(false, OK),
3041 };
3042
[email protected]69b43fe2009-06-15 09:47:373043 StaticMockSocket data(data_reads, data_writes);
[email protected]228ff742009-06-05 01:19:593044 session_deps.socket_factory.AddMockSocket(&data);
[email protected]1c773ea12009-04-28 19:58:423045
3046 TestCompletionCallback callback;
3047
[email protected]684970b2009-08-14 04:54:463048 int rv = trans->Start(&request, &callback, NULL);
[email protected]1c773ea12009-04-28 19:58:423049 EXPECT_EQ(ERR_IO_PENDING, rv);
3050
3051 rv = callback.WaitForResult();
3052 EXPECT_EQ(OK, rv);
3053}
3054
[email protected]3cd17242009-06-23 02:59:023055TEST_F(HttpNetworkTransactionTest, SOCKS4_HTTP_GET) {
[email protected]80d6524d2009-08-18 03:58:093056 SessionDependencies session_deps(
3057 CreateFixedProxyService("socks4://myproxy:1080"));
[email protected]3cd17242009-06-23 02:59:023058
3059 scoped_ptr<HttpTransaction> trans(
3060 new HttpNetworkTransaction(
3061 CreateSession(&session_deps),
3062 &session_deps.socket_factory));
3063
3064 HttpRequestInfo request;
3065 request.method = "GET";
3066 request.url = GURL("http://www.google.com/");
3067 request.load_flags = 0;
3068
3069 char write_buffer[] = { 0x04, 0x01, 0x00, 0x50, 127, 0, 0, 1, 0 };
3070 char read_buffer[] = { 0x00, 0x5A, 0x00, 0x00, 0, 0, 0, 0 };
3071
3072 MockWrite data_writes[] = {
[email protected]e0c27be2009-07-15 13:09:353073 MockWrite(true, write_buffer, arraysize(write_buffer)),
[email protected]3cd17242009-06-23 02:59:023074 MockWrite("GET / HTTP/1.1\r\n"
3075 "Host: www.google.com\r\n"
3076 "Connection: keep-alive\r\n\r\n")
3077 };
3078
3079 MockRead data_reads[] = {
[email protected]e0c27be2009-07-15 13:09:353080 MockWrite(true, read_buffer, arraysize(read_buffer)),
[email protected]3cd17242009-06-23 02:59:023081 MockRead("HTTP/1.0 200 OK\r\n"),
3082 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
3083 MockRead("Payload"),
3084 MockRead(false, OK)
3085 };
3086
3087 StaticMockSocket data(data_reads, data_writes);
3088 session_deps.socket_factory.AddMockSocket(&data);
3089
3090 TestCompletionCallback callback;
3091
[email protected]684970b2009-08-14 04:54:463092 int rv = trans->Start(&request, &callback, NULL);
[email protected]3cd17242009-06-23 02:59:023093 EXPECT_EQ(ERR_IO_PENDING, rv);
3094
3095 rv = callback.WaitForResult();
3096 EXPECT_EQ(OK, rv);
3097
3098 const HttpResponseInfo* response = trans->GetResponseInfo();
3099 EXPECT_FALSE(response == NULL);
3100
3101 std::string response_text;
3102 rv = ReadTransaction(trans.get(), &response_text);
3103 EXPECT_EQ(OK, rv);
3104 EXPECT_EQ("Payload", response_text);
3105}
3106
3107TEST_F(HttpNetworkTransactionTest, SOCKS4_SSL_GET) {
[email protected]80d6524d2009-08-18 03:58:093108 SessionDependencies session_deps(
3109 CreateFixedProxyService("socks4://myproxy:1080"));
[email protected]3cd17242009-06-23 02:59:023110
3111 scoped_ptr<HttpTransaction> trans(
3112 new HttpNetworkTransaction(
3113 CreateSession(&session_deps),
3114 &session_deps.socket_factory));
3115
3116 HttpRequestInfo request;
3117 request.method = "GET";
3118 request.url = GURL("https://www.google.com/");
3119 request.load_flags = 0;
3120
3121 unsigned char write_buffer[] = { 0x04, 0x01, 0x01, 0xBB, 127, 0, 0, 1, 0 };
3122 unsigned char read_buffer[] = { 0x00, 0x5A, 0x00, 0x00, 0, 0, 0, 0 };
3123
3124 MockWrite data_writes[] = {
[email protected]e0c27be2009-07-15 13:09:353125 MockWrite(true, reinterpret_cast<char*>(write_buffer),
3126 arraysize(write_buffer)),
[email protected]3cd17242009-06-23 02:59:023127 MockWrite("GET / HTTP/1.1\r\n"
3128 "Host: www.google.com\r\n"
3129 "Connection: keep-alive\r\n\r\n")
3130 };
3131
3132 MockRead data_reads[] = {
[email protected]e0c27be2009-07-15 13:09:353133 MockWrite(true, reinterpret_cast<char*>(read_buffer),
3134 arraysize(read_buffer)),
3135 MockRead("HTTP/1.0 200 OK\r\n"),
3136 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
3137 MockRead("Payload"),
3138 MockRead(false, OK)
3139 };
3140
3141 StaticMockSocket data(data_reads, data_writes);
3142 session_deps.socket_factory.AddMockSocket(&data);
3143
3144 MockSSLSocket ssl(true, OK);
3145 session_deps.socket_factory.AddMockSSLSocket(&ssl);
3146
3147 TestCompletionCallback callback;
3148
[email protected]684970b2009-08-14 04:54:463149 int rv = trans->Start(&request, &callback, NULL);
[email protected]e0c27be2009-07-15 13:09:353150 EXPECT_EQ(ERR_IO_PENDING, rv);
3151
3152 rv = callback.WaitForResult();
3153 EXPECT_EQ(OK, rv);
3154
3155 const HttpResponseInfo* response = trans->GetResponseInfo();
3156 EXPECT_FALSE(response == NULL);
3157
3158 std::string response_text;
3159 rv = ReadTransaction(trans.get(), &response_text);
3160 EXPECT_EQ(OK, rv);
3161 EXPECT_EQ("Payload", response_text);
3162}
3163
3164TEST_F(HttpNetworkTransactionTest, SOCKS5_HTTP_GET) {
[email protected]80d6524d2009-08-18 03:58:093165 SessionDependencies session_deps(
3166 CreateFixedProxyService("socks5://myproxy:1080"));
[email protected]e0c27be2009-07-15 13:09:353167
3168 scoped_ptr<HttpTransaction> trans(
3169 new HttpNetworkTransaction(
3170 CreateSession(&session_deps),
3171 &session_deps.socket_factory));
3172
3173 HttpRequestInfo request;
3174 request.method = "GET";
3175 request.url = GURL("http://www.google.com/");
3176 request.load_flags = 0;
3177
3178 const char kSOCKS5GreetRequest[] = { 0x05, 0x01, 0x00 };
3179 const char kSOCKS5GreetResponse[] = { 0x05, 0x00 };
3180 const char kSOCKS5OkRequest[] =
3181 { 0x05, 0x01, 0x00, 0x01, 127, 0, 0, 1, 0x00, 0x50 };
3182 const char kSOCKS5OkResponse[] =
3183 { 0x05, 0x00, 0x00, 0x01, 127, 0, 0, 1, 0x00, 0x50 };
3184
3185 MockWrite data_writes[] = {
3186 MockWrite(true, kSOCKS5GreetRequest, arraysize(kSOCKS5GreetRequest)),
3187 MockWrite(true, kSOCKS5OkRequest, arraysize(kSOCKS5OkRequest)),
3188 MockWrite("GET / HTTP/1.1\r\n"
3189 "Host: www.google.com\r\n"
3190 "Connection: keep-alive\r\n\r\n")
3191 };
3192
3193 MockRead data_reads[] = {
3194 MockWrite(true, kSOCKS5GreetResponse, arraysize(kSOCKS5GreetResponse)),
3195 MockWrite(true, kSOCKS5OkResponse, arraysize(kSOCKS5OkResponse)),
3196 MockRead("HTTP/1.0 200 OK\r\n"),
3197 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
3198 MockRead("Payload"),
3199 MockRead(false, OK)
3200 };
3201
3202 StaticMockSocket data(data_reads, data_writes);
3203 session_deps.socket_factory.AddMockSocket(&data);
3204
3205 TestCompletionCallback callback;
3206
[email protected]684970b2009-08-14 04:54:463207 int rv = trans->Start(&request, &callback, NULL);
[email protected]e0c27be2009-07-15 13:09:353208 EXPECT_EQ(ERR_IO_PENDING, rv);
3209
3210 rv = callback.WaitForResult();
3211 EXPECT_EQ(OK, rv);
3212
3213 const HttpResponseInfo* response = trans->GetResponseInfo();
3214 EXPECT_FALSE(response == NULL);
3215
3216 std::string response_text;
3217 rv = ReadTransaction(trans.get(), &response_text);
3218 EXPECT_EQ(OK, rv);
3219 EXPECT_EQ("Payload", response_text);
3220}
3221
3222TEST_F(HttpNetworkTransactionTest, SOCKS5_SSL_GET) {
[email protected]80d6524d2009-08-18 03:58:093223 SessionDependencies session_deps(
3224 CreateFixedProxyService("socks5://myproxy:1080"));
[email protected]e0c27be2009-07-15 13:09:353225
3226 scoped_ptr<HttpTransaction> trans(
3227 new HttpNetworkTransaction(
3228 CreateSession(&session_deps),
3229 &session_deps.socket_factory));
3230
3231 HttpRequestInfo request;
3232 request.method = "GET";
3233 request.url = GURL("https://www.google.com/");
3234 request.load_flags = 0;
3235
3236 const char kSOCKS5GreetRequest[] = { 0x05, 0x01, 0x00 };
3237 const char kSOCKS5GreetResponse[] = { 0x05, 0x00 };
3238 const unsigned char kSOCKS5OkRequest[] =
3239 { 0x05, 0x01, 0x00, 0x01, 127, 0, 0, 1, 0x01, 0xBB };
3240 const char kSOCKS5OkResponse[] =
3241 { 0x05, 0x00, 0x00, 0x01, 0, 0, 0, 0, 0x00, 0x00 };
3242
3243 MockWrite data_writes[] = {
3244 MockWrite(true, kSOCKS5GreetRequest, arraysize(kSOCKS5GreetRequest)),
3245 MockWrite(true, reinterpret_cast<const char*>(kSOCKS5OkRequest),
3246 arraysize(kSOCKS5OkRequest)),
3247 MockWrite("GET / HTTP/1.1\r\n"
3248 "Host: www.google.com\r\n"
3249 "Connection: keep-alive\r\n\r\n")
3250 };
3251
3252 MockRead data_reads[] = {
3253 MockWrite(true, kSOCKS5GreetResponse, arraysize(kSOCKS5GreetResponse)),
3254 MockWrite(true, kSOCKS5OkResponse, arraysize(kSOCKS5OkResponse)),
[email protected]3cd17242009-06-23 02:59:023255 MockRead("HTTP/1.0 200 OK\r\n"),
3256 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
3257 MockRead("Payload"),
3258 MockRead(false, OK)
3259 };
3260
3261 StaticMockSocket data(data_reads, data_writes);
3262 session_deps.socket_factory.AddMockSocket(&data);
3263
3264 MockSSLSocket ssl(true, OK);
3265 session_deps.socket_factory.AddMockSSLSocket(&ssl);
3266
3267 TestCompletionCallback callback;
3268
[email protected]684970b2009-08-14 04:54:463269 int rv = trans->Start(&request, &callback, NULL);
[email protected]3cd17242009-06-23 02:59:023270 EXPECT_EQ(ERR_IO_PENDING, rv);
3271
3272 rv = callback.WaitForResult();
3273 EXPECT_EQ(OK, rv);
3274
3275 const HttpResponseInfo* response = trans->GetResponseInfo();
3276 EXPECT_FALSE(response == NULL);
3277
3278 std::string response_text;
3279 rv = ReadTransaction(trans.get(), &response_text);
3280 EXPECT_EQ(OK, rv);
3281 EXPECT_EQ("Payload", response_text);
3282}
3283
[email protected]04e5be32009-06-26 20:00:313284// Tests that for connection endpoints the group names are correctly set.
3285TEST_F(HttpNetworkTransactionTest, GroupNameForProxyConnections) {
3286 const struct {
3287 const std::string proxy_server;
3288 const std::string url;
3289 const std::string expected_group_name;
3290 } tests[] = {
3291 {
3292 "", // no proxy (direct)
3293 "http://www.google.com/direct",
3294 "http://www.google.com/",
3295 },
3296 {
3297 "http_proxy",
3298 "http://www.google.com/http_proxy_normal",
3299 "proxy/http_proxy:80/",
3300 },
3301 {
3302 "socks4://socks_proxy:1080",
3303 "http://www.google.com/socks4_direct",
3304 "proxy/socks4://socks_proxy:1080/http://www.google.com/",
3305 },
3306
3307 // SSL Tests
3308 {
3309 "",
3310 "https://www.google.com/direct_ssl",
3311 "https://www.google.com/",
3312 },
3313 {
3314 "http_proxy",
3315 "https://www.google.com/http_connect_ssl",
3316 "proxy/http_proxy:80/https://www.google.com/",
3317 },
3318 {
3319 "socks4://socks_proxy:1080",
3320 "https://www.google.com/socks4_ssl",
3321 "proxy/socks4://socks_proxy:1080/https://www.google.com/",
3322 },
3323 };
3324
3325 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) {
[email protected]80d6524d2009-08-18 03:58:093326 SessionDependencies session_deps(
3327 CreateFixedProxyService(tests[i].proxy_server));
[email protected]04e5be32009-06-26 20:00:313328
3329 scoped_refptr<CaptureGroupNameSocketPool> conn_pool(
3330 new CaptureGroupNameSocketPool());
3331
3332 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
3333 session->connection_pool_ = conn_pool.get();
3334
3335 scoped_ptr<HttpTransaction> trans(
3336 new HttpNetworkTransaction(
3337 session.get(),
3338 &session_deps.socket_factory));
3339
3340 HttpRequestInfo request;
3341 request.method = "GET";
3342 request.url = GURL(tests[i].url);
3343 request.load_flags = 0;
3344
3345 TestCompletionCallback callback;
3346
3347 // We do not complete this request, the dtor will clean the transaction up.
[email protected]684970b2009-08-14 04:54:463348 EXPECT_EQ(ERR_IO_PENDING, trans->Start(&request, &callback, NULL));
[email protected]04e5be32009-06-26 20:00:313349 EXPECT_EQ(tests[i].expected_group_name,
3350 conn_pool->last_group_name_received());
3351 }
3352}
3353
[email protected]9172a982009-06-06 00:30:253354TEST_F(HttpNetworkTransactionTest, ReconsiderProxyAfterFailedConnection) {
[email protected]5c6a17e2009-06-10 00:54:543355 SessionDependencies session_deps(
3356 CreateFixedProxyService("myproxy:70;foobar:80"));
[email protected]b59ff372009-07-15 22:04:323357
3358 session_deps.host_resolver->rules()->AddSimulatedFailure("*");
3359
[email protected]9172a982009-06-06 00:30:253360 scoped_ptr<HttpTransaction> trans(
3361 new HttpNetworkTransaction(
3362 CreateSession(&session_deps),
3363 &session_deps.socket_factory));
3364
3365 HttpRequestInfo request;
3366 request.method = "GET";
3367 request.url = GURL("http://www.google.com/");
3368
3369 TestCompletionCallback callback;
3370
[email protected]684970b2009-08-14 04:54:463371 int rv = trans->Start(&request, &callback, NULL);
[email protected]9172a982009-06-06 00:30:253372 EXPECT_EQ(ERR_IO_PENDING, rv);
3373
[email protected]9172a982009-06-06 00:30:253374 rv = callback.WaitForResult();
3375 EXPECT_EQ(ERR_NAME_NOT_RESOLVED, rv);
3376}
3377
[email protected]f3e6c1e2009-06-15 20:52:123378// Host resolution observer used by
3379// HttpNetworkTransactionTest.ResolveMadeWithReferrer to check that host
3380// resovle requests are issued with a referrer of |expected_referrer|.
3381class ResolutionReferrerObserver : public HostResolver::Observer {
3382 public:
3383 explicit ResolutionReferrerObserver(const GURL& expected_referrer)
3384 : expected_referrer_(expected_referrer),
3385 called_start_with_referrer_(false),
3386 called_finish_with_referrer_(false) {
3387 }
3388
3389 virtual void OnStartResolution(int id,
3390 const HostResolver::RequestInfo& info) {
3391 if (info.referrer() == expected_referrer_)
3392 called_start_with_referrer_ = true;
3393 }
3394
3395 virtual void OnFinishResolutionWithStatus(
3396 int id, bool was_resolved, const HostResolver::RequestInfo& info ) {
3397 if (info.referrer() == expected_referrer_)
3398 called_finish_with_referrer_ = true;
3399 }
3400
[email protected]eb255d32009-06-17 02:11:033401 virtual void OnCancelResolution(int id,
3402 const HostResolver::RequestInfo& info ) {
3403 FAIL() << "Should not be cancelling any requests!";
3404 }
3405
[email protected]f3e6c1e2009-06-15 20:52:123406 bool did_complete_with_expected_referrer() const {
3407 return called_start_with_referrer_ && called_finish_with_referrer_;
3408 }
3409
3410 private:
3411 GURL expected_referrer_;
3412 bool called_start_with_referrer_;
3413 bool called_finish_with_referrer_;
3414
3415 DISALLOW_COPY_AND_ASSIGN(ResolutionReferrerObserver);
3416};
3417
3418// Make sure that when HostResolver::Resolve() is invoked, it passes through
3419// the "referrer". This is depended on by the DNS prefetch observer.
3420TEST_F(HttpNetworkTransactionTest, ResolveMadeWithReferrer) {
3421 GURL referrer = GURL("http://expected-referrer/");
3422 EXPECT_TRUE(referrer.is_valid());
3423 ResolutionReferrerObserver resolution_observer(referrer);
3424
3425 SessionDependencies session_deps;
3426 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(
3427 CreateSession(&session_deps), &session_deps.socket_factory));
3428
3429 // Attach an observer to watch the host resolutions being made.
[email protected]94a0d3d92009-06-27 01:50:143430 session_deps.host_resolver->AddObserver(&resolution_observer);
[email protected]f3e6c1e2009-06-15 20:52:123431
3432 // Connect up a mock socket which will fail when reading.
3433 MockRead data_reads[] = {
3434 MockRead(false, ERR_FAILED),
3435 };
3436 StaticMockSocket data(data_reads, NULL);
3437 session_deps.socket_factory.AddMockSocket(&data);
3438
3439 // Issue a request, containing an HTTP referrer.
3440 HttpRequestInfo request;
3441 request.method = "GET";
3442 request.referrer = referrer;
3443 request.url = GURL("http://www.google.com/");
3444
3445 // Run the request until it fails reading from the socket.
3446 TestCompletionCallback callback;
[email protected]684970b2009-08-14 04:54:463447 int rv = trans->Start(&request, &callback, NULL);
[email protected]f3e6c1e2009-06-15 20:52:123448 EXPECT_EQ(ERR_IO_PENDING, rv);
3449 rv = callback.WaitForResult();
3450 EXPECT_EQ(ERR_FAILED, rv);
3451
3452 // Check that the host resolution observer saw |referrer|.
3453 EXPECT_TRUE(resolution_observer.did_complete_with_expected_referrer());
3454}
3455
[email protected]3b9cca42009-06-16 01:08:283456// Make sure that when the load flags contain LOAD_BYPASS_CACHE, the resolver's
3457// host cache is bypassed.
3458TEST_F(HttpNetworkTransactionTest, BypassHostCacheOnRefresh) {
3459 SessionDependencies session_deps;
[email protected]b59ff372009-07-15 22:04:323460
[email protected]a2c2fb92009-07-18 07:31:043461 // Select a host resolver that does caching.
3462 session_deps.host_resolver = new MockCachingHostResolver;
[email protected]b59ff372009-07-15 22:04:323463
[email protected]3b9cca42009-06-16 01:08:283464 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(
3465 CreateSession(&session_deps), &session_deps.socket_factory));
3466
3467 // Warm up the host cache so it has an entry for "www.google.com" (by doing
3468 // a synchronous lookup.)
3469 AddressList addrlist;
[email protected]94a0d3d92009-06-27 01:50:143470 int rv = session_deps.host_resolver->Resolve(
[email protected]684970b2009-08-14 04:54:463471 HostResolver::RequestInfo("www.google.com", 80), &addrlist,
3472 NULL, NULL, NULL);
[email protected]3b9cca42009-06-16 01:08:283473 EXPECT_EQ(OK, rv);
3474
3475 // Verify that it was added to host cache, by doing a subsequent async lookup
3476 // and confirming it completes synchronously.
3477 TestCompletionCallback resolve_callback;
[email protected]684970b2009-08-14 04:54:463478 rv = session_deps.host_resolver->Resolve(
[email protected]3b9cca42009-06-16 01:08:283479 HostResolver::RequestInfo("www.google.com", 80), &addrlist,
[email protected]684970b2009-08-14 04:54:463480 &resolve_callback, NULL, NULL);
[email protected]b59ff372009-07-15 22:04:323481 ASSERT_EQ(OK, rv);
[email protected]3b9cca42009-06-16 01:08:283482
3483 // Inject a failure the next time that "www.google.com" is resolved. This way
3484 // we can tell if the next lookup hit the cache, or the "network".
3485 // (cache --> success, "network" --> failure).
[email protected]b59ff372009-07-15 22:04:323486 session_deps.host_resolver->rules()->AddSimulatedFailure("www.google.com");
[email protected]3b9cca42009-06-16 01:08:283487
3488 // Connect up a mock socket which will fail with ERR_UNEXPECTED during the
3489 // first read -- this won't be reached as the host resolution will fail first.
3490 MockRead data_reads[] = { MockRead(false, ERR_UNEXPECTED) };
3491 StaticMockSocket data(data_reads, NULL);
3492 session_deps.socket_factory.AddMockSocket(&data);
3493
3494 // Issue a request, asking to bypass the cache(s).
3495 HttpRequestInfo request;
3496 request.method = "GET";
3497 request.load_flags = LOAD_BYPASS_CACHE;
3498 request.url = GURL("http://www.google.com/");
3499
3500 // Run the request.
3501 TestCompletionCallback callback;
[email protected]684970b2009-08-14 04:54:463502 rv = trans->Start(&request, &callback, NULL);
[email protected]3b9cca42009-06-16 01:08:283503 ASSERT_EQ(ERR_IO_PENDING, rv);
3504 rv = callback.WaitForResult();
3505
3506 // If we bypassed the cache, we would have gotten a failure while resolving
3507 // "www.google.com".
3508 EXPECT_EQ(ERR_NAME_NOT_RESOLVED, rv);
3509}
3510
[email protected]a97cca42009-08-14 01:00:293511TEST_F(HttpNetworkTransactionTest, GetIdentifyFromUrl) {
3512 struct {
3513 const char* input_url;
3514 const wchar_t* expected_username;
3515 const wchar_t* expected_password;
3516 } tests[] = {
3517 {
3518 "http://username:[email protected]",
3519 L"username",
3520 L"password",
3521 },
3522 { // Test for http://crbug.com/19200
3523 "http://username:p@[email protected]",
3524 L"username",
3525 L"p@ssword",
3526 },
3527 { // Username contains %20.
3528 "http://use rname:[email protected]",
3529 L"use rname",
3530 L"password",
3531 },
3532 { // The URL canonicalizer for userinfo does not recognize non-ascii
3533 // escapes it seems... So things like %00 will NOT be unescapable,
3534 // since they are canonicalized by escaping the %...
3535 "http://use%00rname:[email protected]",
3536 L"use%2500rname",
3537 L"password",
3538 },
3539 { // Use a '+' in the username.
3540 "http://use+rname:[email protected]",
3541 L"use+rname",
3542 L"password",
3543 },
3544 { // Use a '&' in the password.
3545 "http://username:p&[email protected]",
3546 L"username",
3547 L"p&ssword",
3548 },
3549 };
3550 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) {
3551 SCOPED_TRACE(StringPrintf("Test[%d]: %s", i, tests[i].input_url));
3552 GURL url(tests[i].input_url);
3553
3554 std::wstring username, password;
3555 HttpNetworkTransaction::GetIdentifyFromUrl(url, &username, &password);
3556
3557 EXPECT_EQ(tests[i].expected_username, username);
3558 EXPECT_EQ(tests[i].expected_password, password);
3559 }
3560}
3561
3562// Try extracting a username which was encoded with UTF8.
3563TEST_F(HttpNetworkTransactionTest, GetIdentifyFromUrl_UTF8) {
3564 GURL url(WideToUTF16(L"http://foo:\x4f60\[email protected]"));
3565
3566 EXPECT_EQ("foo", url.username());
3567 EXPECT_EQ("%E4%BD%A0%E5%A5%BD", url.password());
3568
3569 // Extract the unescaped identity.
3570 std::wstring username, password;
3571 HttpNetworkTransaction::GetIdentifyFromUrl(url, &username, &password);
3572
3573 // Verify that it was decoded as UTF8.
3574 EXPECT_EQ(L"foo", username);
3575 EXPECT_EQ(L"\x4f60\x597d", password);
3576}
3577
[email protected]89ceba9a2009-03-21 03:46:063578} // namespace net