blob: 164450edd415d380d5e29bf4de7f903b41d86ede [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]a937a06d2009-08-19 21:19:24168class CaptureGroupNameSocketPool : public TCPClientSocketPool {
[email protected]04e5be32009-06-26 20:00:31169 public:
[email protected]a937a06d2009-08-19 21:19:24170 CaptureGroupNameSocketPool() : TCPClientSocketPool(0, 0, NULL, NULL) {}
[email protected]d80a4322009-08-14 07:07:49171 const std::string last_group_name_received() const {
172 return last_group_name_;
173 }
174
[email protected]684970b2009-08-14 04:54:46175 virtual int RequestSocket(const std::string& group_name,
[email protected]d80a4322009-08-14 07:07:49176 const void* socket_params,
[email protected]04e5be32009-06-26 20:00:31177 int priority,
178 ClientSocketHandle* handle,
[email protected]684970b2009-08-14 04:54:46179 CompletionCallback* callback,
180 LoadLog* load_log) {
[email protected]04e5be32009-06-26 20:00:31181 last_group_name_ = group_name;
182 return ERR_IO_PENDING;
183 }
[email protected]04e5be32009-06-26 20:00:31184 virtual void CancelRequest(const std::string& group_name,
185 const ClientSocketHandle* handle) { }
186 virtual void ReleaseSocket(const std::string& group_name,
187 ClientSocket* socket) {}
188 virtual void CloseIdleSockets() {}
189 virtual HostResolver* GetHostResolver() const {
190 return NULL;
191 }
192 virtual int IdleSocketCount() const {
193 return 0;
194 }
195 virtual int IdleSocketCountInGroup(const std::string& group_name) const {
196 return 0;
197 }
198 virtual LoadState GetLoadState(const std::string& group_name,
199 const ClientSocketHandle* handle) const {
200 return LOAD_STATE_IDLE;
201 }
[email protected]d80a4322009-08-14 07:07:49202
203 private:
[email protected]04e5be32009-06-26 20:00:31204 std::string last_group_name_;
205};
206
[email protected]231d5a32008-09-13 00:45:27207//-----------------------------------------------------------------------------
208
209TEST_F(HttpNetworkTransactionTest, Basic) {
[email protected]228ff742009-06-05 01:19:59210 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:40211 scoped_ptr<HttpTransaction> trans(
212 new HttpNetworkTransaction(
[email protected]228ff742009-06-05 01:19:59213 CreateSession(&session_deps),
214 &session_deps.socket_factory));
[email protected]231d5a32008-09-13 00:45:27215}
216
217TEST_F(HttpNetworkTransactionTest, SimpleGET) {
218 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35219 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
220 MockRead("hello world"),
[email protected]1c773ea12009-04-28 19:58:42221 MockRead(false, OK),
[email protected]231d5a32008-09-13 00:45:27222 };
[email protected]231d5a32008-09-13 00:45:27223 SimpleGetHelperResult out = SimpleGetHelper(data_reads);
[email protected]1c773ea12009-04-28 19:58:42224 EXPECT_EQ(OK, out.rv);
[email protected]231d5a32008-09-13 00:45:27225 EXPECT_EQ("HTTP/1.0 200 OK", out.status_line);
226 EXPECT_EQ("hello world", out.response_data);
227}
228
229// Response with no status line.
230TEST_F(HttpNetworkTransactionTest, SimpleGETNoHeaders) {
231 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35232 MockRead("hello world"),
[email protected]1c773ea12009-04-28 19:58:42233 MockRead(false, OK),
[email protected]231d5a32008-09-13 00:45:27234 };
[email protected]231d5a32008-09-13 00:45:27235 SimpleGetHelperResult out = SimpleGetHelper(data_reads);
[email protected]1c773ea12009-04-28 19:58:42236 EXPECT_EQ(OK, out.rv);
[email protected]231d5a32008-09-13 00:45:27237 EXPECT_EQ("HTTP/0.9 200 OK", out.status_line);
238 EXPECT_EQ("hello world", out.response_data);
239}
240
241// Allow up to 4 bytes of junk to precede status line.
242TEST_F(HttpNetworkTransactionTest, StatusLineJunk2Bytes) {
243 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35244 MockRead("xxxHTTP/1.0 404 Not Found\nServer: blah\n\nDATA"),
[email protected]1c773ea12009-04-28 19:58:42245 MockRead(false, OK),
[email protected]231d5a32008-09-13 00:45:27246 };
247 SimpleGetHelperResult out = SimpleGetHelper(data_reads);
[email protected]1c773ea12009-04-28 19:58:42248 EXPECT_EQ(OK, out.rv);
[email protected]231d5a32008-09-13 00:45:27249 EXPECT_EQ("HTTP/1.0 404 Not Found", out.status_line);
250 EXPECT_EQ("DATA", out.response_data);
251}
252
253// Allow up to 4 bytes of junk to precede status line.
254TEST_F(HttpNetworkTransactionTest, StatusLineJunk4Bytes) {
255 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35256 MockRead("\n\nQJHTTP/1.0 404 Not Found\nServer: blah\n\nDATA"),
[email protected]1c773ea12009-04-28 19:58:42257 MockRead(false, OK),
[email protected]231d5a32008-09-13 00:45:27258 };
259 SimpleGetHelperResult out = SimpleGetHelper(data_reads);
[email protected]1c773ea12009-04-28 19:58:42260 EXPECT_EQ(OK, out.rv);
[email protected]231d5a32008-09-13 00:45:27261 EXPECT_EQ("HTTP/1.0 404 Not Found", out.status_line);
262 EXPECT_EQ("DATA", out.response_data);
263}
264
265// Beyond 4 bytes of slop and it should fail to find a status line.
266TEST_F(HttpNetworkTransactionTest, StatusLineJunk5Bytes) {
267 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35268 MockRead("xxxxxHTTP/1.1 404 Not Found\nServer: blah"),
[email protected]1c773ea12009-04-28 19:58:42269 MockRead(false, OK),
[email protected]231d5a32008-09-13 00:45:27270 };
271 SimpleGetHelperResult out = SimpleGetHelper(data_reads);
[email protected]1c773ea12009-04-28 19:58:42272 EXPECT_EQ(OK, out.rv);
[email protected]3d2a59b2008-09-26 19:44:25273 EXPECT_EQ("HTTP/0.9 200 OK", out.status_line);
274 EXPECT_EQ("xxxxxHTTP/1.1 404 Not Found\nServer: blah", out.response_data);
[email protected]231d5a32008-09-13 00:45:27275}
276
277// Same as StatusLineJunk4Bytes, except the read chunks are smaller.
278TEST_F(HttpNetworkTransactionTest, StatusLineJunk4Bytes_Slow) {
279 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35280 MockRead("\n"),
281 MockRead("\n"),
282 MockRead("Q"),
283 MockRead("J"),
284 MockRead("HTTP/1.0 404 Not Found\nServer: blah\n\nDATA"),
[email protected]1c773ea12009-04-28 19:58:42285 MockRead(false, OK),
[email protected]231d5a32008-09-13 00:45:27286 };
287 SimpleGetHelperResult out = SimpleGetHelper(data_reads);
[email protected]1c773ea12009-04-28 19:58:42288 EXPECT_EQ(OK, out.rv);
[email protected]231d5a32008-09-13 00:45:27289 EXPECT_EQ("HTTP/1.0 404 Not Found", out.status_line);
290 EXPECT_EQ("DATA", out.response_data);
291}
292
293// Close the connection before enough bytes to have a status line.
294TEST_F(HttpNetworkTransactionTest, StatusLinePartial) {
295 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35296 MockRead("HTT"),
[email protected]1c773ea12009-04-28 19:58:42297 MockRead(false, OK),
[email protected]231d5a32008-09-13 00:45:27298 };
299 SimpleGetHelperResult out = SimpleGetHelper(data_reads);
[email protected]1c773ea12009-04-28 19:58:42300 EXPECT_EQ(OK, out.rv);
[email protected]231d5a32008-09-13 00:45:27301 EXPECT_EQ("HTTP/0.9 200 OK", out.status_line);
302 EXPECT_EQ("HTT", out.response_data);
initial.commit586acc5fe2008-07-26 22:42:52303}
304
[email protected]f9d44aa2008-09-23 23:57:17305// Simulate a 204 response, lacking a Content-Length header, sent over a
306// persistent connection. The response should still terminate since a 204
307// cannot have a response body.
308TEST_F(HttpNetworkTransactionTest, StopsReading204) {
309 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35310 MockRead("HTTP/1.1 204 No Content\r\n\r\n"),
311 MockRead("junk"), // Should not be read!!
[email protected]1c773ea12009-04-28 19:58:42312 MockRead(false, OK),
[email protected]f9d44aa2008-09-23 23:57:17313 };
314 SimpleGetHelperResult out = SimpleGetHelper(data_reads);
[email protected]1c773ea12009-04-28 19:58:42315 EXPECT_EQ(OK, out.rv);
[email protected]f9d44aa2008-09-23 23:57:17316 EXPECT_EQ("HTTP/1.1 204 No Content", out.status_line);
317 EXPECT_EQ("", out.response_data);
318}
319
[email protected]ef0faf2e72009-03-05 23:27:23320// Do a request using the HEAD method. Verify that we don't try to read the
321// message body (since HEAD has none).
322TEST_F(HttpNetworkTransactionTest, Head) {
[email protected]228ff742009-06-05 01:19:59323 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:40324 scoped_ptr<HttpTransaction> trans(
325 new HttpNetworkTransaction(
[email protected]228ff742009-06-05 01:19:59326 CreateSession(&session_deps),
327 &session_deps.socket_factory));
[email protected]ef0faf2e72009-03-05 23:27:23328
[email protected]1c773ea12009-04-28 19:58:42329 HttpRequestInfo request;
[email protected]ef0faf2e72009-03-05 23:27:23330 request.method = "HEAD";
331 request.url = GURL("http://www.google.com/");
332 request.load_flags = 0;
333
334 MockWrite data_writes1[] = {
335 MockWrite("HEAD / HTTP/1.1\r\n"
336 "Host: www.google.com\r\n"
337 "Connection: keep-alive\r\n"
338 "Content-Length: 0\r\n\r\n"),
339 };
340 MockRead data_reads1[] = {
341 MockRead("HTTP/1.1 404 Not Found\r\n"),
342 MockRead("Server: Blah\r\n"),
343 MockRead("Content-Length: 1234\r\n\r\n"),
344
345 // No response body because the test stops reading here.
[email protected]1c773ea12009-04-28 19:58:42346 MockRead(false, ERR_UNEXPECTED), // Should not be reached.
[email protected]ef0faf2e72009-03-05 23:27:23347 };
348
[email protected]69b43fe2009-06-15 09:47:37349 StaticMockSocket data1(data_reads1, data_writes1);
[email protected]228ff742009-06-05 01:19:59350 session_deps.socket_factory.AddMockSocket(&data1);
[email protected]ef0faf2e72009-03-05 23:27:23351
352 TestCompletionCallback callback1;
353
[email protected]684970b2009-08-14 04:54:46354 int rv = trans->Start(&request, &callback1, NULL);
[email protected]1c773ea12009-04-28 19:58:42355 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]ef0faf2e72009-03-05 23:27:23356
357 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42358 EXPECT_EQ(OK, rv);
[email protected]ef0faf2e72009-03-05 23:27:23359
[email protected]1c773ea12009-04-28 19:58:42360 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]ef0faf2e72009-03-05 23:27:23361 EXPECT_FALSE(response == NULL);
362
363 // Check that the headers got parsed.
364 EXPECT_TRUE(response->headers != NULL);
365 EXPECT_EQ(1234, response->headers->GetContentLength());
366 EXPECT_EQ("HTTP/1.1 404 Not Found", response->headers->GetStatusLine());
367
368 std::string server_header;
369 void* iter = NULL;
370 bool has_server_header = response->headers->EnumerateHeader(
371 &iter, "Server", &server_header);
372 EXPECT_TRUE(has_server_header);
373 EXPECT_EQ("Blah", server_header);
374
375 // Reading should give EOF right away, since there is no message body
376 // (despite non-zero content-length).
377 std::string response_data;
378 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:42379 EXPECT_EQ(OK, rv);
[email protected]ef0faf2e72009-03-05 23:27:23380 EXPECT_EQ("", response_data);
381}
382
initial.commit586acc5fe2008-07-26 22:42:52383TEST_F(HttpNetworkTransactionTest, ReuseConnection) {
[email protected]228ff742009-06-05 01:19:59384 SessionDependencies session_deps;
385 scoped_refptr<HttpNetworkSession> session = CreateSession(&session_deps);
initial.commit586acc5fe2008-07-26 22:42:52386
387 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35388 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
389 MockRead("hello"),
390 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
391 MockRead("world"),
[email protected]1c773ea12009-04-28 19:58:42392 MockRead(false, OK),
initial.commit586acc5fe2008-07-26 22:42:52393 };
[email protected]69b43fe2009-06-15 09:47:37394 StaticMockSocket data(data_reads, NULL);
[email protected]228ff742009-06-05 01:19:59395 session_deps.socket_factory.AddMockSocket(&data);
initial.commit586acc5fe2008-07-26 22:42:52396
397 const char* kExpectedResponseData[] = {
398 "hello", "world"
399 };
400
401 for (int i = 0; i < 2; ++i) {
[email protected]1c773ea12009-04-28 19:58:42402 scoped_ptr<HttpTransaction> trans(
[email protected]228ff742009-06-05 01:19:59403 new HttpNetworkTransaction(session, &session_deps.socket_factory));
initial.commit586acc5fe2008-07-26 22:42:52404
[email protected]1c773ea12009-04-28 19:58:42405 HttpRequestInfo request;
initial.commit586acc5fe2008-07-26 22:42:52406 request.method = "GET";
407 request.url = GURL("http://www.google.com/");
408 request.load_flags = 0;
409
410 TestCompletionCallback callback;
411
[email protected]684970b2009-08-14 04:54:46412 int rv = trans->Start(&request, &callback, NULL);
[email protected]1c773ea12009-04-28 19:58:42413 EXPECT_EQ(ERR_IO_PENDING, rv);
initial.commit586acc5fe2008-07-26 22:42:52414
415 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42416 EXPECT_EQ(OK, rv);
initial.commit586acc5fe2008-07-26 22:42:52417
[email protected]1c773ea12009-04-28 19:58:42418 const HttpResponseInfo* response = trans->GetResponseInfo();
initial.commit586acc5fe2008-07-26 22:42:52419 EXPECT_TRUE(response != NULL);
420
421 EXPECT_TRUE(response->headers != NULL);
[email protected]3d2a59b2008-09-26 19:44:25422 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
initial.commit586acc5fe2008-07-26 22:42:52423
424 std::string response_data;
[email protected]af4876d2008-10-21 23:10:57425 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:42426 EXPECT_EQ(OK, rv);
[email protected]3d2a59b2008-09-26 19:44:25427 EXPECT_EQ(kExpectedResponseData[i], response_data);
initial.commit586acc5fe2008-07-26 22:42:52428 }
429}
430
431TEST_F(HttpNetworkTransactionTest, Ignores100) {
[email protected]228ff742009-06-05 01:19:59432 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:40433 scoped_ptr<HttpTransaction> trans(
434 new HttpNetworkTransaction(
[email protected]228ff742009-06-05 01:19:59435 CreateSession(&session_deps),
436 &session_deps.socket_factory));
initial.commit586acc5fe2008-07-26 22:42:52437
[email protected]1c773ea12009-04-28 19:58:42438 HttpRequestInfo request;
initial.commit586acc5fe2008-07-26 22:42:52439 request.method = "POST";
440 request.url = GURL("http://www.foo.com/");
[email protected]1c773ea12009-04-28 19:58:42441 request.upload_data = new UploadData;
initial.commit586acc5fe2008-07-26 22:42:52442 request.upload_data->AppendBytes("foo", 3);
443 request.load_flags = 0;
444
445 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35446 MockRead("HTTP/1.0 100 Continue\r\n\r\n"),
447 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
448 MockRead("hello world"),
[email protected]1c773ea12009-04-28 19:58:42449 MockRead(false, OK),
initial.commit586acc5fe2008-07-26 22:42:52450 };
[email protected]69b43fe2009-06-15 09:47:37451 StaticMockSocket data(data_reads, NULL);
[email protected]228ff742009-06-05 01:19:59452 session_deps.socket_factory.AddMockSocket(&data);
initial.commit586acc5fe2008-07-26 22:42:52453
454 TestCompletionCallback callback;
455
[email protected]684970b2009-08-14 04:54:46456 int rv = trans->Start(&request, &callback, NULL);
[email protected]1c773ea12009-04-28 19:58:42457 EXPECT_EQ(ERR_IO_PENDING, rv);
initial.commit586acc5fe2008-07-26 22:42:52458
459 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42460 EXPECT_EQ(OK, rv);
initial.commit586acc5fe2008-07-26 22:42:52461
[email protected]1c773ea12009-04-28 19:58:42462 const HttpResponseInfo* response = trans->GetResponseInfo();
initial.commit586acc5fe2008-07-26 22:42:52463 EXPECT_TRUE(response != NULL);
464
465 EXPECT_TRUE(response->headers != NULL);
[email protected]3d2a59b2008-09-26 19:44:25466 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
initial.commit586acc5fe2008-07-26 22:42:52467
468 std::string response_data;
[email protected]af4876d2008-10-21 23:10:57469 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:42470 EXPECT_EQ(OK, rv);
[email protected]3d2a59b2008-09-26 19:44:25471 EXPECT_EQ("hello world", response_data);
initial.commit586acc5fe2008-07-26 22:42:52472}
473
[email protected]3a2d3662009-03-27 03:49:14474// This test is almost the same as Ignores100 above, but the response contains
475// a 102 instead of a 100. Also, instead of HTTP/1.0 the response is
476// HTTP/1.1.
477TEST_F(HttpNetworkTransactionTest, Ignores1xx) {
[email protected]228ff742009-06-05 01:19:59478 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:40479 scoped_ptr<HttpTransaction> trans(
480 new HttpNetworkTransaction(
[email protected]228ff742009-06-05 01:19:59481 CreateSession(&session_deps),
482 &session_deps.socket_factory));
[email protected]3a2d3662009-03-27 03:49:14483
[email protected]1c773ea12009-04-28 19:58:42484 HttpRequestInfo request;
[email protected]3a2d3662009-03-27 03:49:14485 request.method = "GET";
486 request.url = GURL("http://www.foo.com/");
487 request.load_flags = 0;
488
489 MockRead data_reads[] = {
490 MockRead("HTTP/1.1 102 Unspecified status code\r\n\r\n"),
491 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
492 MockRead("hello world"),
[email protected]1c773ea12009-04-28 19:58:42493 MockRead(false, OK),
[email protected]3a2d3662009-03-27 03:49:14494 };
[email protected]69b43fe2009-06-15 09:47:37495 StaticMockSocket data(data_reads, NULL);
[email protected]228ff742009-06-05 01:19:59496 session_deps.socket_factory.AddMockSocket(&data);
[email protected]3a2d3662009-03-27 03:49:14497
498 TestCompletionCallback callback;
499
[email protected]684970b2009-08-14 04:54:46500 int rv = trans->Start(&request, &callback, NULL);
[email protected]1c773ea12009-04-28 19:58:42501 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]3a2d3662009-03-27 03:49:14502
503 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42504 EXPECT_EQ(OK, rv);
[email protected]3a2d3662009-03-27 03:49:14505
[email protected]1c773ea12009-04-28 19:58:42506 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]3a2d3662009-03-27 03:49:14507 EXPECT_TRUE(response != NULL);
508
509 EXPECT_TRUE(response->headers != NULL);
510 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
511
512 std::string response_data;
513 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:42514 EXPECT_EQ(OK, rv);
[email protected]3a2d3662009-03-27 03:49:14515 EXPECT_EQ("hello world", response_data);
516}
517
[email protected]3d2a59b2008-09-26 19:44:25518// read_failure specifies a read failure that should cause the network
519// transaction to resend the request.
520void HttpNetworkTransactionTest::KeepAliveConnectionResendRequestTest(
521 const MockRead& read_failure) {
[email protected]228ff742009-06-05 01:19:59522 SessionDependencies session_deps;
523 scoped_refptr<HttpNetworkSession> session = CreateSession(&session_deps);
initial.commit586acc5fe2008-07-26 22:42:52524
[email protected]1c773ea12009-04-28 19:58:42525 HttpRequestInfo request;
initial.commit586acc5fe2008-07-26 22:42:52526 request.method = "GET";
527 request.url = GURL("http://www.foo.com/");
528 request.load_flags = 0;
529
530 MockRead data1_reads[] = {
[email protected]217e6022008-09-29 18:18:35531 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
532 MockRead("hello"),
[email protected]3d2a59b2008-09-26 19:44:25533 read_failure, // Now, we reuse the connection and fail the first read.
initial.commit586acc5fe2008-07-26 22:42:52534 };
[email protected]69b43fe2009-06-15 09:47:37535 StaticMockSocket data1(data1_reads, NULL);
[email protected]228ff742009-06-05 01:19:59536 session_deps.socket_factory.AddMockSocket(&data1);
initial.commit586acc5fe2008-07-26 22:42:52537
538 MockRead data2_reads[] = {
[email protected]217e6022008-09-29 18:18:35539 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
540 MockRead("world"),
[email protected]1c773ea12009-04-28 19:58:42541 MockRead(true, OK),
initial.commit586acc5fe2008-07-26 22:42:52542 };
[email protected]69b43fe2009-06-15 09:47:37543 StaticMockSocket data2(data2_reads, NULL);
[email protected]228ff742009-06-05 01:19:59544 session_deps.socket_factory.AddMockSocket(&data2);
initial.commit586acc5fe2008-07-26 22:42:52545
546 const char* kExpectedResponseData[] = {
547 "hello", "world"
548 };
549
550 for (int i = 0; i < 2; ++i) {
551 TestCompletionCallback callback;
552
[email protected]1c773ea12009-04-28 19:58:42553 scoped_ptr<HttpTransaction> trans(
[email protected]228ff742009-06-05 01:19:59554 new HttpNetworkTransaction(session, &session_deps.socket_factory));
initial.commit586acc5fe2008-07-26 22:42:52555
[email protected]684970b2009-08-14 04:54:46556 int rv = trans->Start(&request, &callback, NULL);
[email protected]1c773ea12009-04-28 19:58:42557 EXPECT_EQ(ERR_IO_PENDING, rv);
initial.commit586acc5fe2008-07-26 22:42:52558
559 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42560 EXPECT_EQ(OK, rv);
initial.commit586acc5fe2008-07-26 22:42:52561
[email protected]1c773ea12009-04-28 19:58:42562 const HttpResponseInfo* response = trans->GetResponseInfo();
initial.commit586acc5fe2008-07-26 22:42:52563 EXPECT_TRUE(response != NULL);
564
565 EXPECT_TRUE(response->headers != NULL);
[email protected]3d2a59b2008-09-26 19:44:25566 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
initial.commit586acc5fe2008-07-26 22:42:52567
568 std::string response_data;
[email protected]af4876d2008-10-21 23:10:57569 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:42570 EXPECT_EQ(OK, rv);
[email protected]3d2a59b2008-09-26 19:44:25571 EXPECT_EQ(kExpectedResponseData[i], response_data);
initial.commit586acc5fe2008-07-26 22:42:52572 }
573}
[email protected]3d2a59b2008-09-26 19:44:25574
575TEST_F(HttpNetworkTransactionTest, KeepAliveConnectionReset) {
[email protected]1c773ea12009-04-28 19:58:42576 MockRead read_failure(true, ERR_CONNECTION_RESET);
[email protected]3d2a59b2008-09-26 19:44:25577 KeepAliveConnectionResendRequestTest(read_failure);
578}
579
580TEST_F(HttpNetworkTransactionTest, KeepAliveConnectionEOF) {
[email protected]1c773ea12009-04-28 19:58:42581 MockRead read_failure(false, OK); // EOF
[email protected]3d2a59b2008-09-26 19:44:25582 KeepAliveConnectionResendRequestTest(read_failure);
583}
584
585TEST_F(HttpNetworkTransactionTest, NonKeepAliveConnectionReset) {
[email protected]228ff742009-06-05 01:19:59586 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:40587 scoped_ptr<HttpTransaction> trans(
588 new HttpNetworkTransaction(
[email protected]228ff742009-06-05 01:19:59589 CreateSession(&session_deps),
590 &session_deps.socket_factory));
[email protected]3d2a59b2008-09-26 19:44:25591
[email protected]1c773ea12009-04-28 19:58:42592 HttpRequestInfo request;
[email protected]3d2a59b2008-09-26 19:44:25593 request.method = "GET";
594 request.url = GURL("http://www.google.com/");
595 request.load_flags = 0;
596
597 MockRead data_reads[] = {
[email protected]1c773ea12009-04-28 19:58:42598 MockRead(true, ERR_CONNECTION_RESET),
[email protected]217e6022008-09-29 18:18:35599 MockRead("HTTP/1.0 200 OK\r\n\r\n"), // Should not be used
600 MockRead("hello world"),
[email protected]1c773ea12009-04-28 19:58:42601 MockRead(false, OK),
[email protected]3d2a59b2008-09-26 19:44:25602 };
[email protected]69b43fe2009-06-15 09:47:37603 StaticMockSocket data(data_reads, NULL);
[email protected]228ff742009-06-05 01:19:59604 session_deps.socket_factory.AddMockSocket(&data);
[email protected]3d2a59b2008-09-26 19:44:25605
606 TestCompletionCallback callback;
607
[email protected]684970b2009-08-14 04:54:46608 int rv = trans->Start(&request, &callback, NULL);
[email protected]1c773ea12009-04-28 19:58:42609 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]3d2a59b2008-09-26 19:44:25610
611 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42612 EXPECT_EQ(ERR_CONNECTION_RESET, rv);
[email protected]3d2a59b2008-09-26 19:44:25613
[email protected]1c773ea12009-04-28 19:58:42614 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]3d2a59b2008-09-26 19:44:25615 EXPECT_TRUE(response == NULL);
[email protected]3d2a59b2008-09-26 19:44:25616}
617
618// What do various browsers do when the server closes a non-keepalive
619// connection without sending any response header or body?
620//
621// IE7: error page
622// Safari 3.1.2 (Windows): error page
623// Firefox 3.0.1: blank page
624// Opera 9.52: after five attempts, blank page
[email protected]1c773ea12009-04-28 19:58:42625// Us with WinHTTP: error page (ERR_INVALID_RESPONSE)
626// Us: error page (EMPTY_RESPONSE)
[email protected]3d2a59b2008-09-26 19:44:25627TEST_F(HttpNetworkTransactionTest, NonKeepAliveConnectionEOF) {
628 MockRead data_reads[] = {
[email protected]1c773ea12009-04-28 19:58:42629 MockRead(false, OK), // EOF
[email protected]217e6022008-09-29 18:18:35630 MockRead("HTTP/1.0 200 OK\r\n\r\n"), // Should not be used
631 MockRead("hello world"),
[email protected]1c773ea12009-04-28 19:58:42632 MockRead(false, OK),
[email protected]3d2a59b2008-09-26 19:44:25633 };
634 SimpleGetHelperResult out = SimpleGetHelper(data_reads);
[email protected]1c773ea12009-04-28 19:58:42635 EXPECT_EQ(ERR_EMPTY_RESPONSE, out.rv);
[email protected]3d2a59b2008-09-26 19:44:25636}
[email protected]038e9a32008-10-08 22:40:16637
638// Test the request-challenge-retry sequence for basic auth.
639// (basic auth is the easiest to mock, because it has no randomness).
640TEST_F(HttpNetworkTransactionTest, BasicAuth) {
[email protected]228ff742009-06-05 01:19:59641 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:40642 scoped_ptr<HttpTransaction> trans(
643 new HttpNetworkTransaction(
[email protected]228ff742009-06-05 01:19:59644 CreateSession(&session_deps),
645 &session_deps.socket_factory));
[email protected]038e9a32008-10-08 22:40:16646
[email protected]1c773ea12009-04-28 19:58:42647 HttpRequestInfo request;
[email protected]038e9a32008-10-08 22:40:16648 request.method = "GET";
649 request.url = GURL("http://www.google.com/");
650 request.load_flags = 0;
651
[email protected]f9ee6b52008-11-08 06:46:23652 MockWrite data_writes1[] = {
653 MockWrite("GET / HTTP/1.1\r\n"
654 "Host: www.google.com\r\n"
655 "Connection: keep-alive\r\n\r\n"),
656 };
657
[email protected]038e9a32008-10-08 22:40:16658 MockRead data_reads1[] = {
659 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
660 // Give a couple authenticate options (only the middle one is actually
661 // supported).
[email protected]aaead502008-10-15 00:20:11662 MockRead("WWW-Authenticate: Basic\r\n"), // Malformed
[email protected]038e9a32008-10-08 22:40:16663 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
664 MockRead("WWW-Authenticate: UNSUPPORTED realm=\"FOO\"\r\n"),
665 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
666 // Large content-length -- won't matter, as connection will be reset.
667 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:42668 MockRead(false, ERR_FAILED),
[email protected]038e9a32008-10-08 22:40:16669 };
670
671 // After calling trans->RestartWithAuth(), this is the request we should
672 // be issuing -- the final header line contains the credentials.
673 MockWrite data_writes2[] = {
674 MockWrite("GET / HTTP/1.1\r\n"
675 "Host: www.google.com\r\n"
676 "Connection: keep-alive\r\n"
677 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
678 };
679
680 // Lastly, the server responds with the actual content.
681 MockRead data_reads2[] = {
682 MockRead("HTTP/1.0 200 OK\r\n"),
683 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
684 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:42685 MockRead(false, OK),
[email protected]038e9a32008-10-08 22:40:16686 };
687
[email protected]69b43fe2009-06-15 09:47:37688 StaticMockSocket data1(data_reads1, data_writes1);
689 StaticMockSocket data2(data_reads2, data_writes2);
[email protected]228ff742009-06-05 01:19:59690 session_deps.socket_factory.AddMockSocket(&data1);
691 session_deps.socket_factory.AddMockSocket(&data2);
[email protected]038e9a32008-10-08 22:40:16692
693 TestCompletionCallback callback1;
694
[email protected]684970b2009-08-14 04:54:46695 int rv = trans->Start(&request, &callback1, NULL);
[email protected]1c773ea12009-04-28 19:58:42696 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]038e9a32008-10-08 22:40:16697
698 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42699 EXPECT_EQ(OK, rv);
[email protected]038e9a32008-10-08 22:40:16700
[email protected]1c773ea12009-04-28 19:58:42701 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]038e9a32008-10-08 22:40:16702 EXPECT_FALSE(response == NULL);
703
704 // The password prompt info should have been set in response->auth_challenge.
705 EXPECT_FALSE(response->auth_challenge.get() == NULL);
706
[email protected]71e4573a2009-05-21 22:03:00707 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
[email protected]038e9a32008-10-08 22:40:16708 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
709 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
710
711 TestCompletionCallback callback2;
712
713 rv = trans->RestartWithAuth(L"foo", L"bar", &callback2);
[email protected]1c773ea12009-04-28 19:58:42714 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]038e9a32008-10-08 22:40:16715
716 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42717 EXPECT_EQ(OK, rv);
[email protected]038e9a32008-10-08 22:40:16718
719 response = trans->GetResponseInfo();
720 EXPECT_FALSE(response == NULL);
721 EXPECT_TRUE(response->auth_challenge.get() == NULL);
722 EXPECT_EQ(100, response->headers->GetContentLength());
[email protected]038e9a32008-10-08 22:40:16723}
724
[email protected]2d2697f92009-02-18 21:00:32725// Test the request-challenge-retry sequence for basic auth, over a keep-alive
726// connection.
727TEST_F(HttpNetworkTransactionTest, BasicAuthKeepAlive) {
[email protected]228ff742009-06-05 01:19:59728 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:40729 scoped_ptr<HttpTransaction> trans(
730 new HttpNetworkTransaction(
[email protected]228ff742009-06-05 01:19:59731 CreateSession(&session_deps),
732 &session_deps.socket_factory));
[email protected]2d2697f92009-02-18 21:00:32733
[email protected]1c773ea12009-04-28 19:58:42734 HttpRequestInfo request;
[email protected]2d2697f92009-02-18 21:00:32735 request.method = "GET";
736 request.url = GURL("http://www.google.com/");
737 request.load_flags = 0;
738
739 MockWrite data_writes1[] = {
740 MockWrite("GET / HTTP/1.1\r\n"
741 "Host: www.google.com\r\n"
742 "Connection: keep-alive\r\n\r\n"),
743
744 // After calling trans->RestartWithAuth(), this is the request we should
745 // be issuing -- the final header line contains the credentials.
746 MockWrite("GET / HTTP/1.1\r\n"
747 "Host: www.google.com\r\n"
748 "Connection: keep-alive\r\n"
749 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
750 };
751
752 MockRead data_reads1[] = {
753 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
754 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
755 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
756 MockRead("Content-Length: 14\r\n\r\n"),
757 MockRead("Unauthorized\r\n"),
758
759 // Lastly, the server responds with the actual content.
760 MockRead("HTTP/1.1 200 OK\r\n"),
761 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
762 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:42763 MockRead(false, OK),
[email protected]2d2697f92009-02-18 21:00:32764 };
765
[email protected]69b43fe2009-06-15 09:47:37766 StaticMockSocket data1(data_reads1, data_writes1);
[email protected]228ff742009-06-05 01:19:59767 session_deps.socket_factory.AddMockSocket(&data1);
[email protected]2d2697f92009-02-18 21:00:32768
769 TestCompletionCallback callback1;
770
[email protected]684970b2009-08-14 04:54:46771 int rv = trans->Start(&request, &callback1, NULL);
[email protected]1c773ea12009-04-28 19:58:42772 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:32773
774 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42775 EXPECT_EQ(OK, rv);
[email protected]2d2697f92009-02-18 21:00:32776
[email protected]1c773ea12009-04-28 19:58:42777 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]2d2697f92009-02-18 21:00:32778 EXPECT_FALSE(response == NULL);
779
780 // The password prompt info should have been set in response->auth_challenge.
781 EXPECT_FALSE(response->auth_challenge.get() == NULL);
782
[email protected]71e4573a2009-05-21 22:03:00783 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
[email protected]2d2697f92009-02-18 21:00:32784 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
785 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
786
787 TestCompletionCallback callback2;
788
789 rv = trans->RestartWithAuth(L"foo", L"bar", &callback2);
[email protected]1c773ea12009-04-28 19:58:42790 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:32791
792 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42793 EXPECT_EQ(OK, rv);
[email protected]2d2697f92009-02-18 21:00:32794
795 response = trans->GetResponseInfo();
796 EXPECT_FALSE(response == NULL);
797 EXPECT_TRUE(response->auth_challenge.get() == NULL);
798 EXPECT_EQ(100, response->headers->GetContentLength());
799}
800
801// Test the request-challenge-retry sequence for basic auth, over a keep-alive
802// connection and with no response body to drain.
803TEST_F(HttpNetworkTransactionTest, BasicAuthKeepAliveNoBody) {
[email protected]228ff742009-06-05 01:19:59804 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:40805 scoped_ptr<HttpTransaction> trans(
806 new HttpNetworkTransaction(
[email protected]228ff742009-06-05 01:19:59807 CreateSession(&session_deps),
808 &session_deps.socket_factory));
[email protected]2d2697f92009-02-18 21:00:32809
[email protected]1c773ea12009-04-28 19:58:42810 HttpRequestInfo request;
[email protected]2d2697f92009-02-18 21:00:32811 request.method = "GET";
812 request.url = GURL("http://www.google.com/");
813 request.load_flags = 0;
814
815 MockWrite data_writes1[] = {
816 MockWrite("GET / HTTP/1.1\r\n"
817 "Host: www.google.com\r\n"
818 "Connection: keep-alive\r\n\r\n"),
819
820 // After calling trans->RestartWithAuth(), this is the request we should
821 // be issuing -- the final header line contains the credentials.
822 MockWrite("GET / HTTP/1.1\r\n"
823 "Host: www.google.com\r\n"
824 "Connection: keep-alive\r\n"
825 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
826 };
827
828 // Respond with 5 kb of response body.
829 std::string large_body_string("Unauthorized");
830 large_body_string.append(5 * 1024, ' ');
831 large_body_string.append("\r\n");
832
833 MockRead data_reads1[] = {
834 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
835 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
836 MockRead("Content-Length: 0\r\n\r\n"),
837
838 // Lastly, the server responds with the actual content.
839 MockRead("HTTP/1.1 200 OK\r\n"),
840 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
841 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:42842 MockRead(false, OK),
[email protected]2d2697f92009-02-18 21:00:32843 };
844
[email protected]69b43fe2009-06-15 09:47:37845 StaticMockSocket data1(data_reads1, data_writes1);
[email protected]228ff742009-06-05 01:19:59846 session_deps.socket_factory.AddMockSocket(&data1);
[email protected]2d2697f92009-02-18 21:00:32847
848 TestCompletionCallback callback1;
849
[email protected]684970b2009-08-14 04:54:46850 int rv = trans->Start(&request, &callback1, NULL);
[email protected]1c773ea12009-04-28 19:58:42851 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:32852
853 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42854 EXPECT_EQ(OK, rv);
[email protected]2d2697f92009-02-18 21:00:32855
[email protected]1c773ea12009-04-28 19:58:42856 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]2d2697f92009-02-18 21:00:32857 EXPECT_FALSE(response == NULL);
858
859 // The password prompt info should have been set in response->auth_challenge.
860 EXPECT_FALSE(response->auth_challenge.get() == NULL);
861
[email protected]71e4573a2009-05-21 22:03:00862 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
[email protected]2d2697f92009-02-18 21:00:32863 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
864 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
865
866 TestCompletionCallback callback2;
867
868 rv = trans->RestartWithAuth(L"foo", L"bar", &callback2);
[email protected]1c773ea12009-04-28 19:58:42869 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:32870
871 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42872 EXPECT_EQ(OK, rv);
[email protected]2d2697f92009-02-18 21:00:32873
874 response = trans->GetResponseInfo();
875 EXPECT_FALSE(response == NULL);
876 EXPECT_TRUE(response->auth_challenge.get() == NULL);
877 EXPECT_EQ(100, response->headers->GetContentLength());
878}
879
880// Test the request-challenge-retry sequence for basic auth, over a keep-alive
881// connection and with a large response body to drain.
882TEST_F(HttpNetworkTransactionTest, BasicAuthKeepAliveLargeBody) {
[email protected]228ff742009-06-05 01:19:59883 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:40884 scoped_ptr<HttpTransaction> trans(
885 new HttpNetworkTransaction(
[email protected]228ff742009-06-05 01:19:59886 CreateSession(&session_deps),
887 &session_deps.socket_factory));
[email protected]2d2697f92009-02-18 21:00:32888
[email protected]1c773ea12009-04-28 19:58:42889 HttpRequestInfo request;
[email protected]2d2697f92009-02-18 21:00:32890 request.method = "GET";
891 request.url = GURL("http://www.google.com/");
892 request.load_flags = 0;
893
894 MockWrite data_writes1[] = {
895 MockWrite("GET / HTTP/1.1\r\n"
896 "Host: www.google.com\r\n"
897 "Connection: keep-alive\r\n\r\n"),
898
899 // After calling trans->RestartWithAuth(), this is the request we should
900 // be issuing -- the final header line contains the credentials.
901 MockWrite("GET / HTTP/1.1\r\n"
902 "Host: www.google.com\r\n"
903 "Connection: keep-alive\r\n"
904 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
905 };
906
907 // Respond with 5 kb of response body.
908 std::string large_body_string("Unauthorized");
909 large_body_string.append(5 * 1024, ' ');
910 large_body_string.append("\r\n");
911
912 MockRead data_reads1[] = {
913 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
914 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
915 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
916 // 5134 = 12 + 5 * 1024 + 2
917 MockRead("Content-Length: 5134\r\n\r\n"),
918 MockRead(true, large_body_string.data(), large_body_string.size()),
919
920 // Lastly, the server responds with the actual content.
921 MockRead("HTTP/1.1 200 OK\r\n"),
922 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
923 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:42924 MockRead(false, OK),
[email protected]2d2697f92009-02-18 21:00:32925 };
926
[email protected]69b43fe2009-06-15 09:47:37927 StaticMockSocket data1(data_reads1, data_writes1);
[email protected]228ff742009-06-05 01:19:59928 session_deps.socket_factory.AddMockSocket(&data1);
[email protected]2d2697f92009-02-18 21:00:32929
930 TestCompletionCallback callback1;
931
[email protected]684970b2009-08-14 04:54:46932 int rv = trans->Start(&request, &callback1, NULL);
[email protected]1c773ea12009-04-28 19:58:42933 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:32934
935 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42936 EXPECT_EQ(OK, rv);
[email protected]2d2697f92009-02-18 21:00:32937
[email protected]1c773ea12009-04-28 19:58:42938 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]2d2697f92009-02-18 21:00:32939 EXPECT_FALSE(response == NULL);
940
941 // The password prompt info should have been set in response->auth_challenge.
942 EXPECT_FALSE(response->auth_challenge.get() == NULL);
943
[email protected]71e4573a2009-05-21 22:03:00944 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
[email protected]2d2697f92009-02-18 21:00:32945 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
946 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
947
948 TestCompletionCallback callback2;
949
950 rv = trans->RestartWithAuth(L"foo", L"bar", &callback2);
[email protected]1c773ea12009-04-28 19:58:42951 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:32952
953 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42954 EXPECT_EQ(OK, rv);
[email protected]2d2697f92009-02-18 21:00:32955
956 response = trans->GetResponseInfo();
957 EXPECT_FALSE(response == NULL);
958 EXPECT_TRUE(response->auth_challenge.get() == NULL);
959 EXPECT_EQ(100, response->headers->GetContentLength());
960}
961
962// Test the request-challenge-retry sequence for basic auth, over a keep-alive
963// proxy connection, when setting up an SSL tunnel.
964TEST_F(HttpNetworkTransactionTest, BasicAuthProxyKeepAlive) {
965 // Configure against proxy server "myproxy:70".
[email protected]228ff742009-06-05 01:19:59966 SessionDependencies session_deps(CreateFixedProxyService("myproxy:70"));
967 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]2d2697f92009-02-18 21:00:32968
[email protected]1c773ea12009-04-28 19:58:42969 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(
[email protected]228ff742009-06-05 01:19:59970 session.get(), &session_deps.socket_factory));
[email protected]2d2697f92009-02-18 21:00:32971
[email protected]1c773ea12009-04-28 19:58:42972 HttpRequestInfo request;
[email protected]2d2697f92009-02-18 21:00:32973 request.method = "GET";
974 request.url = GURL("https://www.google.com/");
975 request.load_flags = 0;
976
977 // Since we have proxy, should try to establish tunnel.
978 MockWrite data_writes1[] = {
979 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
[email protected]e44de5d2009-06-05 20:12:45980 "Host: www.google.com\r\n"
981 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]2d2697f92009-02-18 21:00:32982
983 // After calling trans->RestartWithAuth(), this is the request we should
984 // be issuing -- the final header line contains the credentials.
985 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
986 "Host: www.google.com\r\n"
[email protected]e44de5d2009-06-05 20:12:45987 "Proxy-Connection: keep-alive\r\n"
[email protected]2d2697f92009-02-18 21:00:32988 "Proxy-Authorization: Basic Zm9vOmJheg==\r\n\r\n"),
989 };
990
991 // The proxy responds to the connect with a 407, using a persistent
992 // connection.
993 MockRead data_reads1[] = {
994 // No credentials.
995 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
996 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
997 MockRead("Content-Length: 10\r\n\r\n"),
998 MockRead("0123456789"),
999
1000 // Wrong credentials (wrong password).
1001 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
1002 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1003 MockRead("Content-Length: 10\r\n\r\n"),
1004 // No response body because the test stops reading here.
[email protected]1c773ea12009-04-28 19:58:421005 MockRead(false, ERR_UNEXPECTED), // Should not be reached.
[email protected]2d2697f92009-02-18 21:00:321006 };
1007
[email protected]69b43fe2009-06-15 09:47:371008 StaticMockSocket data1(data_reads1, data_writes1);
[email protected]228ff742009-06-05 01:19:591009 session_deps.socket_factory.AddMockSocket(&data1);
[email protected]2d2697f92009-02-18 21:00:321010
1011 TestCompletionCallback callback1;
1012
[email protected]684970b2009-08-14 04:54:461013 int rv = trans->Start(&request, &callback1, NULL);
[email protected]1c773ea12009-04-28 19:58:421014 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:321015
1016 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421017 EXPECT_EQ(OK, rv);
[email protected]2d2697f92009-02-18 21:00:321018
[email protected]1c773ea12009-04-28 19:58:421019 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]2d2697f92009-02-18 21:00:321020 EXPECT_FALSE(response == NULL);
1021
1022 EXPECT_TRUE(response->headers->IsKeepAlive());
1023 EXPECT_EQ(407, response->headers->response_code());
1024 EXPECT_EQ(10, response->headers->GetContentLength());
[email protected]1c773ea12009-04-28 19:58:421025 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
[email protected]2d2697f92009-02-18 21:00:321026
1027 // The password prompt info should have been set in response->auth_challenge.
1028 EXPECT_FALSE(response->auth_challenge.get() == NULL);
1029
[email protected]71e4573a2009-05-21 22:03:001030 EXPECT_EQ(L"myproxy:70", response->auth_challenge->host_and_port);
[email protected]2d2697f92009-02-18 21:00:321031 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
1032 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
1033
1034 TestCompletionCallback callback2;
1035
1036 // Wrong password (should be "bar").
1037 rv = trans->RestartWithAuth(L"foo", L"baz", &callback2);
[email protected]1c773ea12009-04-28 19:58:421038 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:321039
1040 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421041 EXPECT_EQ(OK, rv);
[email protected]2d2697f92009-02-18 21:00:321042
1043 response = trans->GetResponseInfo();
1044 EXPECT_FALSE(response == NULL);
1045
1046 EXPECT_TRUE(response->headers->IsKeepAlive());
1047 EXPECT_EQ(407, response->headers->response_code());
1048 EXPECT_EQ(10, response->headers->GetContentLength());
[email protected]1c773ea12009-04-28 19:58:421049 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
[email protected]2d2697f92009-02-18 21:00:321050
1051 // The password prompt info should have been set in response->auth_challenge.
1052 EXPECT_FALSE(response->auth_challenge.get() == NULL);
1053
[email protected]71e4573a2009-05-21 22:03:001054 EXPECT_EQ(L"myproxy:70", response->auth_challenge->host_and_port);
[email protected]2d2697f92009-02-18 21:00:321055 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
1056 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
1057}
1058
[email protected]a8e9b162009-03-12 00:06:441059// Test that we don't read the response body when we fail to establish a tunnel,
1060// even if the user cancels the proxy's auth attempt.
1061TEST_F(HttpNetworkTransactionTest, BasicAuthProxyCancelTunnel) {
1062 // Configure against proxy server "myproxy:70".
[email protected]228ff742009-06-05 01:19:591063 SessionDependencies session_deps(CreateFixedProxyService("myproxy:70"));
[email protected]a8e9b162009-03-12 00:06:441064
[email protected]e44de5d2009-06-05 20:12:451065 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]a8e9b162009-03-12 00:06:441066
[email protected]1c773ea12009-04-28 19:58:421067 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(
[email protected]228ff742009-06-05 01:19:591068 session.get(), &session_deps.socket_factory));
[email protected]a8e9b162009-03-12 00:06:441069
[email protected]1c773ea12009-04-28 19:58:421070 HttpRequestInfo request;
[email protected]a8e9b162009-03-12 00:06:441071 request.method = "GET";
1072 request.url = GURL("https://www.google.com/");
1073 request.load_flags = 0;
1074
1075 // Since we have proxy, should try to establish tunnel.
1076 MockWrite data_writes[] = {
1077 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
[email protected]e44de5d2009-06-05 20:12:451078 "Host: www.google.com\r\n"
1079 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]a8e9b162009-03-12 00:06:441080 };
1081
1082 // The proxy responds to the connect with a 407.
1083 MockRead data_reads[] = {
1084 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
1085 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1086 MockRead("Content-Length: 10\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:421087 MockRead(false, ERR_UNEXPECTED), // Should not be reached.
[email protected]a8e9b162009-03-12 00:06:441088 };
1089
[email protected]69b43fe2009-06-15 09:47:371090 StaticMockSocket data(data_reads, data_writes);
[email protected]228ff742009-06-05 01:19:591091 session_deps.socket_factory.AddMockSocket(&data);
[email protected]a8e9b162009-03-12 00:06:441092
1093 TestCompletionCallback callback;
1094
[email protected]684970b2009-08-14 04:54:461095 int rv = trans->Start(&request, &callback, NULL);
[email protected]1c773ea12009-04-28 19:58:421096 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]a8e9b162009-03-12 00:06:441097
1098 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421099 EXPECT_EQ(OK, rv);
[email protected]a8e9b162009-03-12 00:06:441100
[email protected]1c773ea12009-04-28 19:58:421101 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]a8e9b162009-03-12 00:06:441102 EXPECT_FALSE(response == NULL);
1103
1104 EXPECT_TRUE(response->headers->IsKeepAlive());
1105 EXPECT_EQ(407, response->headers->response_code());
1106 EXPECT_EQ(10, response->headers->GetContentLength());
[email protected]1c773ea12009-04-28 19:58:421107 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
[email protected]a8e9b162009-03-12 00:06:441108
1109 std::string response_data;
1110 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:421111 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED, rv);
[email protected]a8e9b162009-03-12 00:06:441112}
1113
[email protected]ff007e162009-05-23 09:13:151114void HttpNetworkTransactionTest::ConnectStatusHelperWithExpectedStatus(
[email protected]c744cf22009-02-27 07:28:081115 const MockRead& status, int expected_status) {
1116 // Configure against proxy server "myproxy:70".
[email protected]228ff742009-06-05 01:19:591117 SessionDependencies session_deps(CreateFixedProxyService("myproxy:70"));
[email protected]c744cf22009-02-27 07:28:081118
[email protected]228ff742009-06-05 01:19:591119 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]c744cf22009-02-27 07:28:081120
[email protected]1c773ea12009-04-28 19:58:421121 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(
[email protected]228ff742009-06-05 01:19:591122 session.get(), &session_deps.socket_factory));
[email protected]c744cf22009-02-27 07:28:081123
[email protected]1c773ea12009-04-28 19:58:421124 HttpRequestInfo request;
[email protected]c744cf22009-02-27 07:28:081125 request.method = "GET";
1126 request.url = GURL("https://www.google.com/");
1127 request.load_flags = 0;
1128
1129 // Since we have proxy, should try to establish tunnel.
1130 MockWrite data_writes[] = {
1131 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
[email protected]e44de5d2009-06-05 20:12:451132 "Host: www.google.com\r\n"
1133 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]c744cf22009-02-27 07:28:081134 };
1135
1136 MockRead data_reads[] = {
1137 status,
1138 MockRead("Content-Length: 10\r\n\r\n"),
1139 // No response body because the test stops reading here.
[email protected]1c773ea12009-04-28 19:58:421140 MockRead(false, ERR_UNEXPECTED), // Should not be reached.
[email protected]c744cf22009-02-27 07:28:081141 };
1142
[email protected]69b43fe2009-06-15 09:47:371143 StaticMockSocket data(data_reads, data_writes);
[email protected]228ff742009-06-05 01:19:591144 session_deps.socket_factory.AddMockSocket(&data);
[email protected]c744cf22009-02-27 07:28:081145
1146 TestCompletionCallback callback;
1147
[email protected]684970b2009-08-14 04:54:461148 int rv = trans->Start(&request, &callback, NULL);
[email protected]1c773ea12009-04-28 19:58:421149 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]c744cf22009-02-27 07:28:081150
1151 rv = callback.WaitForResult();
1152 EXPECT_EQ(expected_status, rv);
1153}
1154
[email protected]ff007e162009-05-23 09:13:151155void HttpNetworkTransactionTest::ConnectStatusHelper(const MockRead& status) {
[email protected]c744cf22009-02-27 07:28:081156 ConnectStatusHelperWithExpectedStatus(
[email protected]1c773ea12009-04-28 19:58:421157 status, ERR_TUNNEL_CONNECTION_FAILED);
[email protected]c744cf22009-02-27 07:28:081158}
1159
1160TEST_F(HttpNetworkTransactionTest, ConnectStatus100) {
1161 ConnectStatusHelper(MockRead("HTTP/1.1 100 Continue\r\n"));
1162}
1163
1164TEST_F(HttpNetworkTransactionTest, ConnectStatus101) {
1165 ConnectStatusHelper(MockRead("HTTP/1.1 101 Switching Protocols\r\n"));
1166}
1167
1168TEST_F(HttpNetworkTransactionTest, ConnectStatus201) {
1169 ConnectStatusHelper(MockRead("HTTP/1.1 201 Created\r\n"));
1170}
1171
1172TEST_F(HttpNetworkTransactionTest, ConnectStatus202) {
1173 ConnectStatusHelper(MockRead("HTTP/1.1 202 Accepted\r\n"));
1174}
1175
1176TEST_F(HttpNetworkTransactionTest, ConnectStatus203) {
1177 ConnectStatusHelper(
1178 MockRead("HTTP/1.1 203 Non-Authoritative Information\r\n"));
1179}
1180
1181TEST_F(HttpNetworkTransactionTest, ConnectStatus204) {
1182 ConnectStatusHelper(MockRead("HTTP/1.1 204 No Content\r\n"));
1183}
1184
1185TEST_F(HttpNetworkTransactionTest, ConnectStatus205) {
1186 ConnectStatusHelper(MockRead("HTTP/1.1 205 Reset Content\r\n"));
1187}
1188
1189TEST_F(HttpNetworkTransactionTest, ConnectStatus206) {
1190 ConnectStatusHelper(MockRead("HTTP/1.1 206 Partial Content\r\n"));
1191}
1192
1193TEST_F(HttpNetworkTransactionTest, ConnectStatus300) {
1194 ConnectStatusHelper(MockRead("HTTP/1.1 300 Multiple Choices\r\n"));
1195}
1196
1197TEST_F(HttpNetworkTransactionTest, ConnectStatus301) {
1198 ConnectStatusHelper(MockRead("HTTP/1.1 301 Moved Permanently\r\n"));
1199}
1200
1201TEST_F(HttpNetworkTransactionTest, ConnectStatus302) {
1202 ConnectStatusHelper(MockRead("HTTP/1.1 302 Found\r\n"));
1203}
1204
1205TEST_F(HttpNetworkTransactionTest, ConnectStatus303) {
1206 ConnectStatusHelper(MockRead("HTTP/1.1 303 See Other\r\n"));
1207}
1208
1209TEST_F(HttpNetworkTransactionTest, ConnectStatus304) {
1210 ConnectStatusHelper(MockRead("HTTP/1.1 304 Not Modified\r\n"));
1211}
1212
1213TEST_F(HttpNetworkTransactionTest, ConnectStatus305) {
1214 ConnectStatusHelper(MockRead("HTTP/1.1 305 Use Proxy\r\n"));
1215}
1216
1217TEST_F(HttpNetworkTransactionTest, ConnectStatus306) {
1218 ConnectStatusHelper(MockRead("HTTP/1.1 306\r\n"));
1219}
1220
1221TEST_F(HttpNetworkTransactionTest, ConnectStatus307) {
1222 ConnectStatusHelper(MockRead("HTTP/1.1 307 Temporary Redirect\r\n"));
1223}
1224
1225TEST_F(HttpNetworkTransactionTest, ConnectStatus400) {
1226 ConnectStatusHelper(MockRead("HTTP/1.1 400 Bad Request\r\n"));
1227}
1228
1229TEST_F(HttpNetworkTransactionTest, ConnectStatus401) {
1230 ConnectStatusHelper(MockRead("HTTP/1.1 401 Unauthorized\r\n"));
1231}
1232
1233TEST_F(HttpNetworkTransactionTest, ConnectStatus402) {
1234 ConnectStatusHelper(MockRead("HTTP/1.1 402 Payment Required\r\n"));
1235}
1236
1237TEST_F(HttpNetworkTransactionTest, ConnectStatus403) {
1238 ConnectStatusHelper(MockRead("HTTP/1.1 403 Forbidden\r\n"));
1239}
1240
1241TEST_F(HttpNetworkTransactionTest, ConnectStatus404) {
1242 ConnectStatusHelper(MockRead("HTTP/1.1 404 Not Found\r\n"));
1243}
1244
1245TEST_F(HttpNetworkTransactionTest, ConnectStatus405) {
1246 ConnectStatusHelper(MockRead("HTTP/1.1 405 Method Not Allowed\r\n"));
1247}
1248
1249TEST_F(HttpNetworkTransactionTest, ConnectStatus406) {
1250 ConnectStatusHelper(MockRead("HTTP/1.1 406 Not Acceptable\r\n"));
1251}
1252
1253TEST_F(HttpNetworkTransactionTest, ConnectStatus407) {
1254 ConnectStatusHelperWithExpectedStatus(
1255 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
[email protected]1c773ea12009-04-28 19:58:421256 ERR_PROXY_AUTH_REQUESTED);
[email protected]c744cf22009-02-27 07:28:081257}
1258
1259TEST_F(HttpNetworkTransactionTest, ConnectStatus408) {
1260 ConnectStatusHelper(MockRead("HTTP/1.1 408 Request Timeout\r\n"));
1261}
1262
1263TEST_F(HttpNetworkTransactionTest, ConnectStatus409) {
1264 ConnectStatusHelper(MockRead("HTTP/1.1 409 Conflict\r\n"));
1265}
1266
1267TEST_F(HttpNetworkTransactionTest, ConnectStatus410) {
1268 ConnectStatusHelper(MockRead("HTTP/1.1 410 Gone\r\n"));
1269}
1270
1271TEST_F(HttpNetworkTransactionTest, ConnectStatus411) {
1272 ConnectStatusHelper(MockRead("HTTP/1.1 411 Length Required\r\n"));
1273}
1274
1275TEST_F(HttpNetworkTransactionTest, ConnectStatus412) {
1276 ConnectStatusHelper(MockRead("HTTP/1.1 412 Precondition Failed\r\n"));
1277}
1278
1279TEST_F(HttpNetworkTransactionTest, ConnectStatus413) {
1280 ConnectStatusHelper(MockRead("HTTP/1.1 413 Request Entity Too Large\r\n"));
1281}
1282
1283TEST_F(HttpNetworkTransactionTest, ConnectStatus414) {
1284 ConnectStatusHelper(MockRead("HTTP/1.1 414 Request-URI Too Long\r\n"));
1285}
1286
1287TEST_F(HttpNetworkTransactionTest, ConnectStatus415) {
1288 ConnectStatusHelper(MockRead("HTTP/1.1 415 Unsupported Media Type\r\n"));
1289}
1290
1291TEST_F(HttpNetworkTransactionTest, ConnectStatus416) {
1292 ConnectStatusHelper(
1293 MockRead("HTTP/1.1 416 Requested Range Not Satisfiable\r\n"));
1294}
1295
1296TEST_F(HttpNetworkTransactionTest, ConnectStatus417) {
1297 ConnectStatusHelper(MockRead("HTTP/1.1 417 Expectation Failed\r\n"));
1298}
1299
1300TEST_F(HttpNetworkTransactionTest, ConnectStatus500) {
1301 ConnectStatusHelper(MockRead("HTTP/1.1 500 Internal Server Error\r\n"));
1302}
1303
1304TEST_F(HttpNetworkTransactionTest, ConnectStatus501) {
1305 ConnectStatusHelper(MockRead("HTTP/1.1 501 Not Implemented\r\n"));
1306}
1307
1308TEST_F(HttpNetworkTransactionTest, ConnectStatus502) {
1309 ConnectStatusHelper(MockRead("HTTP/1.1 502 Bad Gateway\r\n"));
1310}
1311
1312TEST_F(HttpNetworkTransactionTest, ConnectStatus503) {
1313 ConnectStatusHelper(MockRead("HTTP/1.1 503 Service Unavailable\r\n"));
1314}
1315
1316TEST_F(HttpNetworkTransactionTest, ConnectStatus504) {
1317 ConnectStatusHelper(MockRead("HTTP/1.1 504 Gateway Timeout\r\n"));
1318}
1319
1320TEST_F(HttpNetworkTransactionTest, ConnectStatus505) {
1321 ConnectStatusHelper(MockRead("HTTP/1.1 505 HTTP Version Not Supported\r\n"));
1322}
1323
[email protected]038e9a32008-10-08 22:40:161324// Test the flow when both the proxy server AND origin server require
1325// authentication. Again, this uses basic auth for both since that is
1326// the simplest to mock.
1327TEST_F(HttpNetworkTransactionTest, BasicAuthProxyThenServer) {
[email protected]228ff742009-06-05 01:19:591328 SessionDependencies session_deps(CreateFixedProxyService("myproxy:70"));
[email protected]db8f44c2008-12-13 04:52:011329
[email protected]038e9a32008-10-08 22:40:161330 // Configure against proxy server "myproxy:70".
[email protected]1c773ea12009-04-28 19:58:421331 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(
[email protected]228ff742009-06-05 01:19:591332 CreateSession(&session_deps),
1333 &session_deps.socket_factory));
[email protected]038e9a32008-10-08 22:40:161334
[email protected]1c773ea12009-04-28 19:58:421335 HttpRequestInfo request;
[email protected]038e9a32008-10-08 22:40:161336 request.method = "GET";
1337 request.url = GURL("http://www.google.com/");
1338 request.load_flags = 0;
1339
[email protected]f9ee6b52008-11-08 06:46:231340 MockWrite data_writes1[] = {
1341 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
1342 "Host: www.google.com\r\n"
1343 "Proxy-Connection: keep-alive\r\n\r\n"),
1344 };
1345
[email protected]038e9a32008-10-08 22:40:161346 MockRead data_reads1[] = {
1347 MockRead("HTTP/1.0 407 Unauthorized\r\n"),
1348 // Give a couple authenticate options (only the middle one is actually
1349 // supported).
[email protected]aaead502008-10-15 00:20:111350 MockRead("Proxy-Authenticate: Basic\r\n"), // Malformed
[email protected]038e9a32008-10-08 22:40:161351 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1352 MockRead("Proxy-Authenticate: UNSUPPORTED realm=\"FOO\"\r\n"),
1353 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1354 // Large content-length -- won't matter, as connection will be reset.
1355 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:421356 MockRead(false, ERR_FAILED),
[email protected]038e9a32008-10-08 22:40:161357 };
1358
1359 // After calling trans->RestartWithAuth() the first time, this is the
1360 // request we should be issuing -- the final header line contains the
1361 // proxy's credentials.
1362 MockWrite data_writes2[] = {
1363 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
1364 "Host: www.google.com\r\n"
1365 "Proxy-Connection: keep-alive\r\n"
1366 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
1367 };
1368
1369 // Now the proxy server lets the request pass through to origin server.
1370 // The origin server responds with a 401.
1371 MockRead data_reads2[] = {
1372 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
1373 // Note: We are using the same realm-name as the proxy server. This is
1374 // completely valid, as realms are unique across hosts.
1375 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1376 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1377 MockRead("Content-Length: 2000\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:421378 MockRead(false, ERR_FAILED), // Won't be reached.
[email protected]038e9a32008-10-08 22:40:161379 };
1380
1381 // After calling trans->RestartWithAuth() the second time, we should send
1382 // the credentials for both the proxy and origin server.
1383 MockWrite data_writes3[] = {
1384 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
1385 "Host: www.google.com\r\n"
1386 "Proxy-Connection: keep-alive\r\n"
1387 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n"
1388 "Authorization: Basic Zm9vMjpiYXIy\r\n\r\n"),
1389 };
1390
1391 // Lastly we get the desired content.
1392 MockRead data_reads3[] = {
1393 MockRead("HTTP/1.0 200 OK\r\n"),
1394 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1395 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:421396 MockRead(false, OK),
[email protected]038e9a32008-10-08 22:40:161397 };
1398
[email protected]69b43fe2009-06-15 09:47:371399 StaticMockSocket data1(data_reads1, data_writes1);
1400 StaticMockSocket data2(data_reads2, data_writes2);
1401 StaticMockSocket data3(data_reads3, data_writes3);
[email protected]228ff742009-06-05 01:19:591402 session_deps.socket_factory.AddMockSocket(&data1);
1403 session_deps.socket_factory.AddMockSocket(&data2);
1404 session_deps.socket_factory.AddMockSocket(&data3);
[email protected]038e9a32008-10-08 22:40:161405
1406 TestCompletionCallback callback1;
1407
[email protected]684970b2009-08-14 04:54:461408 int rv = trans->Start(&request, &callback1, NULL);
[email protected]1c773ea12009-04-28 19:58:421409 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]038e9a32008-10-08 22:40:161410
1411 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421412 EXPECT_EQ(OK, rv);
[email protected]038e9a32008-10-08 22:40:161413
[email protected]1c773ea12009-04-28 19:58:421414 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]038e9a32008-10-08 22:40:161415 EXPECT_FALSE(response == NULL);
1416
1417 // The password prompt info should have been set in response->auth_challenge.
1418 EXPECT_FALSE(response->auth_challenge.get() == NULL);
1419
[email protected]71e4573a2009-05-21 22:03:001420 EXPECT_EQ(L"myproxy:70", response->auth_challenge->host_and_port);
[email protected]038e9a32008-10-08 22:40:161421 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
1422 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
1423
1424 TestCompletionCallback callback2;
1425
1426 rv = trans->RestartWithAuth(L"foo", L"bar", &callback2);
[email protected]1c773ea12009-04-28 19:58:421427 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]038e9a32008-10-08 22:40:161428
1429 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421430 EXPECT_EQ(OK, rv);
[email protected]038e9a32008-10-08 22:40:161431
1432 response = trans->GetResponseInfo();
1433 EXPECT_FALSE(response == NULL);
1434 EXPECT_FALSE(response->auth_challenge.get() == NULL);
1435
[email protected]71e4573a2009-05-21 22:03:001436 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
[email protected]038e9a32008-10-08 22:40:161437 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
1438 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
1439
1440 TestCompletionCallback callback3;
1441
1442 rv = trans->RestartWithAuth(L"foo2", L"bar2", &callback3);
[email protected]1c773ea12009-04-28 19:58:421443 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]038e9a32008-10-08 22:40:161444
1445 rv = callback3.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421446 EXPECT_EQ(OK, rv);
[email protected]038e9a32008-10-08 22:40:161447
1448 response = trans->GetResponseInfo();
1449 EXPECT_TRUE(response->auth_challenge.get() == NULL);
1450 EXPECT_EQ(100, response->headers->GetContentLength());
[email protected]038e9a32008-10-08 22:40:161451}
[email protected]4ddaf2502008-10-23 18:26:191452
[email protected]385a4672009-03-11 22:21:291453// The NTLM authentication unit tests were generated by capturing the HTTP
1454// requests and responses using Fiddler 2 and inspecting the generated random
1455// bytes in the debugger.
1456
1457// Enter the correct password and authenticate successfully.
1458TEST_F(HttpNetworkTransactionTest, NTLMAuth1) {
[email protected]1c773ea12009-04-28 19:58:421459 HttpAuthHandlerNTLM::ScopedProcSetter proc_setter(MockGenerateRandom1,
[email protected]fe2bc6a2009-03-23 16:52:201460 MockGetHostName);
[email protected]228ff742009-06-05 01:19:591461 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:401462 scoped_ptr<HttpTransaction> trans(
1463 new HttpNetworkTransaction(
[email protected]228ff742009-06-05 01:19:591464 CreateSession(&session_deps),
1465 &session_deps.socket_factory));
[email protected]3f918782009-02-28 01:29:241466
[email protected]1c773ea12009-04-28 19:58:421467 HttpRequestInfo request;
[email protected]3f918782009-02-28 01:29:241468 request.method = "GET";
1469 request.url = GURL("http://172.22.68.17/kids/login.aspx");
1470 request.load_flags = 0;
1471
1472 MockWrite data_writes1[] = {
1473 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
1474 "Host: 172.22.68.17\r\n"
1475 "Connection: keep-alive\r\n\r\n"),
1476 };
1477
1478 MockRead data_reads1[] = {
1479 MockRead("HTTP/1.1 401 Access Denied\r\n"),
1480 // Negotiate and NTLM are often requested together. We only support NTLM.
1481 MockRead("WWW-Authenticate: Negotiate\r\n"),
1482 MockRead("WWW-Authenticate: NTLM\r\n"),
1483 MockRead("Connection: close\r\n"),
1484 MockRead("Content-Length: 42\r\n"),
[email protected]076c85082009-04-10 23:21:361485 MockRead("Content-Type: text/html\r\n\r\n"),
[email protected]3f918782009-02-28 01:29:241486 // Missing content -- won't matter, as connection will be reset.
[email protected]1c773ea12009-04-28 19:58:421487 MockRead(false, ERR_UNEXPECTED),
[email protected]3f918782009-02-28 01:29:241488 };
1489
1490 MockWrite data_writes2[] = {
[email protected]0757e7702009-03-27 04:00:221491 // After restarting with a null identity, this is the
[email protected]3f918782009-02-28 01:29:241492 // request we should be issuing -- the final header line contains a Type
1493 // 1 message.
1494 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
1495 "Host: 172.22.68.17\r\n"
1496 "Connection: keep-alive\r\n"
1497 "Authorization: NTLM "
1498 "TlRMTVNTUAABAAAAB4IIAAAAAAAAAAAAAAAAAAAAAAA=\r\n\r\n"),
1499
1500 // After calling trans->RestartWithAuth(), we should send a Type 3 message
1501 // (the credentials for the origin server). The second request continues
1502 // on the same connection.
1503 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
1504 "Host: 172.22.68.17\r\n"
1505 "Connection: keep-alive\r\n"
[email protected]385a4672009-03-11 22:21:291506 "Authorization: NTLM TlRMTVNTUAADAAAAGAAYAGgAAAAYABgAgA"
1507 "AAAAAAAABAAAAAGAAYAEAAAAAQABAAWAAAAAAAAAAAAAAABYIIAHQA"
1508 "ZQBzAHQAaQBuAGcALQBuAHQAbABtAFcAVABDAC0AVwBJAE4ANwBVKW"
1509 "Yma5xzVAAAAAAAAAAAAAAAAAAAAACH+gWcm+YsP9Tqb9zCR3WAeZZX"
1510 "ahlhx5I=\r\n\r\n"),
[email protected]3f918782009-02-28 01:29:241511 };
1512
1513 MockRead data_reads2[] = {
1514 // The origin server responds with a Type 2 message.
1515 MockRead("HTTP/1.1 401 Access Denied\r\n"),
1516 MockRead("WWW-Authenticate: NTLM "
[email protected]385a4672009-03-11 22:21:291517 "TlRMTVNTUAACAAAADAAMADgAAAAFgokCjGpMpPGlYKkAAAAAAAAAALo"
[email protected]3f918782009-02-28 01:29:241518 "AugBEAAAABQEoCgAAAA9HAE8ATwBHAEwARQACAAwARwBPAE8ARwBMAE"
1519 "UAAQAaAEEASwBFAEUAUwBBAFIAQQAtAEMATwBSAFAABAAeAGMAbwByA"
1520 "HAALgBnAG8AbwBnAGwAZQAuAGMAbwBtAAMAQABhAGsAZQBlAHMAYQBy"
1521 "AGEALQBjAG8AcgBwAC4AYQBkAC4AYwBvAHIAcAAuAGcAbwBvAGcAbAB"
1522 "lAC4AYwBvAG0ABQAeAGMAbwByAHAALgBnAG8AbwBnAGwAZQAuAGMAbw"
1523 "BtAAAAAAA=\r\n"),
1524 MockRead("Content-Length: 42\r\n"),
[email protected]076c85082009-04-10 23:21:361525 MockRead("Content-Type: text/html\r\n\r\n"),
[email protected]3f918782009-02-28 01:29:241526 MockRead("You are not authorized to view this page\r\n"),
1527
1528 // Lastly we get the desired content.
1529 MockRead("HTTP/1.1 200 OK\r\n"),
1530 MockRead("Content-Type: text/html; charset=utf-8\r\n"),
1531 MockRead("Content-Length: 13\r\n\r\n"),
1532 MockRead("Please Login\r\n"),
[email protected]1c773ea12009-04-28 19:58:421533 MockRead(false, OK),
[email protected]3f918782009-02-28 01:29:241534 };
1535
[email protected]69b43fe2009-06-15 09:47:371536 StaticMockSocket data1(data_reads1, data_writes1);
1537 StaticMockSocket data2(data_reads2, data_writes2);
[email protected]228ff742009-06-05 01:19:591538 session_deps.socket_factory.AddMockSocket(&data1);
1539 session_deps.socket_factory.AddMockSocket(&data2);
[email protected]3f918782009-02-28 01:29:241540
1541 TestCompletionCallback callback1;
1542
[email protected]684970b2009-08-14 04:54:461543 int rv = trans->Start(&request, &callback1, NULL);
[email protected]1c773ea12009-04-28 19:58:421544 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]3f918782009-02-28 01:29:241545
1546 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421547 EXPECT_EQ(OK, rv);
[email protected]3f918782009-02-28 01:29:241548
[email protected]0757e7702009-03-27 04:00:221549 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
1550 TestCompletionCallback callback2;
1551 rv = trans->RestartWithAuth(std::wstring(), std::wstring(), &callback2);
[email protected]1c773ea12009-04-28 19:58:421552 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]0757e7702009-03-27 04:00:221553 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421554 EXPECT_EQ(OK, rv);
[email protected]0757e7702009-03-27 04:00:221555 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
1556
[email protected]1c773ea12009-04-28 19:58:421557 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]3f918782009-02-28 01:29:241558 EXPECT_FALSE(response == NULL);
1559
1560 // The password prompt info should have been set in response->auth_challenge.
1561 EXPECT_FALSE(response->auth_challenge.get() == NULL);
1562
[email protected]71e4573a2009-05-21 22:03:001563 EXPECT_EQ(L"172.22.68.17:80", response->auth_challenge->host_and_port);
[email protected]3f918782009-02-28 01:29:241564 EXPECT_EQ(L"", response->auth_challenge->realm);
1565 EXPECT_EQ(L"ntlm", response->auth_challenge->scheme);
1566
[email protected]0757e7702009-03-27 04:00:221567 TestCompletionCallback callback3;
[email protected]3f918782009-02-28 01:29:241568
[email protected]0757e7702009-03-27 04:00:221569 rv = trans->RestartWithAuth(L"testing-ntlm", L"testing-ntlm", &callback3);
[email protected]1c773ea12009-04-28 19:58:421570 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]3f918782009-02-28 01:29:241571
[email protected]0757e7702009-03-27 04:00:221572 rv = callback3.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421573 EXPECT_EQ(OK, rv);
[email protected]3f918782009-02-28 01:29:241574
1575 response = trans->GetResponseInfo();
1576 EXPECT_TRUE(response->auth_challenge.get() == NULL);
1577 EXPECT_EQ(13, response->headers->GetContentLength());
1578}
1579
[email protected]385a4672009-03-11 22:21:291580// Enter a wrong password, and then the correct one.
1581TEST_F(HttpNetworkTransactionTest, NTLMAuth2) {
[email protected]1c773ea12009-04-28 19:58:421582 HttpAuthHandlerNTLM::ScopedProcSetter proc_setter(MockGenerateRandom2,
[email protected]fe2bc6a2009-03-23 16:52:201583 MockGetHostName);
[email protected]228ff742009-06-05 01:19:591584 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:401585 scoped_ptr<HttpTransaction> trans(
1586 new HttpNetworkTransaction(
[email protected]228ff742009-06-05 01:19:591587 CreateSession(&session_deps),
1588 &session_deps.socket_factory));
[email protected]385a4672009-03-11 22:21:291589
[email protected]1c773ea12009-04-28 19:58:421590 HttpRequestInfo request;
[email protected]385a4672009-03-11 22:21:291591 request.method = "GET";
1592 request.url = GURL("http://172.22.68.17/kids/login.aspx");
1593 request.load_flags = 0;
1594
1595 MockWrite data_writes1[] = {
1596 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
1597 "Host: 172.22.68.17\r\n"
1598 "Connection: keep-alive\r\n\r\n"),
1599 };
1600
1601 MockRead data_reads1[] = {
1602 MockRead("HTTP/1.1 401 Access Denied\r\n"),
1603 // Negotiate and NTLM are often requested together. We only support NTLM.
1604 MockRead("WWW-Authenticate: Negotiate\r\n"),
1605 MockRead("WWW-Authenticate: NTLM\r\n"),
1606 MockRead("Connection: close\r\n"),
1607 MockRead("Content-Length: 42\r\n"),
[email protected]076c85082009-04-10 23:21:361608 MockRead("Content-Type: text/html\r\n\r\n"),
[email protected]385a4672009-03-11 22:21:291609 // Missing content -- won't matter, as connection will be reset.
[email protected]1c773ea12009-04-28 19:58:421610 MockRead(false, ERR_UNEXPECTED),
[email protected]385a4672009-03-11 22:21:291611 };
1612
1613 MockWrite data_writes2[] = {
[email protected]0757e7702009-03-27 04:00:221614 // After restarting with a null identity, this is the
[email protected]385a4672009-03-11 22:21:291615 // request we should be issuing -- the final header line contains a Type
1616 // 1 message.
1617 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
1618 "Host: 172.22.68.17\r\n"
1619 "Connection: keep-alive\r\n"
1620 "Authorization: NTLM "
1621 "TlRMTVNTUAABAAAAB4IIAAAAAAAAAAAAAAAAAAAAAAA=\r\n\r\n"),
1622
1623 // After calling trans->RestartWithAuth(), we should send a Type 3 message
1624 // (the credentials for the origin server). The second request continues
1625 // on the same connection.
1626 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
1627 "Host: 172.22.68.17\r\n"
1628 "Connection: keep-alive\r\n"
1629 "Authorization: NTLM TlRMTVNTUAADAAAAGAAYAGgAAAAYABgAgA"
1630 "AAAAAAAABAAAAAGAAYAEAAAAAQABAAWAAAAAAAAAAAAAAABYIIAHQA"
1631 "ZQBzAHQAaQBuAGcALQBuAHQAbABtAFcAVABDAC0AVwBJAE4ANwCWeY"
1632 "XnSZNwoQAAAAAAAAAAAAAAAAAAAADLa34/phTTKzNTWdub+uyFleOj"
1633 "4Ww7b7E=\r\n\r\n"),
1634 };
1635
1636 MockRead data_reads2[] = {
1637 // The origin server responds with a Type 2 message.
1638 MockRead("HTTP/1.1 401 Access Denied\r\n"),
1639 MockRead("WWW-Authenticate: NTLM "
1640 "TlRMTVNTUAACAAAADAAMADgAAAAFgokCbVWUZezVGpAAAAAAAAAAALo"
1641 "AugBEAAAABQEoCgAAAA9HAE8ATwBHAEwARQACAAwARwBPAE8ARwBMAE"
1642 "UAAQAaAEEASwBFAEUAUwBBAFIAQQAtAEMATwBSAFAABAAeAGMAbwByA"
1643 "HAALgBnAG8AbwBnAGwAZQAuAGMAbwBtAAMAQABhAGsAZQBlAHMAYQBy"
1644 "AGEALQBjAG8AcgBwAC4AYQBkAC4AYwBvAHIAcAAuAGcAbwBvAGcAbAB"
1645 "lAC4AYwBvAG0ABQAeAGMAbwByAHAALgBnAG8AbwBnAGwAZQAuAGMAbw"
1646 "BtAAAAAAA=\r\n"),
1647 MockRead("Content-Length: 42\r\n"),
[email protected]076c85082009-04-10 23:21:361648 MockRead("Content-Type: text/html\r\n\r\n"),
[email protected]385a4672009-03-11 22:21:291649 MockRead("You are not authorized to view this page\r\n"),
1650
1651 // Wrong password.
1652 MockRead("HTTP/1.1 401 Access Denied\r\n"),
1653 MockRead("WWW-Authenticate: Negotiate\r\n"),
1654 MockRead("WWW-Authenticate: NTLM\r\n"),
1655 MockRead("Connection: close\r\n"),
1656 MockRead("Content-Length: 42\r\n"),
[email protected]076c85082009-04-10 23:21:361657 MockRead("Content-Type: text/html\r\n\r\n"),
[email protected]385a4672009-03-11 22:21:291658 // Missing content -- won't matter, as connection will be reset.
[email protected]1c773ea12009-04-28 19:58:421659 MockRead(false, ERR_UNEXPECTED),
[email protected]385a4672009-03-11 22:21:291660 };
1661
1662 MockWrite data_writes3[] = {
[email protected]0757e7702009-03-27 04:00:221663 // After restarting with a null identity, this is the
[email protected]385a4672009-03-11 22:21:291664 // request we should be issuing -- the final header line contains a Type
1665 // 1 message.
1666 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
1667 "Host: 172.22.68.17\r\n"
1668 "Connection: keep-alive\r\n"
1669 "Authorization: NTLM "
1670 "TlRMTVNTUAABAAAAB4IIAAAAAAAAAAAAAAAAAAAAAAA=\r\n\r\n"),
1671
1672 // After calling trans->RestartWithAuth(), we should send a Type 3 message
1673 // (the credentials for the origin server). The second request continues
1674 // on the same connection.
1675 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
1676 "Host: 172.22.68.17\r\n"
1677 "Connection: keep-alive\r\n"
1678 "Authorization: NTLM TlRMTVNTUAADAAAAGAAYAGgAAAAYABgAgA"
1679 "AAAAAAAABAAAAAGAAYAEAAAAAQABAAWAAAAAAAAAAAAAAABYIIAHQA"
1680 "ZQBzAHQAaQBuAGcALQBuAHQAbABtAFcAVABDAC0AVwBJAE4ANwBO54"
1681 "dFMVvTHwAAAAAAAAAAAAAAAAAAAACS7sT6Uzw7L0L//WUqlIaVWpbI"
1682 "+4MUm7c=\r\n\r\n"),
1683 };
1684
1685 MockRead data_reads3[] = {
1686 // The origin server responds with a Type 2 message.
1687 MockRead("HTTP/1.1 401 Access Denied\r\n"),
1688 MockRead("WWW-Authenticate: NTLM "
1689 "TlRMTVNTUAACAAAADAAMADgAAAAFgokCL24VN8dgOR8AAAAAAAAAALo"
1690 "AugBEAAAABQEoCgAAAA9HAE8ATwBHAEwARQACAAwARwBPAE8ARwBMAE"
1691 "UAAQAaAEEASwBFAEUAUwBBAFIAQQAtAEMATwBSAFAABAAeAGMAbwByA"
1692 "HAALgBnAG8AbwBnAGwAZQAuAGMAbwBtAAMAQABhAGsAZQBlAHMAYQBy"
1693 "AGEALQBjAG8AcgBwAC4AYQBkAC4AYwBvAHIAcAAuAGcAbwBvAGcAbAB"
1694 "lAC4AYwBvAG0ABQAeAGMAbwByAHAALgBnAG8AbwBnAGwAZQAuAGMAbw"
1695 "BtAAAAAAA=\r\n"),
1696 MockRead("Content-Length: 42\r\n"),
[email protected]076c85082009-04-10 23:21:361697 MockRead("Content-Type: text/html\r\n\r\n"),
[email protected]385a4672009-03-11 22:21:291698 MockRead("You are not authorized to view this page\r\n"),
1699
1700 // Lastly we get the desired content.
1701 MockRead("HTTP/1.1 200 OK\r\n"),
1702 MockRead("Content-Type: text/html; charset=utf-8\r\n"),
1703 MockRead("Content-Length: 13\r\n\r\n"),
1704 MockRead("Please Login\r\n"),
[email protected]1c773ea12009-04-28 19:58:421705 MockRead(false, OK),
[email protected]385a4672009-03-11 22:21:291706 };
1707
[email protected]69b43fe2009-06-15 09:47:371708 StaticMockSocket data1(data_reads1, data_writes1);
1709 StaticMockSocket data2(data_reads2, data_writes2);
1710 StaticMockSocket data3(data_reads3, data_writes3);
[email protected]228ff742009-06-05 01:19:591711 session_deps.socket_factory.AddMockSocket(&data1);
1712 session_deps.socket_factory.AddMockSocket(&data2);
1713 session_deps.socket_factory.AddMockSocket(&data3);
[email protected]385a4672009-03-11 22:21:291714
1715 TestCompletionCallback callback1;
1716
[email protected]684970b2009-08-14 04:54:461717 int rv = trans->Start(&request, &callback1, NULL);
[email protected]1c773ea12009-04-28 19:58:421718 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]385a4672009-03-11 22:21:291719
1720 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421721 EXPECT_EQ(OK, rv);
[email protected]385a4672009-03-11 22:21:291722
[email protected]0757e7702009-03-27 04:00:221723 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
[email protected]385a4672009-03-11 22:21:291724 TestCompletionCallback callback2;
[email protected]0757e7702009-03-27 04:00:221725 rv = trans->RestartWithAuth(std::wstring(), std::wstring(), &callback2);
[email protected]1c773ea12009-04-28 19:58:421726 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]385a4672009-03-11 22:21:291727 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421728 EXPECT_EQ(OK, rv);
[email protected]0757e7702009-03-27 04:00:221729 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
[email protected]385a4672009-03-11 22:21:291730
[email protected]1c773ea12009-04-28 19:58:421731 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]385a4672009-03-11 22:21:291732 EXPECT_FALSE(response == NULL);
1733
1734 // The password prompt info should have been set in response->auth_challenge.
1735 EXPECT_FALSE(response->auth_challenge.get() == NULL);
1736
[email protected]71e4573a2009-05-21 22:03:001737 EXPECT_EQ(L"172.22.68.17:80", response->auth_challenge->host_and_port);
[email protected]385a4672009-03-11 22:21:291738 EXPECT_EQ(L"", response->auth_challenge->realm);
1739 EXPECT_EQ(L"ntlm", response->auth_challenge->scheme);
1740
1741 TestCompletionCallback callback3;
1742
[email protected]0757e7702009-03-27 04:00:221743 // Enter the wrong password.
1744 rv = trans->RestartWithAuth(L"testing-ntlm", L"wrongpassword", &callback3);
[email protected]1c773ea12009-04-28 19:58:421745 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]385a4672009-03-11 22:21:291746
1747 rv = callback3.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421748 EXPECT_EQ(OK, rv);
[email protected]385a4672009-03-11 22:21:291749
[email protected]0757e7702009-03-27 04:00:221750 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
1751 TestCompletionCallback callback4;
1752 rv = trans->RestartWithAuth(std::wstring(), std::wstring(), &callback4);
[email protected]1c773ea12009-04-28 19:58:421753 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]0757e7702009-03-27 04:00:221754 rv = callback4.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421755 EXPECT_EQ(OK, rv);
[email protected]0757e7702009-03-27 04:00:221756 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
1757
1758 response = trans->GetResponseInfo();
1759 EXPECT_FALSE(response == NULL);
1760
1761 // The password prompt info should have been set in response->auth_challenge.
1762 EXPECT_FALSE(response->auth_challenge.get() == NULL);
1763
[email protected]71e4573a2009-05-21 22:03:001764 EXPECT_EQ(L"172.22.68.17:80", response->auth_challenge->host_and_port);
[email protected]0757e7702009-03-27 04:00:221765 EXPECT_EQ(L"", response->auth_challenge->realm);
1766 EXPECT_EQ(L"ntlm", response->auth_challenge->scheme);
1767
1768 TestCompletionCallback callback5;
1769
1770 // Now enter the right password.
1771 rv = trans->RestartWithAuth(L"testing-ntlm", L"testing-ntlm", &callback5);
[email protected]1c773ea12009-04-28 19:58:421772 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]0757e7702009-03-27 04:00:221773
1774 rv = callback5.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421775 EXPECT_EQ(OK, rv);
[email protected]0757e7702009-03-27 04:00:221776
[email protected]385a4672009-03-11 22:21:291777 response = trans->GetResponseInfo();
1778 EXPECT_TRUE(response->auth_challenge.get() == NULL);
1779 EXPECT_EQ(13, response->headers->GetContentLength());
1780}
1781
[email protected]4ddaf2502008-10-23 18:26:191782// Test reading a server response which has only headers, and no body.
1783// After some maximum number of bytes is consumed, the transaction should
1784// fail with ERR_RESPONSE_HEADERS_TOO_BIG.
1785TEST_F(HttpNetworkTransactionTest, LargeHeadersNoBody) {
[email protected]228ff742009-06-05 01:19:591786 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:401787 scoped_ptr<HttpTransaction> trans(
1788 new HttpNetworkTransaction(
[email protected]228ff742009-06-05 01:19:591789 CreateSession(&session_deps),
1790 &session_deps.socket_factory));
[email protected]4ddaf2502008-10-23 18:26:191791
[email protected]1c773ea12009-04-28 19:58:421792 HttpRequestInfo request;
[email protected]4ddaf2502008-10-23 18:26:191793 request.method = "GET";
1794 request.url = GURL("http://www.google.com/");
1795 request.load_flags = 0;
1796
1797 // Respond with 50 kb of headers (we should fail after 32 kb).
[email protected]15a5ccf82008-10-23 19:57:431798 std::string large_headers_string;
1799 FillLargeHeadersString(&large_headers_string, 50 * 1024);
[email protected]4ddaf2502008-10-23 18:26:191800
1801 MockRead data_reads[] = {
1802 MockRead("HTTP/1.0 200 OK\r\n"),
[email protected]15a5ccf82008-10-23 19:57:431803 MockRead(true, large_headers_string.data(), large_headers_string.size()),
[email protected]4ddaf2502008-10-23 18:26:191804 MockRead("\r\nBODY"),
[email protected]1c773ea12009-04-28 19:58:421805 MockRead(false, OK),
[email protected]4ddaf2502008-10-23 18:26:191806 };
[email protected]69b43fe2009-06-15 09:47:371807 StaticMockSocket data(data_reads, NULL);
[email protected]228ff742009-06-05 01:19:591808 session_deps.socket_factory.AddMockSocket(&data);
[email protected]4ddaf2502008-10-23 18:26:191809
1810 TestCompletionCallback callback;
1811
[email protected]684970b2009-08-14 04:54:461812 int rv = trans->Start(&request, &callback, NULL);
[email protected]1c773ea12009-04-28 19:58:421813 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]4ddaf2502008-10-23 18:26:191814
1815 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421816 EXPECT_EQ(ERR_RESPONSE_HEADERS_TOO_BIG, rv);
[email protected]4ddaf2502008-10-23 18:26:191817
[email protected]1c773ea12009-04-28 19:58:421818 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]4ddaf2502008-10-23 18:26:191819 EXPECT_TRUE(response == NULL);
1820}
[email protected]f4e426b2008-11-05 00:24:491821
1822// Make sure that we don't try to reuse a TCPClientSocket when failing to
1823// establish tunnel.
1824// http://code.google.com/p/chromium/issues/detail?id=3772
1825TEST_F(HttpNetworkTransactionTest, DontRecycleTCPSocketForSSLTunnel) {
1826 // Configure against proxy server "myproxy:70".
[email protected]228ff742009-06-05 01:19:591827 SessionDependencies session_deps(CreateFixedProxyService("myproxy:70"));
[email protected]db8f44c2008-12-13 04:52:011828
[email protected]228ff742009-06-05 01:19:591829 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]f4e426b2008-11-05 00:24:491830
[email protected]1c773ea12009-04-28 19:58:421831 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(
[email protected]228ff742009-06-05 01:19:591832 session.get(), &session_deps.socket_factory));
[email protected]f4e426b2008-11-05 00:24:491833
[email protected]1c773ea12009-04-28 19:58:421834 HttpRequestInfo request;
[email protected]f4e426b2008-11-05 00:24:491835 request.method = "GET";
1836 request.url = GURL("https://www.google.com/");
1837 request.load_flags = 0;
1838
1839 // Since we have proxy, should try to establish tunnel.
1840 MockWrite data_writes1[] = {
1841 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
[email protected]e44de5d2009-06-05 20:12:451842 "Host: www.google.com\r\n"
1843 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]f4e426b2008-11-05 00:24:491844 };
1845
[email protected]77848d12008-11-14 00:00:221846 // The proxy responds to the connect with a 404, using a persistent
[email protected]f4e426b2008-11-05 00:24:491847 // connection. Usually a proxy would return 501 (not implemented),
1848 // or 200 (tunnel established).
1849 MockRead data_reads1[] = {
1850 MockRead("HTTP/1.1 404 Not Found\r\n"),
1851 MockRead("Content-Length: 10\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:421852 MockRead(false, ERR_UNEXPECTED), // Should not be reached.
[email protected]f4e426b2008-11-05 00:24:491853 };
1854
[email protected]69b43fe2009-06-15 09:47:371855 StaticMockSocket data1(data_reads1, data_writes1);
[email protected]228ff742009-06-05 01:19:591856 session_deps.socket_factory.AddMockSocket(&data1);
[email protected]f4e426b2008-11-05 00:24:491857
1858 TestCompletionCallback callback1;
1859
[email protected]684970b2009-08-14 04:54:461860 int rv = trans->Start(&request, &callback1, NULL);
[email protected]1c773ea12009-04-28 19:58:421861 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f4e426b2008-11-05 00:24:491862
1863 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421864 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED, rv);
[email protected]f4e426b2008-11-05 00:24:491865
[email protected]1c773ea12009-04-28 19:58:421866 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]c744cf22009-02-27 07:28:081867 EXPECT_TRUE(response == NULL);
[email protected]f4e426b2008-11-05 00:24:491868
[email protected]b4404c02009-04-10 16:38:521869 // Empty the current queue. This is necessary because idle sockets are
1870 // added to the connection pool asynchronously with a PostTask.
1871 MessageLoop::current()->RunAllPending();
1872
[email protected]f4e426b2008-11-05 00:24:491873 // We now check to make sure the TCPClientSocket was not added back to
1874 // the pool.
[email protected]a937a06d2009-08-19 21:19:241875 EXPECT_EQ(0, session->tcp_socket_pool()->IdleSocketCount());
[email protected]f4e426b2008-11-05 00:24:491876 trans.reset();
[email protected]b4404c02009-04-10 16:38:521877 MessageLoop::current()->RunAllPending();
[email protected]f4e426b2008-11-05 00:24:491878 // Make sure that the socket didn't get recycled after calling the destructor.
[email protected]a937a06d2009-08-19 21:19:241879 EXPECT_EQ(0, session->tcp_socket_pool()->IdleSocketCount());
[email protected]f4e426b2008-11-05 00:24:491880}
[email protected]372d34a2008-11-05 21:30:511881
[email protected]1b157c02009-04-21 01:55:401882// Make sure that we recycle a socket after reading all of the response body.
1883TEST_F(HttpNetworkTransactionTest, RecycleSocket) {
[email protected]228ff742009-06-05 01:19:591884 SessionDependencies session_deps;
1885 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]1b157c02009-04-21 01:55:401886
[email protected]1c773ea12009-04-28 19:58:421887 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(
[email protected]228ff742009-06-05 01:19:591888 session.get(), &session_deps.socket_factory));
[email protected]1b157c02009-04-21 01:55:401889
[email protected]1c773ea12009-04-28 19:58:421890 HttpRequestInfo request;
[email protected]1b157c02009-04-21 01:55:401891 request.method = "GET";
1892 request.url = GURL("http://www.google.com/");
1893 request.load_flags = 0;
1894
1895 MockRead data_reads[] = {
1896 // A part of the response body is received with the response headers.
1897 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 11\r\n\r\nhel"),
1898 // The rest of the response body is received in two parts.
1899 MockRead("lo"),
1900 MockRead(" world"),
1901 MockRead("junk"), // Should not be read!!
[email protected]1c773ea12009-04-28 19:58:421902 MockRead(false, OK),
[email protected]1b157c02009-04-21 01:55:401903 };
1904
[email protected]69b43fe2009-06-15 09:47:371905 StaticMockSocket data(data_reads, NULL);
[email protected]228ff742009-06-05 01:19:591906 session_deps.socket_factory.AddMockSocket(&data);
[email protected]1b157c02009-04-21 01:55:401907
1908 TestCompletionCallback callback;
1909
[email protected]684970b2009-08-14 04:54:461910 int rv = trans->Start(&request, &callback, NULL);
[email protected]1c773ea12009-04-28 19:58:421911 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]1b157c02009-04-21 01:55:401912
1913 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421914 EXPECT_EQ(OK, rv);
[email protected]1b157c02009-04-21 01:55:401915
[email protected]1c773ea12009-04-28 19:58:421916 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]1b157c02009-04-21 01:55:401917 EXPECT_TRUE(response != NULL);
1918
1919 EXPECT_TRUE(response->headers != NULL);
1920 std::string status_line = response->headers->GetStatusLine();
1921 EXPECT_EQ("HTTP/1.1 200 OK", status_line);
1922
[email protected]a937a06d2009-08-19 21:19:241923 EXPECT_EQ(0, session->tcp_socket_pool()->IdleSocketCount());
[email protected]1b157c02009-04-21 01:55:401924
1925 std::string response_data;
1926 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:421927 EXPECT_EQ(OK, rv);
[email protected]1b157c02009-04-21 01:55:401928 EXPECT_EQ("hello world", response_data);
1929
1930 // Empty the current queue. This is necessary because idle sockets are
1931 // added to the connection pool asynchronously with a PostTask.
1932 MessageLoop::current()->RunAllPending();
1933
1934 // We now check to make sure the socket was added back to the pool.
[email protected]a937a06d2009-08-19 21:19:241935 EXPECT_EQ(1, session->tcp_socket_pool()->IdleSocketCount());
[email protected]1b157c02009-04-21 01:55:401936}
1937
[email protected]b4404c02009-04-10 16:38:521938// Make sure that we recycle a socket after a zero-length response.
1939// http://crbug.com/9880
1940TEST_F(HttpNetworkTransactionTest, RecycleSocketAfterZeroContentLength) {
[email protected]228ff742009-06-05 01:19:591941 SessionDependencies session_deps;
1942 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]b4404c02009-04-10 16:38:521943
[email protected]1c773ea12009-04-28 19:58:421944 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(
[email protected]228ff742009-06-05 01:19:591945 session.get(), &session_deps.socket_factory));
[email protected]b4404c02009-04-10 16:38:521946
[email protected]1c773ea12009-04-28 19:58:421947 HttpRequestInfo request;
[email protected]b4404c02009-04-10 16:38:521948 request.method = "GET";
1949 request.url = GURL("http://www.google.com/csi?v=3&s=web&action=&"
1950 "tran=undefined&ei=mAXcSeegAo-SMurloeUN&"
1951 "e=17259,18167,19592,19773,19981,20133,20173,20233&"
1952 "rt=prt.2642,ol.2649,xjs.2951");
1953 request.load_flags = 0;
1954
1955 MockRead data_reads[] = {
1956 MockRead("HTTP/1.1 204 No Content\r\n"
1957 "Content-Length: 0\r\n"
1958 "Content-Type: text/html\r\n\r\n"),
1959 MockRead("junk"), // Should not be read!!
[email protected]1c773ea12009-04-28 19:58:421960 MockRead(false, OK),
[email protected]b4404c02009-04-10 16:38:521961 };
1962
[email protected]69b43fe2009-06-15 09:47:371963 StaticMockSocket data(data_reads, NULL);
[email protected]228ff742009-06-05 01:19:591964 session_deps.socket_factory.AddMockSocket(&data);
[email protected]b4404c02009-04-10 16:38:521965
1966 TestCompletionCallback callback;
1967
[email protected]684970b2009-08-14 04:54:461968 int rv = trans->Start(&request, &callback, NULL);
[email protected]1c773ea12009-04-28 19:58:421969 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]b4404c02009-04-10 16:38:521970
1971 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421972 EXPECT_EQ(OK, rv);
[email protected]b4404c02009-04-10 16:38:521973
[email protected]1c773ea12009-04-28 19:58:421974 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]b4404c02009-04-10 16:38:521975 EXPECT_TRUE(response != NULL);
1976
1977 EXPECT_TRUE(response->headers != NULL);
1978 std::string status_line = response->headers->GetStatusLine();
1979 EXPECT_EQ("HTTP/1.1 204 No Content", status_line);
1980
[email protected]a937a06d2009-08-19 21:19:241981 EXPECT_EQ(0, session->tcp_socket_pool()->IdleSocketCount());
[email protected]b4404c02009-04-10 16:38:521982
1983 std::string response_data;
1984 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:421985 EXPECT_EQ(OK, rv);
[email protected]b4404c02009-04-10 16:38:521986 EXPECT_EQ("", response_data);
1987
1988 // Empty the current queue. This is necessary because idle sockets are
1989 // added to the connection pool asynchronously with a PostTask.
1990 MessageLoop::current()->RunAllPending();
1991
1992 // We now check to make sure the socket was added back to the pool.
[email protected]a937a06d2009-08-19 21:19:241993 EXPECT_EQ(1, session->tcp_socket_pool()->IdleSocketCount());
[email protected]b4404c02009-04-10 16:38:521994}
1995
[email protected]372d34a2008-11-05 21:30:511996TEST_F(HttpNetworkTransactionTest, ResendRequestOnWriteBodyError) {
[email protected]1c773ea12009-04-28 19:58:421997 HttpRequestInfo request[2];
[email protected]372d34a2008-11-05 21:30:511998 // Transaction 1: a GET request that succeeds. The socket is recycled
1999 // after use.
2000 request[0].method = "GET";
2001 request[0].url = GURL("http://www.google.com/");
2002 request[0].load_flags = 0;
2003 // Transaction 2: a POST request. Reuses the socket kept alive from
2004 // transaction 1. The first attempts fails when writing the POST data.
2005 // This causes the transaction to retry with a new socket. The second
2006 // attempt succeeds.
2007 request[1].method = "POST";
2008 request[1].url = GURL("http://www.google.com/login.cgi");
[email protected]1c773ea12009-04-28 19:58:422009 request[1].upload_data = new UploadData;
[email protected]372d34a2008-11-05 21:30:512010 request[1].upload_data->AppendBytes("foo", 3);
2011 request[1].load_flags = 0;
2012
[email protected]228ff742009-06-05 01:19:592013 SessionDependencies session_deps;
2014 scoped_refptr<HttpNetworkSession> session = CreateSession(&session_deps);
[email protected]372d34a2008-11-05 21:30:512015
2016 // The first socket is used for transaction 1 and the first attempt of
2017 // transaction 2.
2018
2019 // The response of transaction 1.
2020 MockRead data_reads1[] = {
2021 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 11\r\n\r\n"),
2022 MockRead("hello world"),
[email protected]1c773ea12009-04-28 19:58:422023 MockRead(false, OK),
[email protected]372d34a2008-11-05 21:30:512024 };
2025 // The mock write results of transaction 1 and the first attempt of
2026 // transaction 2.
2027 MockWrite data_writes1[] = {
2028 MockWrite(false, 64), // GET
2029 MockWrite(false, 93), // POST
[email protected]1c773ea12009-04-28 19:58:422030 MockWrite(false, ERR_CONNECTION_ABORTED), // POST data
[email protected]372d34a2008-11-05 21:30:512031 };
[email protected]69b43fe2009-06-15 09:47:372032 StaticMockSocket data1(data_reads1, data_writes1);
[email protected]372d34a2008-11-05 21:30:512033
2034 // The second socket is used for the second attempt of transaction 2.
2035
2036 // The response of transaction 2.
2037 MockRead data_reads2[] = {
2038 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 7\r\n\r\n"),
2039 MockRead("welcome"),
[email protected]1c773ea12009-04-28 19:58:422040 MockRead(false, OK),
[email protected]372d34a2008-11-05 21:30:512041 };
2042 // The mock write results of the second attempt of transaction 2.
2043 MockWrite data_writes2[] = {
2044 MockWrite(false, 93), // POST
2045 MockWrite(false, 3), // POST data
2046 };
[email protected]69b43fe2009-06-15 09:47:372047 StaticMockSocket data2(data_reads2, data_writes2);
[email protected]372d34a2008-11-05 21:30:512048
[email protected]228ff742009-06-05 01:19:592049 session_deps.socket_factory.AddMockSocket(&data1);
2050 session_deps.socket_factory.AddMockSocket(&data2);
[email protected]372d34a2008-11-05 21:30:512051
2052 const char* kExpectedResponseData[] = {
2053 "hello world", "welcome"
2054 };
2055
2056 for (int i = 0; i < 2; ++i) {
[email protected]1c773ea12009-04-28 19:58:422057 scoped_ptr<HttpTransaction> trans(
[email protected]228ff742009-06-05 01:19:592058 new HttpNetworkTransaction(session, &session_deps.socket_factory));
[email protected]372d34a2008-11-05 21:30:512059
2060 TestCompletionCallback callback;
2061
[email protected]684970b2009-08-14 04:54:462062 int rv = trans->Start(&request[i], &callback, NULL);
[email protected]1c773ea12009-04-28 19:58:422063 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]372d34a2008-11-05 21:30:512064
2065 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422066 EXPECT_EQ(OK, rv);
[email protected]372d34a2008-11-05 21:30:512067
[email protected]1c773ea12009-04-28 19:58:422068 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]372d34a2008-11-05 21:30:512069 EXPECT_TRUE(response != NULL);
2070
2071 EXPECT_TRUE(response->headers != NULL);
2072 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
2073
2074 std::string response_data;
2075 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:422076 EXPECT_EQ(OK, rv);
[email protected]372d34a2008-11-05 21:30:512077 EXPECT_EQ(kExpectedResponseData[i], response_data);
2078 }
2079}
[email protected]f9ee6b52008-11-08 06:46:232080
2081// Test the request-challenge-retry sequence for basic auth when there is
2082// an identity in the URL. The request should be sent as normal, but when
2083// it fails the identity from the URL is used to answer the challenge.
2084TEST_F(HttpNetworkTransactionTest, AuthIdentityInUrl) {
[email protected]228ff742009-06-05 01:19:592085 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:402086 scoped_ptr<HttpTransaction> trans(
2087 new HttpNetworkTransaction(
[email protected]228ff742009-06-05 01:19:592088 CreateSession(&session_deps),
2089 &session_deps.socket_factory));
[email protected]f9ee6b52008-11-08 06:46:232090
[email protected]1c773ea12009-04-28 19:58:422091 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:232092 request.method = "GET";
2093 // Note: the URL has a username:password in it.
[email protected]a97cca42009-08-14 01:00:292094 request.url = GURL("http://foo:b@[email protected]/");
2095
2096 // The password contains an escaped character -- for this test to pass it
2097 // will need to be unescaped by HttpNetworkTransaction.
2098 EXPECT_EQ("b%40r", request.url.password());
2099
[email protected]f9ee6b52008-11-08 06:46:232100 request.load_flags = 0;
2101
2102 MockWrite data_writes1[] = {
2103 MockWrite("GET / HTTP/1.1\r\n"
2104 "Host: www.google.com\r\n"
2105 "Connection: keep-alive\r\n\r\n"),
2106 };
2107
2108 MockRead data_reads1[] = {
2109 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
2110 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2111 MockRead("Content-Length: 10\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422112 MockRead(false, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:232113 };
2114
2115 // After the challenge above, the transaction will be restarted using the
2116 // identity from the url (foo, bar) to answer the challenge.
2117 MockWrite data_writes2[] = {
2118 MockWrite("GET / HTTP/1.1\r\n"
2119 "Host: www.google.com\r\n"
2120 "Connection: keep-alive\r\n"
[email protected]a97cca42009-08-14 01:00:292121 "Authorization: Basic Zm9vOmJAcg==\r\n\r\n"),
[email protected]f9ee6b52008-11-08 06:46:232122 };
2123
2124 MockRead data_reads2[] = {
2125 MockRead("HTTP/1.0 200 OK\r\n"),
2126 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422127 MockRead(false, OK),
[email protected]f9ee6b52008-11-08 06:46:232128 };
2129
[email protected]69b43fe2009-06-15 09:47:372130 StaticMockSocket data1(data_reads1, data_writes1);
2131 StaticMockSocket data2(data_reads2, data_writes2);
[email protected]228ff742009-06-05 01:19:592132 session_deps.socket_factory.AddMockSocket(&data1);
2133 session_deps.socket_factory.AddMockSocket(&data2);
[email protected]f9ee6b52008-11-08 06:46:232134
2135 TestCompletionCallback callback1;
2136
[email protected]684970b2009-08-14 04:54:462137 int rv = trans->Start(&request, &callback1, NULL);
[email protected]1c773ea12009-04-28 19:58:422138 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:232139
2140 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422141 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:232142
[email protected]0757e7702009-03-27 04:00:222143 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
2144 TestCompletionCallback callback2;
2145 rv = trans->RestartWithAuth(std::wstring(), std::wstring(), &callback2);
[email protected]1c773ea12009-04-28 19:58:422146 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]0757e7702009-03-27 04:00:222147 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422148 EXPECT_EQ(OK, rv);
[email protected]0757e7702009-03-27 04:00:222149 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
2150
[email protected]1c773ea12009-04-28 19:58:422151 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]f9ee6b52008-11-08 06:46:232152 EXPECT_FALSE(response == NULL);
2153
2154 // There is no challenge info, since the identity in URL worked.
2155 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2156
2157 EXPECT_EQ(100, response->headers->GetContentLength());
2158
2159 // Empty the current queue.
2160 MessageLoop::current()->RunAllPending();
2161}
2162
2163// Test that previously tried username/passwords for a realm get re-used.
2164TEST_F(HttpNetworkTransactionTest, BasicAuthCacheAndPreauth) {
[email protected]228ff742009-06-05 01:19:592165 SessionDependencies session_deps;
2166 scoped_refptr<HttpNetworkSession> session = CreateSession(&session_deps);
[email protected]f9ee6b52008-11-08 06:46:232167
2168 // Transaction 1: authenticate (foo, bar) on MyRealm1
2169 {
[email protected]1c773ea12009-04-28 19:58:422170 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(
[email protected]228ff742009-06-05 01:19:592171 session, &session_deps.socket_factory));
[email protected]f9ee6b52008-11-08 06:46:232172
[email protected]1c773ea12009-04-28 19:58:422173 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:232174 request.method = "GET";
2175 request.url = GURL("http://www.google.com/x/y/z");
2176 request.load_flags = 0;
2177
2178 MockWrite data_writes1[] = {
2179 MockWrite("GET /x/y/z HTTP/1.1\r\n"
2180 "Host: www.google.com\r\n"
2181 "Connection: keep-alive\r\n\r\n"),
2182 };
2183
2184 MockRead data_reads1[] = {
2185 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
2186 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2187 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422188 MockRead(false, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:232189 };
2190
2191 // Resend with authorization (username=foo, password=bar)
2192 MockWrite data_writes2[] = {
2193 MockWrite("GET /x/y/z HTTP/1.1\r\n"
2194 "Host: www.google.com\r\n"
2195 "Connection: keep-alive\r\n"
2196 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2197 };
2198
2199 // Sever accepts the authorization.
2200 MockRead data_reads2[] = {
2201 MockRead("HTTP/1.0 200 OK\r\n"),
2202 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422203 MockRead(false, OK),
[email protected]f9ee6b52008-11-08 06:46:232204 };
2205
[email protected]69b43fe2009-06-15 09:47:372206 StaticMockSocket data1(data_reads1, data_writes1);
2207 StaticMockSocket data2(data_reads2, data_writes2);
[email protected]228ff742009-06-05 01:19:592208 session_deps.socket_factory.AddMockSocket(&data1);
2209 session_deps.socket_factory.AddMockSocket(&data2);
[email protected]f9ee6b52008-11-08 06:46:232210
2211 TestCompletionCallback callback1;
2212
[email protected]684970b2009-08-14 04:54:462213 int rv = trans->Start(&request, &callback1, NULL);
[email protected]1c773ea12009-04-28 19:58:422214 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:232215
2216 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422217 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:232218
[email protected]1c773ea12009-04-28 19:58:422219 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]f9ee6b52008-11-08 06:46:232220 EXPECT_FALSE(response == NULL);
2221
2222 // The password prompt info should have been set in
2223 // response->auth_challenge.
2224 EXPECT_FALSE(response->auth_challenge.get() == NULL);
2225
[email protected]71e4573a2009-05-21 22:03:002226 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
[email protected]f9ee6b52008-11-08 06:46:232227 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
2228 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
2229
2230 TestCompletionCallback callback2;
2231
2232 rv = trans->RestartWithAuth(L"foo", L"bar", &callback2);
[email protected]1c773ea12009-04-28 19:58:422233 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:232234
2235 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422236 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:232237
2238 response = trans->GetResponseInfo();
2239 EXPECT_FALSE(response == NULL);
2240 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2241 EXPECT_EQ(100, response->headers->GetContentLength());
2242 }
2243
2244 // ------------------------------------------------------------------------
2245
2246 // Transaction 2: authenticate (foo2, bar2) on MyRealm2
2247 {
[email protected]1c773ea12009-04-28 19:58:422248 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(
[email protected]228ff742009-06-05 01:19:592249 session, &session_deps.socket_factory));
[email protected]f9ee6b52008-11-08 06:46:232250
[email protected]1c773ea12009-04-28 19:58:422251 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:232252 request.method = "GET";
2253 // Note that Transaction 1 was at /x/y/z, so this is in the same
2254 // protection space as MyRealm1.
2255 request.url = GURL("http://www.google.com/x/y/a/b");
2256 request.load_flags = 0;
2257
2258 MockWrite data_writes1[] = {
2259 MockWrite("GET /x/y/a/b HTTP/1.1\r\n"
2260 "Host: www.google.com\r\n"
2261 "Connection: keep-alive\r\n"
2262 // Send preemptive authorization for MyRealm1
2263 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2264 };
2265
2266 // The server didn't like the preemptive authorization, and
2267 // challenges us for a different realm (MyRealm2).
2268 MockRead data_reads1[] = {
2269 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
2270 MockRead("WWW-Authenticate: Basic realm=\"MyRealm2\"\r\n"),
2271 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422272 MockRead(false, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:232273 };
2274
2275 // Resend with authorization for MyRealm2 (username=foo2, password=bar2)
2276 MockWrite data_writes2[] = {
2277 MockWrite("GET /x/y/a/b HTTP/1.1\r\n"
2278 "Host: www.google.com\r\n"
2279 "Connection: keep-alive\r\n"
2280 "Authorization: Basic Zm9vMjpiYXIy\r\n\r\n"),
2281 };
2282
2283 // Sever accepts the authorization.
2284 MockRead data_reads2[] = {
2285 MockRead("HTTP/1.0 200 OK\r\n"),
2286 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422287 MockRead(false, OK),
[email protected]f9ee6b52008-11-08 06:46:232288 };
2289
[email protected]69b43fe2009-06-15 09:47:372290 StaticMockSocket data1(data_reads1, data_writes1);
2291 StaticMockSocket data2(data_reads2, data_writes2);
[email protected]228ff742009-06-05 01:19:592292 session_deps.socket_factory.AddMockSocket(&data1);
2293 session_deps.socket_factory.AddMockSocket(&data2);
[email protected]f9ee6b52008-11-08 06:46:232294
2295 TestCompletionCallback callback1;
2296
[email protected]684970b2009-08-14 04:54:462297 int rv = trans->Start(&request, &callback1, NULL);
[email protected]1c773ea12009-04-28 19:58:422298 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:232299
2300 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422301 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:232302
[email protected]1c773ea12009-04-28 19:58:422303 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]f9ee6b52008-11-08 06:46:232304 EXPECT_FALSE(response == NULL);
2305
2306 // The password prompt info should have been set in
2307 // response->auth_challenge.
2308 EXPECT_FALSE(response->auth_challenge.get() == NULL);
2309
[email protected]71e4573a2009-05-21 22:03:002310 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
[email protected]f9ee6b52008-11-08 06:46:232311 EXPECT_EQ(L"MyRealm2", response->auth_challenge->realm);
2312 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
2313
2314 TestCompletionCallback callback2;
2315
2316 rv = trans->RestartWithAuth(L"foo2", L"bar2", &callback2);
[email protected]1c773ea12009-04-28 19:58:422317 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:232318
2319 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422320 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:232321
2322 response = trans->GetResponseInfo();
2323 EXPECT_FALSE(response == NULL);
2324 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2325 EXPECT_EQ(100, response->headers->GetContentLength());
2326 }
2327
2328 // ------------------------------------------------------------------------
2329
2330 // Transaction 3: Resend a request in MyRealm's protection space --
2331 // succeed with preemptive authorization.
2332 {
[email protected]1c773ea12009-04-28 19:58:422333 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(
[email protected]228ff742009-06-05 01:19:592334 session, &session_deps.socket_factory));
[email protected]f9ee6b52008-11-08 06:46:232335
[email protected]1c773ea12009-04-28 19:58:422336 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:232337 request.method = "GET";
2338 request.url = GURL("http://www.google.com/x/y/z2");
2339 request.load_flags = 0;
2340
2341 MockWrite data_writes1[] = {
2342 MockWrite("GET /x/y/z2 HTTP/1.1\r\n"
2343 "Host: www.google.com\r\n"
2344 "Connection: keep-alive\r\n"
2345 // The authorization for MyRealm1 gets sent preemptively
2346 // (since the url is in the same protection space)
2347 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2348 };
2349
2350 // Sever accepts the preemptive authorization
2351 MockRead data_reads1[] = {
2352 MockRead("HTTP/1.0 200 OK\r\n"),
2353 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422354 MockRead(false, OK),
[email protected]f9ee6b52008-11-08 06:46:232355 };
2356
[email protected]69b43fe2009-06-15 09:47:372357 StaticMockSocket data1(data_reads1, data_writes1);
[email protected]228ff742009-06-05 01:19:592358 session_deps.socket_factory.AddMockSocket(&data1);
[email protected]f9ee6b52008-11-08 06:46:232359
2360 TestCompletionCallback callback1;
2361
[email protected]684970b2009-08-14 04:54:462362 int rv = trans->Start(&request, &callback1, NULL);
[email protected]1c773ea12009-04-28 19:58:422363 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:232364
2365 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422366 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:232367
[email protected]1c773ea12009-04-28 19:58:422368 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]f9ee6b52008-11-08 06:46:232369 EXPECT_FALSE(response == NULL);
2370
2371 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2372 EXPECT_EQ(100, response->headers->GetContentLength());
2373 }
2374
2375 // ------------------------------------------------------------------------
2376
2377 // Transaction 4: request another URL in MyRealm (however the
2378 // url is not known to belong to the protection space, so no pre-auth).
2379 {
[email protected]1c773ea12009-04-28 19:58:422380 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(
[email protected]228ff742009-06-05 01:19:592381 session, &session_deps.socket_factory));
[email protected]f9ee6b52008-11-08 06:46:232382
[email protected]1c773ea12009-04-28 19:58:422383 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:232384 request.method = "GET";
2385 request.url = GURL("http://www.google.com/x/1");
2386 request.load_flags = 0;
2387
2388 MockWrite data_writes1[] = {
2389 MockWrite("GET /x/1 HTTP/1.1\r\n"
2390 "Host: www.google.com\r\n"
2391 "Connection: keep-alive\r\n\r\n"),
2392 };
2393
2394 MockRead data_reads1[] = {
2395 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
2396 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2397 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422398 MockRead(false, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:232399 };
2400
2401 // Resend with authorization from MyRealm's cache.
2402 MockWrite data_writes2[] = {
2403 MockWrite("GET /x/1 HTTP/1.1\r\n"
2404 "Host: www.google.com\r\n"
2405 "Connection: keep-alive\r\n"
2406 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2407 };
2408
2409 // Sever accepts the authorization.
2410 MockRead data_reads2[] = {
2411 MockRead("HTTP/1.0 200 OK\r\n"),
2412 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422413 MockRead(false, OK),
[email protected]f9ee6b52008-11-08 06:46:232414 };
2415
[email protected]69b43fe2009-06-15 09:47:372416 StaticMockSocket data1(data_reads1, data_writes1);
2417 StaticMockSocket data2(data_reads2, data_writes2);
[email protected]228ff742009-06-05 01:19:592418 session_deps.socket_factory.AddMockSocket(&data1);
2419 session_deps.socket_factory.AddMockSocket(&data2);
[email protected]f9ee6b52008-11-08 06:46:232420
2421 TestCompletionCallback callback1;
2422
[email protected]684970b2009-08-14 04:54:462423 int rv = trans->Start(&request, &callback1, NULL);
[email protected]1c773ea12009-04-28 19:58:422424 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:232425
2426 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422427 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:232428
[email protected]0757e7702009-03-27 04:00:222429 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
2430 TestCompletionCallback callback2;
2431 rv = trans->RestartWithAuth(std::wstring(), std::wstring(), &callback2);
[email protected]1c773ea12009-04-28 19:58:422432 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]0757e7702009-03-27 04:00:222433 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422434 EXPECT_EQ(OK, rv);
[email protected]0757e7702009-03-27 04:00:222435 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
2436
[email protected]1c773ea12009-04-28 19:58:422437 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]f9ee6b52008-11-08 06:46:232438 EXPECT_FALSE(response == NULL);
2439 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2440 EXPECT_EQ(100, response->headers->GetContentLength());
2441 }
2442
2443 // ------------------------------------------------------------------------
2444
2445 // Transaction 5: request a URL in MyRealm, but the server rejects the
2446 // cached identity. Should invalidate and re-prompt.
2447 {
[email protected]1c773ea12009-04-28 19:58:422448 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(
[email protected]228ff742009-06-05 01:19:592449 session, &session_deps.socket_factory));
[email protected]f9ee6b52008-11-08 06:46:232450
[email protected]1c773ea12009-04-28 19:58:422451 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:232452 request.method = "GET";
2453 request.url = GURL("http://www.google.com/p/q/t");
2454 request.load_flags = 0;
2455
2456 MockWrite data_writes1[] = {
2457 MockWrite("GET /p/q/t HTTP/1.1\r\n"
2458 "Host: www.google.com\r\n"
2459 "Connection: keep-alive\r\n\r\n"),
2460 };
2461
2462 MockRead data_reads1[] = {
2463 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
2464 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2465 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422466 MockRead(false, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:232467 };
2468
2469 // Resend with authorization from cache for MyRealm.
2470 MockWrite data_writes2[] = {
2471 MockWrite("GET /p/q/t HTTP/1.1\r\n"
2472 "Host: www.google.com\r\n"
2473 "Connection: keep-alive\r\n"
2474 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2475 };
2476
2477 // Sever rejects the authorization.
2478 MockRead data_reads2[] = {
2479 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
2480 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2481 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422482 MockRead(false, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:232483 };
2484
2485 // At this point we should prompt for new credentials for MyRealm.
2486 // Restart with username=foo3, password=foo4.
2487 MockWrite data_writes3[] = {
2488 MockWrite("GET /p/q/t HTTP/1.1\r\n"
2489 "Host: www.google.com\r\n"
2490 "Connection: keep-alive\r\n"
2491 "Authorization: Basic Zm9vMzpiYXIz\r\n\r\n"),
2492 };
2493
2494 // Sever accepts the authorization.
2495 MockRead data_reads3[] = {
2496 MockRead("HTTP/1.0 200 OK\r\n"),
2497 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422498 MockRead(false, OK),
[email protected]f9ee6b52008-11-08 06:46:232499 };
2500
[email protected]69b43fe2009-06-15 09:47:372501 StaticMockSocket data1(data_reads1, data_writes1);
2502 StaticMockSocket data2(data_reads2, data_writes2);
2503 StaticMockSocket data3(data_reads3, data_writes3);
[email protected]228ff742009-06-05 01:19:592504 session_deps.socket_factory.AddMockSocket(&data1);
2505 session_deps.socket_factory.AddMockSocket(&data2);
2506 session_deps.socket_factory.AddMockSocket(&data3);
[email protected]f9ee6b52008-11-08 06:46:232507
2508 TestCompletionCallback callback1;
2509
[email protected]684970b2009-08-14 04:54:462510 int rv = trans->Start(&request, &callback1, NULL);
[email protected]1c773ea12009-04-28 19:58:422511 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:232512
2513 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422514 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:232515
[email protected]0757e7702009-03-27 04:00:222516 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
2517 TestCompletionCallback callback2;
2518 rv = trans->RestartWithAuth(std::wstring(), std::wstring(), &callback2);
[email protected]1c773ea12009-04-28 19:58:422519 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]0757e7702009-03-27 04:00:222520 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422521 EXPECT_EQ(OK, rv);
[email protected]0757e7702009-03-27 04:00:222522 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
2523
[email protected]1c773ea12009-04-28 19:58:422524 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]f9ee6b52008-11-08 06:46:232525 EXPECT_FALSE(response == NULL);
2526
2527 // The password prompt info should have been set in
2528 // response->auth_challenge.
2529 EXPECT_FALSE(response->auth_challenge.get() == NULL);
2530
[email protected]71e4573a2009-05-21 22:03:002531 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
[email protected]f9ee6b52008-11-08 06:46:232532 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
2533 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
2534
[email protected]0757e7702009-03-27 04:00:222535 TestCompletionCallback callback3;
[email protected]f9ee6b52008-11-08 06:46:232536
[email protected]0757e7702009-03-27 04:00:222537 rv = trans->RestartWithAuth(L"foo3", L"bar3", &callback3);
[email protected]1c773ea12009-04-28 19:58:422538 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:232539
[email protected]0757e7702009-03-27 04:00:222540 rv = callback3.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422541 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:232542
2543 response = trans->GetResponseInfo();
2544 EXPECT_FALSE(response == NULL);
2545 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2546 EXPECT_EQ(100, response->headers->GetContentLength());
2547 }
2548}
[email protected]89ceba9a2009-03-21 03:46:062549
2550// Test the ResetStateForRestart() private method.
2551TEST_F(HttpNetworkTransactionTest, ResetStateForRestart) {
2552 // Create a transaction (the dependencies aren't important).
[email protected]228ff742009-06-05 01:19:592553 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:402554 scoped_ptr<HttpNetworkTransaction> trans(
2555 new HttpNetworkTransaction(
[email protected]228ff742009-06-05 01:19:592556 CreateSession(&session_deps),
2557 &session_deps.socket_factory));
[email protected]89ceba9a2009-03-21 03:46:062558
2559 // Setup some state (which we expect ResetStateForRestart() will clear).
[email protected]ffeb0882009-04-30 21:51:252560 trans->header_buf_->Realloc(10);
[email protected]89ceba9a2009-03-21 03:46:062561 trans->header_buf_capacity_ = 10;
2562 trans->header_buf_len_ = 3;
2563 trans->header_buf_body_offset_ = 11;
2564 trans->header_buf_http_offset_ = 0;
2565 trans->response_body_length_ = 100;
2566 trans->response_body_read_ = 1;
2567 trans->read_buf_ = new IOBuffer(15);
2568 trans->read_buf_len_ = 15;
[email protected]ffeb0882009-04-30 21:51:252569 trans->request_headers_->headers_ = "Authorization: NTLM";
[email protected]89ceba9a2009-03-21 03:46:062570 trans->request_headers_bytes_sent_ = 3;
2571
2572 // Setup state in response_
2573 trans->response_.auth_challenge = new AuthChallengeInfo();
2574 trans->response_.ssl_info.cert_status = -15;
2575 trans->response_.response_time = base::Time::Now();
[email protected]b4404c02009-04-10 16:38:522576 trans->response_.was_cached = true; // (Wouldn't ever actually be true...)
[email protected]89ceba9a2009-03-21 03:46:062577
2578 { // Setup state for response_.vary_data
2579 HttpRequestInfo request;
2580 std::string temp("HTTP/1.1 200 OK\nVary: foo, bar\n\n");
2581 std::replace(temp.begin(), temp.end(), '\n', '\0');
2582 scoped_refptr<HttpResponseHeaders> response = new HttpResponseHeaders(temp);
2583 request.extra_headers = "Foo: 1\nbar: 23";
2584 EXPECT_TRUE(trans->response_.vary_data.Init(request, *response));
2585 }
2586
2587 // Cause the above state to be reset.
2588 trans->ResetStateForRestart();
2589
2590 // Verify that the state that needed to be reset, has been reset.
[email protected]ffeb0882009-04-30 21:51:252591 EXPECT_EQ(NULL, trans->header_buf_->headers());
[email protected]89ceba9a2009-03-21 03:46:062592 EXPECT_EQ(0, trans->header_buf_capacity_);
2593 EXPECT_EQ(0, trans->header_buf_len_);
2594 EXPECT_EQ(-1, trans->header_buf_body_offset_);
2595 EXPECT_EQ(-1, trans->header_buf_http_offset_);
2596 EXPECT_EQ(-1, trans->response_body_length_);
2597 EXPECT_EQ(0, trans->response_body_read_);
2598 EXPECT_EQ(NULL, trans->read_buf_.get());
2599 EXPECT_EQ(0, trans->read_buf_len_);
[email protected]ffeb0882009-04-30 21:51:252600 EXPECT_EQ("", trans->request_headers_->headers_);
[email protected]89ceba9a2009-03-21 03:46:062601 EXPECT_EQ(0U, trans->request_headers_bytes_sent_);
2602 EXPECT_EQ(NULL, trans->response_.auth_challenge.get());
2603 EXPECT_EQ(NULL, trans->response_.headers.get());
2604 EXPECT_EQ(false, trans->response_.was_cached);
[email protected]89ceba9a2009-03-21 03:46:062605 EXPECT_EQ(0, trans->response_.ssl_info.cert_status);
2606 EXPECT_FALSE(trans->response_.vary_data.is_valid());
2607}
2608
[email protected]bacff652009-03-31 17:50:332609// Test HTTPS connections to a site with a bad certificate
2610TEST_F(HttpNetworkTransactionTest, HTTPSBadCertificate) {
[email protected]228ff742009-06-05 01:19:592611 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:402612 scoped_ptr<HttpTransaction> trans(
2613 new HttpNetworkTransaction(
[email protected]228ff742009-06-05 01:19:592614 CreateSession(&session_deps),
2615 &session_deps.socket_factory));
[email protected]bacff652009-03-31 17:50:332616
2617 HttpRequestInfo request;
2618 request.method = "GET";
2619 request.url = GURL("https://www.google.com/");
2620 request.load_flags = 0;
2621
2622 MockWrite data_writes[] = {
2623 MockWrite("GET / HTTP/1.1\r\n"
2624 "Host: www.google.com\r\n"
2625 "Connection: keep-alive\r\n\r\n"),
2626 };
2627
2628 MockRead data_reads[] = {
2629 MockRead("HTTP/1.0 200 OK\r\n"),
2630 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2631 MockRead("Content-Length: 100\r\n\r\n"),
2632 MockRead(false, OK),
2633 };
2634
[email protected]69b43fe2009-06-15 09:47:372635 StaticMockSocket ssl_bad_certificate;
2636 StaticMockSocket data(data_reads, data_writes);
[email protected]bacff652009-03-31 17:50:332637 MockSSLSocket ssl_bad(true, ERR_CERT_AUTHORITY_INVALID);
2638 MockSSLSocket ssl(true, OK);
2639
[email protected]228ff742009-06-05 01:19:592640 session_deps.socket_factory.AddMockSocket(&ssl_bad_certificate);
2641 session_deps.socket_factory.AddMockSocket(&data);
2642 session_deps.socket_factory.AddMockSSLSocket(&ssl_bad);
2643 session_deps.socket_factory.AddMockSSLSocket(&ssl);
[email protected]bacff652009-03-31 17:50:332644
2645 TestCompletionCallback callback;
2646
[email protected]684970b2009-08-14 04:54:462647 int rv = trans->Start(&request, &callback, NULL);
[email protected]bacff652009-03-31 17:50:332648 EXPECT_EQ(ERR_IO_PENDING, rv);
2649
2650 rv = callback.WaitForResult();
2651 EXPECT_EQ(ERR_CERT_AUTHORITY_INVALID, rv);
2652
2653 rv = trans->RestartIgnoringLastError(&callback);
2654 EXPECT_EQ(ERR_IO_PENDING, rv);
2655
2656 rv = callback.WaitForResult();
2657 EXPECT_EQ(OK, rv);
2658
2659 const HttpResponseInfo* response = trans->GetResponseInfo();
2660
2661 EXPECT_FALSE(response == NULL);
2662 EXPECT_EQ(100, response->headers->GetContentLength());
2663}
2664
2665// Test HTTPS connections to a site with a bad certificate, going through a
2666// proxy
2667TEST_F(HttpNetworkTransactionTest, HTTPSBadCertificateViaProxy) {
[email protected]228ff742009-06-05 01:19:592668 SessionDependencies session_deps(CreateFixedProxyService("myproxy:70"));
[email protected]bacff652009-03-31 17:50:332669
2670 HttpRequestInfo request;
2671 request.method = "GET";
2672 request.url = GURL("https://www.google.com/");
2673 request.load_flags = 0;
2674
2675 MockWrite proxy_writes[] = {
2676 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
[email protected]e44de5d2009-06-05 20:12:452677 "Host: www.google.com\r\n"
2678 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]bacff652009-03-31 17:50:332679 };
2680
2681 MockRead proxy_reads[] = {
2682 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422683 MockRead(false, OK)
[email protected]bacff652009-03-31 17:50:332684 };
2685
2686 MockWrite data_writes[] = {
2687 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
[email protected]e44de5d2009-06-05 20:12:452688 "Host: www.google.com\r\n"
2689 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]bacff652009-03-31 17:50:332690 MockWrite("GET / HTTP/1.1\r\n"
2691 "Host: www.google.com\r\n"
2692 "Connection: keep-alive\r\n\r\n"),
2693 };
2694
2695 MockRead data_reads[] = {
2696 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
2697 MockRead("HTTP/1.0 200 OK\r\n"),
2698 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2699 MockRead("Content-Length: 100\r\n\r\n"),
2700 MockRead(false, OK),
2701 };
2702
[email protected]69b43fe2009-06-15 09:47:372703 StaticMockSocket ssl_bad_certificate(proxy_reads, proxy_writes);
2704 StaticMockSocket data(data_reads, data_writes);
[email protected]bacff652009-03-31 17:50:332705 MockSSLSocket ssl_bad(true, ERR_CERT_AUTHORITY_INVALID);
2706 MockSSLSocket ssl(true, OK);
2707
[email protected]228ff742009-06-05 01:19:592708 session_deps.socket_factory.AddMockSocket(&ssl_bad_certificate);
2709 session_deps.socket_factory.AddMockSocket(&data);
2710 session_deps.socket_factory.AddMockSSLSocket(&ssl_bad);
2711 session_deps.socket_factory.AddMockSSLSocket(&ssl);
[email protected]bacff652009-03-31 17:50:332712
2713 TestCompletionCallback callback;
2714
2715 for (int i = 0; i < 2; i++) {
[email protected]228ff742009-06-05 01:19:592716 session_deps.socket_factory.ResetNextMockIndexes();
[email protected]bacff652009-03-31 17:50:332717
[email protected]d207a5f2009-06-04 05:28:402718 scoped_ptr<HttpTransaction> trans(
2719 new HttpNetworkTransaction(
[email protected]228ff742009-06-05 01:19:592720 CreateSession(&session_deps),
2721 &session_deps.socket_factory));
[email protected]bacff652009-03-31 17:50:332722
[email protected]684970b2009-08-14 04:54:462723 int rv = trans->Start(&request, &callback, NULL);
[email protected]bacff652009-03-31 17:50:332724 EXPECT_EQ(ERR_IO_PENDING, rv);
2725
2726 rv = callback.WaitForResult();
2727 EXPECT_EQ(ERR_CERT_AUTHORITY_INVALID, rv);
2728
2729 rv = trans->RestartIgnoringLastError(&callback);
2730 EXPECT_EQ(ERR_IO_PENDING, rv);
2731
2732 rv = callback.WaitForResult();
2733 EXPECT_EQ(OK, rv);
2734
2735 const HttpResponseInfo* response = trans->GetResponseInfo();
2736
2737 EXPECT_FALSE(response == NULL);
2738 EXPECT_EQ(100, response->headers->GetContentLength());
2739 }
2740}
2741
[email protected]1c773ea12009-04-28 19:58:422742TEST_F(HttpNetworkTransactionTest, BuildRequest_UserAgent) {
[email protected]228ff742009-06-05 01:19:592743 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:402744 scoped_ptr<HttpTransaction> trans(
2745 new HttpNetworkTransaction(
[email protected]228ff742009-06-05 01:19:592746 CreateSession(&session_deps),
2747 &session_deps.socket_factory));
[email protected]1c773ea12009-04-28 19:58:422748
2749 HttpRequestInfo request;
2750 request.method = "GET";
2751 request.url = GURL("http://www.google.com/");
2752 request.user_agent = "Chromium Ultra Awesome X Edition";
2753
2754 MockWrite data_writes[] = {
2755 MockWrite("GET / HTTP/1.1\r\n"
2756 "Host: www.google.com\r\n"
2757 "Connection: keep-alive\r\n"
2758 "User-Agent: Chromium Ultra Awesome X Edition\r\n\r\n"),
2759 };
2760
2761 // Lastly, the server responds with the actual content.
2762 MockRead data_reads[] = {
2763 MockRead("HTTP/1.0 200 OK\r\n"),
2764 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2765 MockRead("Content-Length: 100\r\n\r\n"),
2766 MockRead(false, OK),
2767 };
2768
[email protected]69b43fe2009-06-15 09:47:372769 StaticMockSocket data(data_reads, data_writes);
[email protected]228ff742009-06-05 01:19:592770 session_deps.socket_factory.AddMockSocket(&data);
[email protected]1c773ea12009-04-28 19:58:422771
2772 TestCompletionCallback callback;
2773
[email protected]684970b2009-08-14 04:54:462774 int rv = trans->Start(&request, &callback, NULL);
[email protected]1c773ea12009-04-28 19:58:422775 EXPECT_EQ(ERR_IO_PENDING, rv);
2776
2777 rv = callback.WaitForResult();
2778 EXPECT_EQ(OK, rv);
2779}
2780
2781TEST_F(HttpNetworkTransactionTest, BuildRequest_Referer) {
[email protected]228ff742009-06-05 01:19:592782 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:402783 scoped_ptr<HttpTransaction> trans(
2784 new HttpNetworkTransaction(
[email protected]228ff742009-06-05 01:19:592785 CreateSession(&session_deps),
2786 &session_deps.socket_factory));
[email protected]1c773ea12009-04-28 19:58:422787
2788 HttpRequestInfo request;
2789 request.method = "GET";
2790 request.url = GURL("http://www.google.com/");
2791 request.load_flags = 0;
2792 request.referrer = GURL("http://the.previous.site.com/");
2793
2794 MockWrite data_writes[] = {
2795 MockWrite("GET / HTTP/1.1\r\n"
2796 "Host: www.google.com\r\n"
2797 "Connection: keep-alive\r\n"
2798 "Referer: http://the.previous.site.com/\r\n\r\n"),
2799 };
2800
2801 // Lastly, the server responds with the actual content.
2802 MockRead data_reads[] = {
2803 MockRead("HTTP/1.0 200 OK\r\n"),
2804 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2805 MockRead("Content-Length: 100\r\n\r\n"),
2806 MockRead(false, OK),
2807 };
2808
[email protected]69b43fe2009-06-15 09:47:372809 StaticMockSocket data(data_reads, data_writes);
[email protected]228ff742009-06-05 01:19:592810 session_deps.socket_factory.AddMockSocket(&data);
[email protected]1c773ea12009-04-28 19:58:422811
2812 TestCompletionCallback callback;
2813
[email protected]684970b2009-08-14 04:54:462814 int rv = trans->Start(&request, &callback, NULL);
[email protected]1c773ea12009-04-28 19:58:422815 EXPECT_EQ(ERR_IO_PENDING, rv);
2816
2817 rv = callback.WaitForResult();
2818 EXPECT_EQ(OK, rv);
2819}
2820
2821TEST_F(HttpNetworkTransactionTest, BuildRequest_PostContentLengthZero) {
[email protected]228ff742009-06-05 01:19:592822 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:402823 scoped_ptr<HttpTransaction> trans(
2824 new HttpNetworkTransaction(
[email protected]228ff742009-06-05 01:19:592825 CreateSession(&session_deps),
2826 &session_deps.socket_factory));
[email protected]1c773ea12009-04-28 19:58:422827
2828 HttpRequestInfo request;
2829 request.method = "POST";
2830 request.url = GURL("http://www.google.com/");
2831
2832 MockWrite data_writes[] = {
2833 MockWrite("POST / HTTP/1.1\r\n"
2834 "Host: www.google.com\r\n"
2835 "Connection: keep-alive\r\n"
2836 "Content-Length: 0\r\n\r\n"),
2837 };
2838
2839 // Lastly, the server responds with the actual content.
2840 MockRead data_reads[] = {
2841 MockRead("HTTP/1.0 200 OK\r\n"),
2842 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2843 MockRead("Content-Length: 100\r\n\r\n"),
2844 MockRead(false, OK),
2845 };
2846
[email protected]69b43fe2009-06-15 09:47:372847 StaticMockSocket data(data_reads, data_writes);
[email protected]228ff742009-06-05 01:19:592848 session_deps.socket_factory.AddMockSocket(&data);
[email protected]1c773ea12009-04-28 19:58:422849
2850 TestCompletionCallback callback;
2851
[email protected]684970b2009-08-14 04:54:462852 int rv = trans->Start(&request, &callback, NULL);
[email protected]1c773ea12009-04-28 19:58:422853 EXPECT_EQ(ERR_IO_PENDING, rv);
2854
2855 rv = callback.WaitForResult();
2856 EXPECT_EQ(OK, rv);
2857}
2858
2859TEST_F(HttpNetworkTransactionTest, BuildRequest_PutContentLengthZero) {
[email protected]228ff742009-06-05 01:19:592860 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:402861 scoped_ptr<HttpTransaction> trans(
2862 new HttpNetworkTransaction(
[email protected]228ff742009-06-05 01:19:592863 CreateSession(&session_deps),
2864 &session_deps.socket_factory));
[email protected]1c773ea12009-04-28 19:58:422865
2866 HttpRequestInfo request;
2867 request.method = "PUT";
2868 request.url = GURL("http://www.google.com/");
2869
2870 MockWrite data_writes[] = {
2871 MockWrite("PUT / HTTP/1.1\r\n"
2872 "Host: www.google.com\r\n"
2873 "Connection: keep-alive\r\n"
2874 "Content-Length: 0\r\n\r\n"),
2875 };
2876
2877 // Lastly, the server responds with the actual content.
2878 MockRead data_reads[] = {
2879 MockRead("HTTP/1.0 200 OK\r\n"),
2880 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2881 MockRead("Content-Length: 100\r\n\r\n"),
2882 MockRead(false, OK),
2883 };
2884
[email protected]69b43fe2009-06-15 09:47:372885 StaticMockSocket data(data_reads, data_writes);
[email protected]228ff742009-06-05 01:19:592886 session_deps.socket_factory.AddMockSocket(&data);
[email protected]1c773ea12009-04-28 19:58:422887
2888 TestCompletionCallback callback;
2889
[email protected]684970b2009-08-14 04:54:462890 int rv = trans->Start(&request, &callback, NULL);
[email protected]1c773ea12009-04-28 19:58:422891 EXPECT_EQ(ERR_IO_PENDING, rv);
2892
2893 rv = callback.WaitForResult();
2894 EXPECT_EQ(OK, rv);
2895}
2896
2897TEST_F(HttpNetworkTransactionTest, BuildRequest_HeadContentLengthZero) {
[email protected]228ff742009-06-05 01:19:592898 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:402899 scoped_ptr<HttpTransaction> trans(
2900 new HttpNetworkTransaction(
[email protected]228ff742009-06-05 01:19:592901 CreateSession(&session_deps),
2902 &session_deps.socket_factory));
[email protected]1c773ea12009-04-28 19:58:422903
2904 HttpRequestInfo request;
2905 request.method = "HEAD";
2906 request.url = GURL("http://www.google.com/");
2907
2908 MockWrite data_writes[] = {
2909 MockWrite("HEAD / HTTP/1.1\r\n"
2910 "Host: www.google.com\r\n"
2911 "Connection: keep-alive\r\n"
2912 "Content-Length: 0\r\n\r\n"),
2913 };
2914
2915 // Lastly, the server responds with the actual content.
2916 MockRead data_reads[] = {
2917 MockRead("HTTP/1.0 200 OK\r\n"),
2918 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2919 MockRead("Content-Length: 100\r\n\r\n"),
2920 MockRead(false, OK),
2921 };
2922
[email protected]69b43fe2009-06-15 09:47:372923 StaticMockSocket data(data_reads, data_writes);
[email protected]228ff742009-06-05 01:19:592924 session_deps.socket_factory.AddMockSocket(&data);
[email protected]1c773ea12009-04-28 19:58:422925
2926 TestCompletionCallback callback;
2927
[email protected]684970b2009-08-14 04:54:462928 int rv = trans->Start(&request, &callback, NULL);
[email protected]1c773ea12009-04-28 19:58:422929 EXPECT_EQ(ERR_IO_PENDING, rv);
2930
2931 rv = callback.WaitForResult();
2932 EXPECT_EQ(OK, rv);
2933}
2934
2935TEST_F(HttpNetworkTransactionTest, BuildRequest_CacheControlNoCache) {
[email protected]228ff742009-06-05 01:19:592936 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:402937 scoped_ptr<HttpTransaction> trans(
2938 new HttpNetworkTransaction(
[email protected]228ff742009-06-05 01:19:592939 CreateSession(&session_deps),
2940 &session_deps.socket_factory));
[email protected]1c773ea12009-04-28 19:58:422941
2942 HttpRequestInfo request;
2943 request.method = "GET";
2944 request.url = GURL("http://www.google.com/");
2945 request.load_flags = LOAD_BYPASS_CACHE;
2946
2947 MockWrite data_writes[] = {
2948 MockWrite("GET / HTTP/1.1\r\n"
2949 "Host: www.google.com\r\n"
2950 "Connection: keep-alive\r\n"
2951 "Pragma: no-cache\r\n"
2952 "Cache-Control: no-cache\r\n\r\n"),
2953 };
2954
2955 // Lastly, the server responds with the actual content.
2956 MockRead data_reads[] = {
2957 MockRead("HTTP/1.0 200 OK\r\n"),
2958 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2959 MockRead("Content-Length: 100\r\n\r\n"),
2960 MockRead(false, OK),
2961 };
2962
[email protected]69b43fe2009-06-15 09:47:372963 StaticMockSocket data(data_reads, data_writes);
[email protected]228ff742009-06-05 01:19:592964 session_deps.socket_factory.AddMockSocket(&data);
[email protected]1c773ea12009-04-28 19:58:422965
2966 TestCompletionCallback callback;
2967
[email protected]684970b2009-08-14 04:54:462968 int rv = trans->Start(&request, &callback, NULL);
[email protected]1c773ea12009-04-28 19:58:422969 EXPECT_EQ(ERR_IO_PENDING, rv);
2970
2971 rv = callback.WaitForResult();
2972 EXPECT_EQ(OK, rv);
2973}
2974
2975TEST_F(HttpNetworkTransactionTest,
2976 BuildRequest_CacheControlValidateCache) {
[email protected]228ff742009-06-05 01:19:592977 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:402978 scoped_ptr<HttpTransaction> trans(
2979 new HttpNetworkTransaction(
[email protected]228ff742009-06-05 01:19:592980 CreateSession(&session_deps),
2981 &session_deps.socket_factory));
[email protected]1c773ea12009-04-28 19:58:422982
2983 HttpRequestInfo request;
2984 request.method = "GET";
2985 request.url = GURL("http://www.google.com/");
2986 request.load_flags = LOAD_VALIDATE_CACHE;
2987
2988 MockWrite data_writes[] = {
2989 MockWrite("GET / HTTP/1.1\r\n"
2990 "Host: www.google.com\r\n"
2991 "Connection: keep-alive\r\n"
2992 "Cache-Control: max-age=0\r\n\r\n"),
2993 };
2994
2995 // Lastly, the server responds with the actual content.
2996 MockRead data_reads[] = {
2997 MockRead("HTTP/1.0 200 OK\r\n"),
2998 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2999 MockRead("Content-Length: 100\r\n\r\n"),
3000 MockRead(false, OK),
3001 };
3002
[email protected]69b43fe2009-06-15 09:47:373003 StaticMockSocket data(data_reads, data_writes);
[email protected]228ff742009-06-05 01:19:593004 session_deps.socket_factory.AddMockSocket(&data);
[email protected]1c773ea12009-04-28 19:58:423005
3006 TestCompletionCallback callback;
3007
[email protected]684970b2009-08-14 04:54:463008 int rv = trans->Start(&request, &callback, NULL);
[email protected]1c773ea12009-04-28 19:58:423009 EXPECT_EQ(ERR_IO_PENDING, rv);
3010
3011 rv = callback.WaitForResult();
3012 EXPECT_EQ(OK, rv);
3013}
3014
3015TEST_F(HttpNetworkTransactionTest, BuildRequest_ExtraHeaders) {
[email protected]228ff742009-06-05 01:19:593016 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:403017 scoped_ptr<HttpTransaction> trans(
3018 new HttpNetworkTransaction(
[email protected]228ff742009-06-05 01:19:593019 CreateSession(&session_deps),
3020 &session_deps.socket_factory));
[email protected]1c773ea12009-04-28 19:58:423021
3022 HttpRequestInfo request;
3023 request.method = "GET";
3024 request.url = GURL("http://www.google.com/");
3025 request.extra_headers = "FooHeader: Bar\r\n";
3026
3027 MockWrite data_writes[] = {
3028 MockWrite("GET / HTTP/1.1\r\n"
3029 "Host: www.google.com\r\n"
3030 "Connection: keep-alive\r\n"
3031 "FooHeader: Bar\r\n\r\n"),
3032 };
3033
3034 // Lastly, the server responds with the actual content.
3035 MockRead data_reads[] = {
3036 MockRead("HTTP/1.0 200 OK\r\n"),
3037 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3038 MockRead("Content-Length: 100\r\n\r\n"),
3039 MockRead(false, OK),
3040 };
3041
[email protected]69b43fe2009-06-15 09:47:373042 StaticMockSocket data(data_reads, data_writes);
[email protected]228ff742009-06-05 01:19:593043 session_deps.socket_factory.AddMockSocket(&data);
[email protected]1c773ea12009-04-28 19:58:423044
3045 TestCompletionCallback callback;
3046
[email protected]684970b2009-08-14 04:54:463047 int rv = trans->Start(&request, &callback, NULL);
[email protected]1c773ea12009-04-28 19:58:423048 EXPECT_EQ(ERR_IO_PENDING, rv);
3049
3050 rv = callback.WaitForResult();
3051 EXPECT_EQ(OK, rv);
3052}
3053
[email protected]3cd17242009-06-23 02:59:023054TEST_F(HttpNetworkTransactionTest, SOCKS4_HTTP_GET) {
[email protected]80d6524d2009-08-18 03:58:093055 SessionDependencies session_deps(
3056 CreateFixedProxyService("socks4://myproxy:1080"));
[email protected]3cd17242009-06-23 02:59:023057
3058 scoped_ptr<HttpTransaction> trans(
3059 new HttpNetworkTransaction(
3060 CreateSession(&session_deps),
3061 &session_deps.socket_factory));
3062
3063 HttpRequestInfo request;
3064 request.method = "GET";
3065 request.url = GURL("http://www.google.com/");
3066 request.load_flags = 0;
3067
3068 char write_buffer[] = { 0x04, 0x01, 0x00, 0x50, 127, 0, 0, 1, 0 };
3069 char read_buffer[] = { 0x00, 0x5A, 0x00, 0x00, 0, 0, 0, 0 };
3070
3071 MockWrite data_writes[] = {
[email protected]e0c27be2009-07-15 13:09:353072 MockWrite(true, write_buffer, arraysize(write_buffer)),
[email protected]3cd17242009-06-23 02:59:023073 MockWrite("GET / HTTP/1.1\r\n"
3074 "Host: www.google.com\r\n"
3075 "Connection: keep-alive\r\n\r\n")
3076 };
3077
3078 MockRead data_reads[] = {
[email protected]e0c27be2009-07-15 13:09:353079 MockWrite(true, read_buffer, arraysize(read_buffer)),
[email protected]3cd17242009-06-23 02:59:023080 MockRead("HTTP/1.0 200 OK\r\n"),
3081 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
3082 MockRead("Payload"),
3083 MockRead(false, OK)
3084 };
3085
3086 StaticMockSocket data(data_reads, data_writes);
3087 session_deps.socket_factory.AddMockSocket(&data);
3088
3089 TestCompletionCallback callback;
3090
[email protected]684970b2009-08-14 04:54:463091 int rv = trans->Start(&request, &callback, NULL);
[email protected]3cd17242009-06-23 02:59:023092 EXPECT_EQ(ERR_IO_PENDING, rv);
3093
3094 rv = callback.WaitForResult();
3095 EXPECT_EQ(OK, rv);
3096
3097 const HttpResponseInfo* response = trans->GetResponseInfo();
3098 EXPECT_FALSE(response == NULL);
3099
3100 std::string response_text;
3101 rv = ReadTransaction(trans.get(), &response_text);
3102 EXPECT_EQ(OK, rv);
3103 EXPECT_EQ("Payload", response_text);
3104}
3105
3106TEST_F(HttpNetworkTransactionTest, SOCKS4_SSL_GET) {
[email protected]80d6524d2009-08-18 03:58:093107 SessionDependencies session_deps(
3108 CreateFixedProxyService("socks4://myproxy:1080"));
[email protected]3cd17242009-06-23 02:59:023109
3110 scoped_ptr<HttpTransaction> trans(
3111 new HttpNetworkTransaction(
3112 CreateSession(&session_deps),
3113 &session_deps.socket_factory));
3114
3115 HttpRequestInfo request;
3116 request.method = "GET";
3117 request.url = GURL("https://www.google.com/");
3118 request.load_flags = 0;
3119
3120 unsigned char write_buffer[] = { 0x04, 0x01, 0x01, 0xBB, 127, 0, 0, 1, 0 };
3121 unsigned char read_buffer[] = { 0x00, 0x5A, 0x00, 0x00, 0, 0, 0, 0 };
3122
3123 MockWrite data_writes[] = {
[email protected]e0c27be2009-07-15 13:09:353124 MockWrite(true, reinterpret_cast<char*>(write_buffer),
3125 arraysize(write_buffer)),
[email protected]3cd17242009-06-23 02:59:023126 MockWrite("GET / HTTP/1.1\r\n"
3127 "Host: www.google.com\r\n"
3128 "Connection: keep-alive\r\n\r\n")
3129 };
3130
3131 MockRead data_reads[] = {
[email protected]e0c27be2009-07-15 13:09:353132 MockWrite(true, reinterpret_cast<char*>(read_buffer),
3133 arraysize(read_buffer)),
3134 MockRead("HTTP/1.0 200 OK\r\n"),
3135 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
3136 MockRead("Payload"),
3137 MockRead(false, OK)
3138 };
3139
3140 StaticMockSocket data(data_reads, data_writes);
3141 session_deps.socket_factory.AddMockSocket(&data);
3142
3143 MockSSLSocket ssl(true, OK);
3144 session_deps.socket_factory.AddMockSSLSocket(&ssl);
3145
3146 TestCompletionCallback callback;
3147
[email protected]684970b2009-08-14 04:54:463148 int rv = trans->Start(&request, &callback, NULL);
[email protected]e0c27be2009-07-15 13:09:353149 EXPECT_EQ(ERR_IO_PENDING, rv);
3150
3151 rv = callback.WaitForResult();
3152 EXPECT_EQ(OK, rv);
3153
3154 const HttpResponseInfo* response = trans->GetResponseInfo();
3155 EXPECT_FALSE(response == NULL);
3156
3157 std::string response_text;
3158 rv = ReadTransaction(trans.get(), &response_text);
3159 EXPECT_EQ(OK, rv);
3160 EXPECT_EQ("Payload", response_text);
3161}
3162
3163TEST_F(HttpNetworkTransactionTest, SOCKS5_HTTP_GET) {
[email protected]80d6524d2009-08-18 03:58:093164 SessionDependencies session_deps(
3165 CreateFixedProxyService("socks5://myproxy:1080"));
[email protected]e0c27be2009-07-15 13:09:353166
3167 scoped_ptr<HttpTransaction> trans(
3168 new HttpNetworkTransaction(
3169 CreateSession(&session_deps),
3170 &session_deps.socket_factory));
3171
3172 HttpRequestInfo request;
3173 request.method = "GET";
3174 request.url = GURL("http://www.google.com/");
3175 request.load_flags = 0;
3176
3177 const char kSOCKS5GreetRequest[] = { 0x05, 0x01, 0x00 };
3178 const char kSOCKS5GreetResponse[] = { 0x05, 0x00 };
3179 const char kSOCKS5OkRequest[] =
3180 { 0x05, 0x01, 0x00, 0x01, 127, 0, 0, 1, 0x00, 0x50 };
3181 const char kSOCKS5OkResponse[] =
3182 { 0x05, 0x00, 0x00, 0x01, 127, 0, 0, 1, 0x00, 0x50 };
3183
3184 MockWrite data_writes[] = {
3185 MockWrite(true, kSOCKS5GreetRequest, arraysize(kSOCKS5GreetRequest)),
3186 MockWrite(true, kSOCKS5OkRequest, arraysize(kSOCKS5OkRequest)),
3187 MockWrite("GET / HTTP/1.1\r\n"
3188 "Host: www.google.com\r\n"
3189 "Connection: keep-alive\r\n\r\n")
3190 };
3191
3192 MockRead data_reads[] = {
3193 MockWrite(true, kSOCKS5GreetResponse, arraysize(kSOCKS5GreetResponse)),
3194 MockWrite(true, kSOCKS5OkResponse, arraysize(kSOCKS5OkResponse)),
3195 MockRead("HTTP/1.0 200 OK\r\n"),
3196 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
3197 MockRead("Payload"),
3198 MockRead(false, OK)
3199 };
3200
3201 StaticMockSocket data(data_reads, data_writes);
3202 session_deps.socket_factory.AddMockSocket(&data);
3203
3204 TestCompletionCallback callback;
3205
[email protected]684970b2009-08-14 04:54:463206 int rv = trans->Start(&request, &callback, NULL);
[email protected]e0c27be2009-07-15 13:09:353207 EXPECT_EQ(ERR_IO_PENDING, rv);
3208
3209 rv = callback.WaitForResult();
3210 EXPECT_EQ(OK, rv);
3211
3212 const HttpResponseInfo* response = trans->GetResponseInfo();
3213 EXPECT_FALSE(response == NULL);
3214
3215 std::string response_text;
3216 rv = ReadTransaction(trans.get(), &response_text);
3217 EXPECT_EQ(OK, rv);
3218 EXPECT_EQ("Payload", response_text);
3219}
3220
3221TEST_F(HttpNetworkTransactionTest, SOCKS5_SSL_GET) {
[email protected]80d6524d2009-08-18 03:58:093222 SessionDependencies session_deps(
3223 CreateFixedProxyService("socks5://myproxy:1080"));
[email protected]e0c27be2009-07-15 13:09:353224
3225 scoped_ptr<HttpTransaction> trans(
3226 new HttpNetworkTransaction(
3227 CreateSession(&session_deps),
3228 &session_deps.socket_factory));
3229
3230 HttpRequestInfo request;
3231 request.method = "GET";
3232 request.url = GURL("https://www.google.com/");
3233 request.load_flags = 0;
3234
3235 const char kSOCKS5GreetRequest[] = { 0x05, 0x01, 0x00 };
3236 const char kSOCKS5GreetResponse[] = { 0x05, 0x00 };
3237 const unsigned char kSOCKS5OkRequest[] =
3238 { 0x05, 0x01, 0x00, 0x01, 127, 0, 0, 1, 0x01, 0xBB };
3239 const char kSOCKS5OkResponse[] =
3240 { 0x05, 0x00, 0x00, 0x01, 0, 0, 0, 0, 0x00, 0x00 };
3241
3242 MockWrite data_writes[] = {
3243 MockWrite(true, kSOCKS5GreetRequest, arraysize(kSOCKS5GreetRequest)),
3244 MockWrite(true, reinterpret_cast<const char*>(kSOCKS5OkRequest),
3245 arraysize(kSOCKS5OkRequest)),
3246 MockWrite("GET / HTTP/1.1\r\n"
3247 "Host: www.google.com\r\n"
3248 "Connection: keep-alive\r\n\r\n")
3249 };
3250
3251 MockRead data_reads[] = {
3252 MockWrite(true, kSOCKS5GreetResponse, arraysize(kSOCKS5GreetResponse)),
3253 MockWrite(true, kSOCKS5OkResponse, arraysize(kSOCKS5OkResponse)),
[email protected]3cd17242009-06-23 02:59:023254 MockRead("HTTP/1.0 200 OK\r\n"),
3255 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
3256 MockRead("Payload"),
3257 MockRead(false, OK)
3258 };
3259
3260 StaticMockSocket data(data_reads, data_writes);
3261 session_deps.socket_factory.AddMockSocket(&data);
3262
3263 MockSSLSocket ssl(true, OK);
3264 session_deps.socket_factory.AddMockSSLSocket(&ssl);
3265
3266 TestCompletionCallback callback;
3267
[email protected]684970b2009-08-14 04:54:463268 int rv = trans->Start(&request, &callback, NULL);
[email protected]3cd17242009-06-23 02:59:023269 EXPECT_EQ(ERR_IO_PENDING, rv);
3270
3271 rv = callback.WaitForResult();
3272 EXPECT_EQ(OK, rv);
3273
3274 const HttpResponseInfo* response = trans->GetResponseInfo();
3275 EXPECT_FALSE(response == NULL);
3276
3277 std::string response_text;
3278 rv = ReadTransaction(trans.get(), &response_text);
3279 EXPECT_EQ(OK, rv);
3280 EXPECT_EQ("Payload", response_text);
3281}
3282
[email protected]04e5be32009-06-26 20:00:313283// Tests that for connection endpoints the group names are correctly set.
3284TEST_F(HttpNetworkTransactionTest, GroupNameForProxyConnections) {
3285 const struct {
3286 const std::string proxy_server;
3287 const std::string url;
3288 const std::string expected_group_name;
3289 } tests[] = {
3290 {
3291 "", // no proxy (direct)
3292 "http://www.google.com/direct",
3293 "http://www.google.com/",
3294 },
3295 {
3296 "http_proxy",
3297 "http://www.google.com/http_proxy_normal",
3298 "proxy/http_proxy:80/",
3299 },
3300 {
3301 "socks4://socks_proxy:1080",
3302 "http://www.google.com/socks4_direct",
3303 "proxy/socks4://socks_proxy:1080/http://www.google.com/",
3304 },
3305
3306 // SSL Tests
3307 {
3308 "",
3309 "https://www.google.com/direct_ssl",
3310 "https://www.google.com/",
3311 },
3312 {
3313 "http_proxy",
3314 "https://www.google.com/http_connect_ssl",
3315 "proxy/http_proxy:80/https://www.google.com/",
3316 },
3317 {
3318 "socks4://socks_proxy:1080",
3319 "https://www.google.com/socks4_ssl",
3320 "proxy/socks4://socks_proxy:1080/https://www.google.com/",
3321 },
3322 };
3323
3324 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) {
[email protected]80d6524d2009-08-18 03:58:093325 SessionDependencies session_deps(
3326 CreateFixedProxyService(tests[i].proxy_server));
[email protected]04e5be32009-06-26 20:00:313327
3328 scoped_refptr<CaptureGroupNameSocketPool> conn_pool(
3329 new CaptureGroupNameSocketPool());
3330
3331 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]a937a06d2009-08-19 21:19:243332 session->tcp_socket_pool_ = conn_pool.get();
[email protected]04e5be32009-06-26 20:00:313333
3334 scoped_ptr<HttpTransaction> trans(
3335 new HttpNetworkTransaction(
3336 session.get(),
3337 &session_deps.socket_factory));
3338
3339 HttpRequestInfo request;
3340 request.method = "GET";
3341 request.url = GURL(tests[i].url);
3342 request.load_flags = 0;
3343
3344 TestCompletionCallback callback;
3345
3346 // We do not complete this request, the dtor will clean the transaction up.
[email protected]684970b2009-08-14 04:54:463347 EXPECT_EQ(ERR_IO_PENDING, trans->Start(&request, &callback, NULL));
[email protected]04e5be32009-06-26 20:00:313348 EXPECT_EQ(tests[i].expected_group_name,
3349 conn_pool->last_group_name_received());
3350 }
3351}
3352
[email protected]9172a982009-06-06 00:30:253353TEST_F(HttpNetworkTransactionTest, ReconsiderProxyAfterFailedConnection) {
[email protected]5c6a17e2009-06-10 00:54:543354 SessionDependencies session_deps(
3355 CreateFixedProxyService("myproxy:70;foobar:80"));
[email protected]b59ff372009-07-15 22:04:323356
3357 session_deps.host_resolver->rules()->AddSimulatedFailure("*");
3358
[email protected]9172a982009-06-06 00:30:253359 scoped_ptr<HttpTransaction> trans(
3360 new HttpNetworkTransaction(
3361 CreateSession(&session_deps),
3362 &session_deps.socket_factory));
3363
3364 HttpRequestInfo request;
3365 request.method = "GET";
3366 request.url = GURL("http://www.google.com/");
3367
3368 TestCompletionCallback callback;
3369
[email protected]684970b2009-08-14 04:54:463370 int rv = trans->Start(&request, &callback, NULL);
[email protected]9172a982009-06-06 00:30:253371 EXPECT_EQ(ERR_IO_PENDING, rv);
3372
[email protected]9172a982009-06-06 00:30:253373 rv = callback.WaitForResult();
3374 EXPECT_EQ(ERR_NAME_NOT_RESOLVED, rv);
3375}
3376
[email protected]f3e6c1e2009-06-15 20:52:123377// Host resolution observer used by
3378// HttpNetworkTransactionTest.ResolveMadeWithReferrer to check that host
3379// resovle requests are issued with a referrer of |expected_referrer|.
3380class ResolutionReferrerObserver : public HostResolver::Observer {
3381 public:
3382 explicit ResolutionReferrerObserver(const GURL& expected_referrer)
3383 : expected_referrer_(expected_referrer),
3384 called_start_with_referrer_(false),
3385 called_finish_with_referrer_(false) {
3386 }
3387
3388 virtual void OnStartResolution(int id,
3389 const HostResolver::RequestInfo& info) {
3390 if (info.referrer() == expected_referrer_)
3391 called_start_with_referrer_ = true;
3392 }
3393
3394 virtual void OnFinishResolutionWithStatus(
3395 int id, bool was_resolved, const HostResolver::RequestInfo& info ) {
3396 if (info.referrer() == expected_referrer_)
3397 called_finish_with_referrer_ = true;
3398 }
3399
[email protected]eb255d32009-06-17 02:11:033400 virtual void OnCancelResolution(int id,
3401 const HostResolver::RequestInfo& info ) {
3402 FAIL() << "Should not be cancelling any requests!";
3403 }
3404
[email protected]f3e6c1e2009-06-15 20:52:123405 bool did_complete_with_expected_referrer() const {
3406 return called_start_with_referrer_ && called_finish_with_referrer_;
3407 }
3408
3409 private:
3410 GURL expected_referrer_;
3411 bool called_start_with_referrer_;
3412 bool called_finish_with_referrer_;
3413
3414 DISALLOW_COPY_AND_ASSIGN(ResolutionReferrerObserver);
3415};
3416
3417// Make sure that when HostResolver::Resolve() is invoked, it passes through
3418// the "referrer". This is depended on by the DNS prefetch observer.
3419TEST_F(HttpNetworkTransactionTest, ResolveMadeWithReferrer) {
3420 GURL referrer = GURL("http://expected-referrer/");
3421 EXPECT_TRUE(referrer.is_valid());
3422 ResolutionReferrerObserver resolution_observer(referrer);
3423
3424 SessionDependencies session_deps;
3425 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(
3426 CreateSession(&session_deps), &session_deps.socket_factory));
3427
3428 // Attach an observer to watch the host resolutions being made.
[email protected]94a0d3d92009-06-27 01:50:143429 session_deps.host_resolver->AddObserver(&resolution_observer);
[email protected]f3e6c1e2009-06-15 20:52:123430
3431 // Connect up a mock socket which will fail when reading.
3432 MockRead data_reads[] = {
3433 MockRead(false, ERR_FAILED),
3434 };
3435 StaticMockSocket data(data_reads, NULL);
3436 session_deps.socket_factory.AddMockSocket(&data);
3437
3438 // Issue a request, containing an HTTP referrer.
3439 HttpRequestInfo request;
3440 request.method = "GET";
3441 request.referrer = referrer;
3442 request.url = GURL("http://www.google.com/");
3443
3444 // Run the request until it fails reading from the socket.
3445 TestCompletionCallback callback;
[email protected]684970b2009-08-14 04:54:463446 int rv = trans->Start(&request, &callback, NULL);
[email protected]f3e6c1e2009-06-15 20:52:123447 EXPECT_EQ(ERR_IO_PENDING, rv);
3448 rv = callback.WaitForResult();
3449 EXPECT_EQ(ERR_FAILED, rv);
3450
3451 // Check that the host resolution observer saw |referrer|.
3452 EXPECT_TRUE(resolution_observer.did_complete_with_expected_referrer());
3453}
3454
[email protected]3b9cca42009-06-16 01:08:283455// Make sure that when the load flags contain LOAD_BYPASS_CACHE, the resolver's
3456// host cache is bypassed.
3457TEST_F(HttpNetworkTransactionTest, BypassHostCacheOnRefresh) {
3458 SessionDependencies session_deps;
[email protected]b59ff372009-07-15 22:04:323459
[email protected]a2c2fb92009-07-18 07:31:043460 // Select a host resolver that does caching.
3461 session_deps.host_resolver = new MockCachingHostResolver;
[email protected]b59ff372009-07-15 22:04:323462
[email protected]3b9cca42009-06-16 01:08:283463 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(
3464 CreateSession(&session_deps), &session_deps.socket_factory));
3465
3466 // Warm up the host cache so it has an entry for "www.google.com" (by doing
3467 // a synchronous lookup.)
3468 AddressList addrlist;
[email protected]94a0d3d92009-06-27 01:50:143469 int rv = session_deps.host_resolver->Resolve(
[email protected]684970b2009-08-14 04:54:463470 HostResolver::RequestInfo("www.google.com", 80), &addrlist,
3471 NULL, NULL, NULL);
[email protected]3b9cca42009-06-16 01:08:283472 EXPECT_EQ(OK, rv);
3473
3474 // Verify that it was added to host cache, by doing a subsequent async lookup
3475 // and confirming it completes synchronously.
3476 TestCompletionCallback resolve_callback;
[email protected]684970b2009-08-14 04:54:463477 rv = session_deps.host_resolver->Resolve(
[email protected]3b9cca42009-06-16 01:08:283478 HostResolver::RequestInfo("www.google.com", 80), &addrlist,
[email protected]684970b2009-08-14 04:54:463479 &resolve_callback, NULL, NULL);
[email protected]b59ff372009-07-15 22:04:323480 ASSERT_EQ(OK, rv);
[email protected]3b9cca42009-06-16 01:08:283481
3482 // Inject a failure the next time that "www.google.com" is resolved. This way
3483 // we can tell if the next lookup hit the cache, or the "network".
3484 // (cache --> success, "network" --> failure).
[email protected]b59ff372009-07-15 22:04:323485 session_deps.host_resolver->rules()->AddSimulatedFailure("www.google.com");
[email protected]3b9cca42009-06-16 01:08:283486
3487 // Connect up a mock socket which will fail with ERR_UNEXPECTED during the
3488 // first read -- this won't be reached as the host resolution will fail first.
3489 MockRead data_reads[] = { MockRead(false, ERR_UNEXPECTED) };
3490 StaticMockSocket data(data_reads, NULL);
3491 session_deps.socket_factory.AddMockSocket(&data);
3492
3493 // Issue a request, asking to bypass the cache(s).
3494 HttpRequestInfo request;
3495 request.method = "GET";
3496 request.load_flags = LOAD_BYPASS_CACHE;
3497 request.url = GURL("http://www.google.com/");
3498
3499 // Run the request.
3500 TestCompletionCallback callback;
[email protected]684970b2009-08-14 04:54:463501 rv = trans->Start(&request, &callback, NULL);
[email protected]3b9cca42009-06-16 01:08:283502 ASSERT_EQ(ERR_IO_PENDING, rv);
3503 rv = callback.WaitForResult();
3504
3505 // If we bypassed the cache, we would have gotten a failure while resolving
3506 // "www.google.com".
3507 EXPECT_EQ(ERR_NAME_NOT_RESOLVED, rv);
3508}
3509
[email protected]a97cca42009-08-14 01:00:293510TEST_F(HttpNetworkTransactionTest, GetIdentifyFromUrl) {
3511 struct {
3512 const char* input_url;
3513 const wchar_t* expected_username;
3514 const wchar_t* expected_password;
3515 } tests[] = {
3516 {
3517 "http://username:[email protected]",
3518 L"username",
3519 L"password",
3520 },
3521 { // Test for http://crbug.com/19200
3522 "http://username:p@[email protected]",
3523 L"username",
3524 L"p@ssword",
3525 },
3526 { // Username contains %20.
3527 "http://use rname:[email protected]",
3528 L"use rname",
3529 L"password",
3530 },
3531 { // The URL canonicalizer for userinfo does not recognize non-ascii
3532 // escapes it seems... So things like %00 will NOT be unescapable,
3533 // since they are canonicalized by escaping the %...
3534 "http://use%00rname:[email protected]",
3535 L"use%2500rname",
3536 L"password",
3537 },
3538 { // Use a '+' in the username.
3539 "http://use+rname:[email protected]",
3540 L"use+rname",
3541 L"password",
3542 },
3543 { // Use a '&' in the password.
3544 "http://username:p&[email protected]",
3545 L"username",
3546 L"p&ssword",
3547 },
3548 };
3549 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) {
3550 SCOPED_TRACE(StringPrintf("Test[%d]: %s", i, tests[i].input_url));
3551 GURL url(tests[i].input_url);
3552
3553 std::wstring username, password;
3554 HttpNetworkTransaction::GetIdentifyFromUrl(url, &username, &password);
3555
3556 EXPECT_EQ(tests[i].expected_username, username);
3557 EXPECT_EQ(tests[i].expected_password, password);
3558 }
3559}
3560
3561// Try extracting a username which was encoded with UTF8.
3562TEST_F(HttpNetworkTransactionTest, GetIdentifyFromUrl_UTF8) {
3563 GURL url(WideToUTF16(L"http://foo:\x4f60\[email protected]"));
3564
3565 EXPECT_EQ("foo", url.username());
3566 EXPECT_EQ("%E4%BD%A0%E5%A5%BD", url.password());
3567
3568 // Extract the unescaped identity.
3569 std::wstring username, password;
3570 HttpNetworkTransaction::GetIdentifyFromUrl(url, &username, &password);
3571
3572 // Verify that it was decoded as UTF8.
3573 EXPECT_EQ(L"foo", username);
3574 EXPECT_EQ(L"\x4f60\x597d", password);
3575}
3576
[email protected]89ceba9a2009-03-21 03:46:063577} // namespace net