blob: 4742122396748bb352b08bb040629f473a45a37b [file] [log] [blame]
[email protected]95d88ffe2010-02-04 21:25:331// Copyright (c) 2010 The Chromium Authors. All rights reserved.
license.botbf09a502008-08-24 00:55:552// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
initial.commit586acc5fe2008-07-26 22:42:524
[email protected]77848d12008-11-14 00:00:225#include <math.h> // ceil
[email protected]95d88ffe2010-02-04 21:25:336#include <vector>
[email protected]77848d12008-11-14 00:00:227
[email protected]68bf9152008-09-25 19:47:308#include "base/compiler_specific.h"
[email protected]95d88ffe2010-02-04 21:25:339#include "base/file_path.h"
10#include "base/file_util.h"
[email protected]6624b4622010-03-29 19:58:3611#include "base/scoped_ptr.h"
[email protected]bacff652009-03-31 17:50:3312#include "net/base/completion_callback.h"
[email protected]b59ff372009-07-15 22:04:3213#include "net/base/mock_host_resolver.h"
[email protected]ac790b42009-12-02 04:31:3114#include "net/base/request_priority.h"
[email protected]db36938c2009-08-19 21:48:4215#include "net/base/ssl_config_service_defaults.h"
[email protected]bacff652009-03-31 17:50:3316#include "net/base/ssl_info.h"
initial.commit586acc5fe2008-07-26 22:42:5217#include "net/base/test_completion_callback.h"
18#include "net/base/upload_data.h"
[email protected]385a4672009-03-11 22:21:2919#include "net/http/http_auth_handler_ntlm.h"
[email protected]0877e3d2009-10-17 22:29:5720#include "net/http/http_basic_stream.h"
initial.commit586acc5fe2008-07-26 22:42:5221#include "net/http/http_network_session.h"
22#include "net/http/http_network_transaction.h"
[email protected]0877e3d2009-10-17 22:29:5723#include "net/http/http_stream.h"
initial.commit586acc5fe2008-07-26 22:42:5224#include "net/http/http_transaction_unittest.h"
[email protected]51fff29d2008-12-19 22:17:5325#include "net/proxy/proxy_config_service_fixed.h"
[email protected]f7984fc62009-06-22 23:26:4426#include "net/socket/client_socket_factory.h"
27#include "net/socket/socket_test_util.h"
28#include "net/socket/ssl_client_socket.h"
[email protected]2ff8b312010-04-26 22:20:5429#include "net/spdy/spdy_framer.h"
30#include "net/spdy/spdy_session.h"
31#include "net/spdy/spdy_session_pool.h"
32#include "net/spdy/spdy_test_util.h"
initial.commit586acc5fe2008-07-26 22:42:5233#include "testing/gtest/include/gtest/gtest.h"
[email protected]23887f04f2008-12-02 19:20:1534#include "testing/platform_test.h"
initial.commit586acc5fe2008-07-26 22:42:5235
36//-----------------------------------------------------------------------------
37
[email protected]89ceba9a2009-03-21 03:46:0638namespace net {
39
[email protected]e44de5d2009-06-05 20:12:4540// Helper to manage the lifetimes of the dependencies for a
41// HttpNetworkTransaction.
[email protected]228ff742009-06-05 01:19:5942class SessionDependencies {
43 public:
44 // Default set of dependencies -- "null" proxy service.
[email protected]db36938c2009-08-19 21:48:4245 SessionDependencies()
46 : host_resolver(new MockHostResolver),
[email protected]dded3e22010-02-05 04:08:3747 proxy_service(ProxyService::CreateNull()),
[email protected]d1eda932009-11-04 01:03:1048 ssl_config_service(new SSLConfigServiceDefaults),
[email protected]61a86c42010-04-19 22:45:5349 http_auth_handler_factory(HttpAuthHandlerFactory::CreateDefault()),
50 spdy_session_pool(new SpdySessionPool) {}
[email protected]228ff742009-06-05 01:19:5951
52 // Custom proxy service dependency.
[email protected]e44de5d2009-06-05 20:12:4553 explicit SessionDependencies(ProxyService* proxy_service)
[email protected]db36938c2009-08-19 21:48:4254 : host_resolver(new MockHostResolver),
55 proxy_service(proxy_service),
[email protected]d1eda932009-11-04 01:03:1056 ssl_config_service(new SSLConfigServiceDefaults),
[email protected]61a86c42010-04-19 22:45:5357 http_auth_handler_factory(HttpAuthHandlerFactory::CreateDefault()),
58 spdy_session_pool(new SpdySessionPool) {}
[email protected]228ff742009-06-05 01:19:5959
[email protected]a2c2fb92009-07-18 07:31:0460 scoped_refptr<MockHostResolverBase> host_resolver;
[email protected]80d6524d2009-08-18 03:58:0961 scoped_refptr<ProxyService> proxy_service;
[email protected]db36938c2009-08-19 21:48:4262 scoped_refptr<SSLConfigService> ssl_config_service;
[email protected]228ff742009-06-05 01:19:5963 MockClientSocketFactory socket_factory;
[email protected]fa55e192010-02-15 14:25:5064 scoped_ptr<HttpAuthHandlerFactory> http_auth_handler_factory;
[email protected]61a86c42010-04-19 22:45:5365 scoped_refptr<SpdySessionPool> spdy_session_pool;
[email protected]228ff742009-06-05 01:19:5966};
67
[email protected]1c773ea12009-04-28 19:58:4268ProxyService* CreateFixedProxyService(const std::string& proxy) {
[email protected]ab501a6a2009-05-12 15:07:5069 net::ProxyConfig proxy_config;
[email protected]ed4ed0f2010-02-24 00:20:4870 proxy_config.proxy_rules().ParseFromString(proxy);
[email protected]3e44697f2009-05-22 14:37:3971 return ProxyService::CreateFixed(proxy_config);
[email protected]51fff29d2008-12-19 22:17:5372}
73
[email protected]228ff742009-06-05 01:19:5974HttpNetworkSession* CreateSession(SessionDependencies* session_deps) {
[email protected]d13c3272010-02-04 00:24:5175 return new HttpNetworkSession(NULL,
76 session_deps->host_resolver,
[email protected]80d6524d2009-08-18 03:58:0977 session_deps->proxy_service,
[email protected]db36938c2009-08-19 21:48:4278 &session_deps->socket_factory,
[email protected]d1eda932009-11-04 01:03:1079 session_deps->ssl_config_service,
[email protected]61a86c42010-04-19 22:45:5380 session_deps->spdy_session_pool,
[email protected]fa55e192010-02-15 14:25:5081 session_deps->http_auth_handler_factory.get());
[email protected]e8d536192008-10-17 22:21:1482}
83
[email protected]89836e22008-09-25 20:33:4284class HttpNetworkTransactionTest : public PlatformTest {
initial.commit586acc5fe2008-07-26 22:42:5285 public:
[email protected]2ff8b312010-04-26 22:20:5486 virtual void SetUp() {
87 spdy::SpdyFramer::set_enable_compression_default(false);
88 }
89
[email protected]0e75a732008-10-16 20:36:0990 virtual void TearDown() {
[email protected]2ff8b312010-04-26 22:20:5491 spdy::SpdyFramer::set_enable_compression_default(true);
[email protected]0e75a732008-10-16 20:36:0992 // Empty the current queue.
93 MessageLoop::current()->RunAllPending();
94 PlatformTest::TearDown();
95 }
96
[email protected]3d2a59b2008-09-26 19:44:2597 protected:
98 void KeepAliveConnectionResendRequestTest(const MockRead& read_failure);
initial.commit586acc5fe2008-07-26 22:42:5299
[email protected]ff007e162009-05-23 09:13:15100 struct SimpleGetHelperResult {
101 int rv;
102 std::string status_line;
103 std::string response_data;
104 };
initial.commit586acc5fe2008-07-26 22:42:52105
[email protected]31a2bfe2010-02-09 08:03:39106 SimpleGetHelperResult SimpleGetHelper(MockRead data_reads[],
107 size_t reads_count) {
[email protected]ff007e162009-05-23 09:13:15108 SimpleGetHelperResult out;
initial.commit586acc5fe2008-07-26 22:42:52109
[email protected]228ff742009-06-05 01:19:59110 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:40111 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:43112 new HttpNetworkTransaction(CreateSession(&session_deps)));
initial.commit586acc5fe2008-07-26 22:42:52113
[email protected]ff007e162009-05-23 09:13:15114 HttpRequestInfo request;
115 request.method = "GET";
116 request.url = GURL("http://www.google.com/");
117 request.load_flags = 0;
initial.commit586acc5fe2008-07-26 22:42:52118
[email protected]31a2bfe2010-02-09 08:03:39119 StaticSocketDataProvider data(data_reads, reads_count, NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:59120 session_deps.socket_factory.AddSocketDataProvider(&data);
initial.commit586acc5fe2008-07-26 22:42:52121
[email protected]ff007e162009-05-23 09:13:15122 TestCompletionCallback callback;
initial.commit586acc5fe2008-07-26 22:42:52123
[email protected]684970b2009-08-14 04:54:46124 int rv = trans->Start(&request, &callback, NULL);
[email protected]ff007e162009-05-23 09:13:15125 EXPECT_EQ(ERR_IO_PENDING, rv);
initial.commit586acc5fe2008-07-26 22:42:52126
[email protected]ff007e162009-05-23 09:13:15127 out.rv = callback.WaitForResult();
128 if (out.rv != OK)
129 return out;
130
131 const HttpResponseInfo* response = trans->GetResponseInfo();
132 EXPECT_TRUE(response != NULL);
133
134 EXPECT_TRUE(response->headers != NULL);
135 out.status_line = response->headers->GetStatusLine();
136
137 rv = ReadTransaction(trans.get(), &out.response_data);
138 EXPECT_EQ(OK, rv);
139
[email protected]aecfbf22008-10-16 02:02:47140 return out;
[email protected]ff007e162009-05-23 09:13:15141 }
initial.commit586acc5fe2008-07-26 22:42:52142
[email protected]ff007e162009-05-23 09:13:15143 void ConnectStatusHelperWithExpectedStatus(const MockRead& status,
144 int expected_status);
initial.commit586acc5fe2008-07-26 22:42:52145
[email protected]ff007e162009-05-23 09:13:15146 void ConnectStatusHelper(const MockRead& status);
[email protected]ff007e162009-05-23 09:13:15147};
[email protected]231d5a32008-09-13 00:45:27148
[email protected]15a5ccf82008-10-23 19:57:43149// Fill |str| with a long header list that consumes >= |size| bytes.
150void FillLargeHeadersString(std::string* str, int size) {
[email protected]4ddaf2502008-10-23 18:26:19151 const char* row =
152 "SomeHeaderName: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\r\n";
153 const int sizeof_row = strlen(row);
154 const int num_rows = static_cast<int>(
155 ceil(static_cast<float>(size) / sizeof_row));
156 const int sizeof_data = num_rows * sizeof_row;
157 DCHECK(sizeof_data >= size);
[email protected]15a5ccf82008-10-23 19:57:43158 str->reserve(sizeof_data);
[email protected]372d34a2008-11-05 21:30:51159
[email protected]4ddaf2502008-10-23 18:26:19160 for (int i = 0; i < num_rows; ++i)
[email protected]15a5ccf82008-10-23 19:57:43161 str->append(row, sizeof_row);
[email protected]4ddaf2502008-10-23 18:26:19162}
163
[email protected]385a4672009-03-11 22:21:29164// Alternative functions that eliminate randomness and dependency on the local
165// host name so that the generated NTLM messages are reproducible.
[email protected]fe2bc6a2009-03-23 16:52:20166void MockGenerateRandom1(uint8* output, size_t n) {
[email protected]385a4672009-03-11 22:21:29167 static const uint8 bytes[] = {
168 0x55, 0x29, 0x66, 0x26, 0x6b, 0x9c, 0x73, 0x54
169 };
170 static size_t current_byte = 0;
171 for (size_t i = 0; i < n; ++i) {
172 output[i] = bytes[current_byte++];
173 current_byte %= arraysize(bytes);
174 }
175}
176
[email protected]fe2bc6a2009-03-23 16:52:20177void MockGenerateRandom2(uint8* output, size_t n) {
[email protected]385a4672009-03-11 22:21:29178 static const uint8 bytes[] = {
179 0x96, 0x79, 0x85, 0xe7, 0x49, 0x93, 0x70, 0xa1,
180 0x4e, 0xe7, 0x87, 0x45, 0x31, 0x5b, 0xd3, 0x1f
181 };
182 static size_t current_byte = 0;
183 for (size_t i = 0; i < n; ++i) {
184 output[i] = bytes[current_byte++];
185 current_byte %= arraysize(bytes);
186 }
187}
188
[email protected]fe2bc6a2009-03-23 16:52:20189std::string MockGetHostName() {
190 return "WTC-WIN7";
[email protected]385a4672009-03-11 22:21:29191}
192
[email protected]a796bcec2010-03-22 17:17:26193template<typename EmulatedClientSocketPool, typename SocketSourceType>
194class CaptureGroupNameSocketPool : public EmulatedClientSocketPool {
[email protected]04e5be32009-06-26 20:00:31195 public:
[email protected]a796bcec2010-03-22 17:17:26196 CaptureGroupNameSocketPool(HttpNetworkSession* session,
197 SocketSourceType* socket_source)
198 : EmulatedClientSocketPool(0, 0, "CaptureGroupNameTestPool",
[email protected]61a86c42010-04-19 22:45:53199 session->host_resolver(), socket_source,
200 NULL) {}
[email protected]d80a4322009-08-14 07:07:49201 const std::string last_group_name_received() const {
202 return last_group_name_;
203 }
204
[email protected]684970b2009-08-14 04:54:46205 virtual int RequestSocket(const std::string& group_name,
[email protected]d80a4322009-08-14 07:07:49206 const void* socket_params,
[email protected]ac790b42009-12-02 04:31:31207 RequestPriority priority,
[email protected]04e5be32009-06-26 20:00:31208 ClientSocketHandle* handle,
[email protected]684970b2009-08-14 04:54:46209 CompletionCallback* callback,
[email protected]9e743cd2010-03-16 07:03:53210 const BoundNetLog& net_log) {
[email protected]04e5be32009-06-26 20:00:31211 last_group_name_ = group_name;
212 return ERR_IO_PENDING;
213 }
[email protected]04e5be32009-06-26 20:00:31214 virtual void CancelRequest(const std::string& group_name,
215 const ClientSocketHandle* handle) { }
216 virtual void ReleaseSocket(const std::string& group_name,
217 ClientSocket* socket) {}
218 virtual void CloseIdleSockets() {}
219 virtual HostResolver* GetHostResolver() const {
220 return NULL;
221 }
222 virtual int IdleSocketCount() const {
223 return 0;
224 }
225 virtual int IdleSocketCountInGroup(const std::string& group_name) const {
226 return 0;
227 }
228 virtual LoadState GetLoadState(const std::string& group_name,
229 const ClientSocketHandle* handle) const {
230 return LOAD_STATE_IDLE;
231 }
[email protected]a796bcec2010-03-22 17:17:26232 virtual base::TimeDelta ConnectionTimeout() const {
233 return base::TimeDelta();
234 }
[email protected]d80a4322009-08-14 07:07:49235
236 private:
[email protected]04e5be32009-06-26 20:00:31237 std::string last_group_name_;
238};
239
[email protected]a796bcec2010-03-22 17:17:26240typedef CaptureGroupNameSocketPool<TCPClientSocketPool, ClientSocketFactory>
241 CaptureGroupNameTCPSocketPool;
242typedef CaptureGroupNameSocketPool<SOCKSClientSocketPool, TCPClientSocketPool>
243 CaptureGroupNameSOCKSSocketPool;
[email protected]231d5a32008-09-13 00:45:27244//-----------------------------------------------------------------------------
245
246TEST_F(HttpNetworkTransactionTest, Basic) {
[email protected]228ff742009-06-05 01:19:59247 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:40248 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:43249 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]231d5a32008-09-13 00:45:27250}
251
252TEST_F(HttpNetworkTransactionTest, SimpleGET) {
253 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35254 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
255 MockRead("hello world"),
[email protected]1c773ea12009-04-28 19:58:42256 MockRead(false, OK),
[email protected]231d5a32008-09-13 00:45:27257 };
[email protected]31a2bfe2010-02-09 08:03:39258 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
259 arraysize(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 200 OK", out.status_line);
262 EXPECT_EQ("hello world", out.response_data);
263}
264
265// Response with no status line.
266TEST_F(HttpNetworkTransactionTest, SimpleGETNoHeaders) {
267 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35268 MockRead("hello world"),
[email protected]1c773ea12009-04-28 19:58:42269 MockRead(false, OK),
[email protected]231d5a32008-09-13 00:45:27270 };
[email protected]31a2bfe2010-02-09 08:03:39271 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
272 arraysize(data_reads));
[email protected]1c773ea12009-04-28 19:58:42273 EXPECT_EQ(OK, out.rv);
[email protected]231d5a32008-09-13 00:45:27274 EXPECT_EQ("HTTP/0.9 200 OK", out.status_line);
275 EXPECT_EQ("hello world", out.response_data);
276}
277
278// Allow up to 4 bytes of junk to precede status line.
279TEST_F(HttpNetworkTransactionTest, StatusLineJunk2Bytes) {
280 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35281 MockRead("xxxHTTP/1.0 404 Not Found\nServer: blah\n\nDATA"),
[email protected]1c773ea12009-04-28 19:58:42282 MockRead(false, OK),
[email protected]231d5a32008-09-13 00:45:27283 };
[email protected]31a2bfe2010-02-09 08:03:39284 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
285 arraysize(data_reads));
[email protected]1c773ea12009-04-28 19:58:42286 EXPECT_EQ(OK, out.rv);
[email protected]231d5a32008-09-13 00:45:27287 EXPECT_EQ("HTTP/1.0 404 Not Found", out.status_line);
288 EXPECT_EQ("DATA", out.response_data);
289}
290
291// Allow up to 4 bytes of junk to precede status line.
292TEST_F(HttpNetworkTransactionTest, StatusLineJunk4Bytes) {
293 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35294 MockRead("\n\nQJHTTP/1.0 404 Not Found\nServer: blah\n\nDATA"),
[email protected]1c773ea12009-04-28 19:58:42295 MockRead(false, OK),
[email protected]231d5a32008-09-13 00:45:27296 };
[email protected]31a2bfe2010-02-09 08:03:39297 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
298 arraysize(data_reads));
[email protected]1c773ea12009-04-28 19:58:42299 EXPECT_EQ(OK, out.rv);
[email protected]231d5a32008-09-13 00:45:27300 EXPECT_EQ("HTTP/1.0 404 Not Found", out.status_line);
301 EXPECT_EQ("DATA", out.response_data);
302}
303
304// Beyond 4 bytes of slop and it should fail to find a status line.
305TEST_F(HttpNetworkTransactionTest, StatusLineJunk5Bytes) {
306 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35307 MockRead("xxxxxHTTP/1.1 404 Not Found\nServer: blah"),
[email protected]1c773ea12009-04-28 19:58:42308 MockRead(false, OK),
[email protected]231d5a32008-09-13 00:45:27309 };
[email protected]31a2bfe2010-02-09 08:03:39310 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
311 arraysize(data_reads));
[email protected]1c773ea12009-04-28 19:58:42312 EXPECT_EQ(OK, out.rv);
[email protected]3d2a59b2008-09-26 19:44:25313 EXPECT_EQ("HTTP/0.9 200 OK", out.status_line);
314 EXPECT_EQ("xxxxxHTTP/1.1 404 Not Found\nServer: blah", out.response_data);
[email protected]231d5a32008-09-13 00:45:27315}
316
317// Same as StatusLineJunk4Bytes, except the read chunks are smaller.
318TEST_F(HttpNetworkTransactionTest, StatusLineJunk4Bytes_Slow) {
319 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35320 MockRead("\n"),
321 MockRead("\n"),
322 MockRead("Q"),
323 MockRead("J"),
324 MockRead("HTTP/1.0 404 Not Found\nServer: blah\n\nDATA"),
[email protected]1c773ea12009-04-28 19:58:42325 MockRead(false, OK),
[email protected]231d5a32008-09-13 00:45:27326 };
[email protected]31a2bfe2010-02-09 08:03:39327 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
328 arraysize(data_reads));
[email protected]1c773ea12009-04-28 19:58:42329 EXPECT_EQ(OK, out.rv);
[email protected]231d5a32008-09-13 00:45:27330 EXPECT_EQ("HTTP/1.0 404 Not Found", out.status_line);
331 EXPECT_EQ("DATA", out.response_data);
332}
333
334// Close the connection before enough bytes to have a status line.
335TEST_F(HttpNetworkTransactionTest, StatusLinePartial) {
336 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35337 MockRead("HTT"),
[email protected]1c773ea12009-04-28 19:58:42338 MockRead(false, OK),
[email protected]231d5a32008-09-13 00:45:27339 };
[email protected]31a2bfe2010-02-09 08:03:39340 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
341 arraysize(data_reads));
[email protected]1c773ea12009-04-28 19:58:42342 EXPECT_EQ(OK, out.rv);
[email protected]231d5a32008-09-13 00:45:27343 EXPECT_EQ("HTTP/0.9 200 OK", out.status_line);
344 EXPECT_EQ("HTT", out.response_data);
initial.commit586acc5fe2008-07-26 22:42:52345}
346
[email protected]f9d44aa2008-09-23 23:57:17347// Simulate a 204 response, lacking a Content-Length header, sent over a
348// persistent connection. The response should still terminate since a 204
349// cannot have a response body.
350TEST_F(HttpNetworkTransactionTest, StopsReading204) {
351 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35352 MockRead("HTTP/1.1 204 No Content\r\n\r\n"),
353 MockRead("junk"), // Should not be read!!
[email protected]1c773ea12009-04-28 19:58:42354 MockRead(false, OK),
[email protected]f9d44aa2008-09-23 23:57:17355 };
[email protected]31a2bfe2010-02-09 08:03:39356 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
357 arraysize(data_reads));
[email protected]1c773ea12009-04-28 19:58:42358 EXPECT_EQ(OK, out.rv);
[email protected]f9d44aa2008-09-23 23:57:17359 EXPECT_EQ("HTTP/1.1 204 No Content", out.status_line);
360 EXPECT_EQ("", out.response_data);
361}
362
[email protected]0877e3d2009-10-17 22:29:57363// A simple request using chunked encoding with some extra data after.
364// (Like might be seen in a pipelined response.)
365TEST_F(HttpNetworkTransactionTest, ChunkedEncoding) {
366 MockRead data_reads[] = {
367 MockRead("HTTP/1.1 200 OK\r\nTransfer-Encoding: chunked\r\n\r\n"),
368 MockRead("5\r\nHello\r\n"),
369 MockRead("1\r\n"),
370 MockRead(" \r\n"),
371 MockRead("5\r\nworld\r\n"),
372 MockRead("0\r\n\r\nHTTP/1.1 200 OK\r\n"),
373 MockRead(false, OK),
374 };
[email protected]31a2bfe2010-02-09 08:03:39375 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
376 arraysize(data_reads));
[email protected]0877e3d2009-10-17 22:29:57377 EXPECT_EQ(OK, out.rv);
378 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
379 EXPECT_EQ("Hello world", out.response_data);
380}
381
[email protected]ef0faf2e72009-03-05 23:27:23382// Do a request using the HEAD method. Verify that we don't try to read the
383// message body (since HEAD has none).
384TEST_F(HttpNetworkTransactionTest, Head) {
[email protected]228ff742009-06-05 01:19:59385 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:40386 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:43387 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]ef0faf2e72009-03-05 23:27:23388
[email protected]1c773ea12009-04-28 19:58:42389 HttpRequestInfo request;
[email protected]ef0faf2e72009-03-05 23:27:23390 request.method = "HEAD";
391 request.url = GURL("http://www.google.com/");
392 request.load_flags = 0;
393
394 MockWrite data_writes1[] = {
395 MockWrite("HEAD / HTTP/1.1\r\n"
396 "Host: www.google.com\r\n"
397 "Connection: keep-alive\r\n"
398 "Content-Length: 0\r\n\r\n"),
399 };
400 MockRead data_reads1[] = {
401 MockRead("HTTP/1.1 404 Not Found\r\n"),
402 MockRead("Server: Blah\r\n"),
403 MockRead("Content-Length: 1234\r\n\r\n"),
404
405 // No response body because the test stops reading here.
[email protected]1c773ea12009-04-28 19:58:42406 MockRead(false, ERR_UNEXPECTED), // Should not be reached.
[email protected]ef0faf2e72009-03-05 23:27:23407 };
408
[email protected]31a2bfe2010-02-09 08:03:39409 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
410 data_writes1, arraysize(data_writes1));
[email protected]5ecc992a42009-11-11 01:41:59411 session_deps.socket_factory.AddSocketDataProvider(&data1);
[email protected]ef0faf2e72009-03-05 23:27:23412
413 TestCompletionCallback callback1;
414
[email protected]684970b2009-08-14 04:54:46415 int rv = trans->Start(&request, &callback1, NULL);
[email protected]1c773ea12009-04-28 19:58:42416 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]ef0faf2e72009-03-05 23:27:23417
418 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42419 EXPECT_EQ(OK, rv);
[email protected]ef0faf2e72009-03-05 23:27:23420
[email protected]1c773ea12009-04-28 19:58:42421 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]ef0faf2e72009-03-05 23:27:23422 EXPECT_FALSE(response == NULL);
423
424 // Check that the headers got parsed.
425 EXPECT_TRUE(response->headers != NULL);
426 EXPECT_EQ(1234, response->headers->GetContentLength());
427 EXPECT_EQ("HTTP/1.1 404 Not Found", response->headers->GetStatusLine());
428
429 std::string server_header;
430 void* iter = NULL;
431 bool has_server_header = response->headers->EnumerateHeader(
432 &iter, "Server", &server_header);
433 EXPECT_TRUE(has_server_header);
434 EXPECT_EQ("Blah", server_header);
435
436 // Reading should give EOF right away, since there is no message body
437 // (despite non-zero content-length).
438 std::string response_data;
439 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:42440 EXPECT_EQ(OK, rv);
[email protected]ef0faf2e72009-03-05 23:27:23441 EXPECT_EQ("", response_data);
442}
443
initial.commit586acc5fe2008-07-26 22:42:52444TEST_F(HttpNetworkTransactionTest, ReuseConnection) {
[email protected]228ff742009-06-05 01:19:59445 SessionDependencies session_deps;
446 scoped_refptr<HttpNetworkSession> session = CreateSession(&session_deps);
initial.commit586acc5fe2008-07-26 22:42:52447
448 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35449 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
450 MockRead("hello"),
451 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
452 MockRead("world"),
[email protected]1c773ea12009-04-28 19:58:42453 MockRead(false, OK),
initial.commit586acc5fe2008-07-26 22:42:52454 };
[email protected]31a2bfe2010-02-09 08:03:39455 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:59456 session_deps.socket_factory.AddSocketDataProvider(&data);
initial.commit586acc5fe2008-07-26 22:42:52457
458 const char* kExpectedResponseData[] = {
459 "hello", "world"
460 };
461
462 for (int i = 0; i < 2; ++i) {
[email protected]5695b8c2009-09-30 21:36:43463 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
initial.commit586acc5fe2008-07-26 22:42:52464
[email protected]1c773ea12009-04-28 19:58:42465 HttpRequestInfo request;
initial.commit586acc5fe2008-07-26 22:42:52466 request.method = "GET";
467 request.url = GURL("http://www.google.com/");
468 request.load_flags = 0;
469
470 TestCompletionCallback callback;
471
[email protected]684970b2009-08-14 04:54:46472 int rv = trans->Start(&request, &callback, NULL);
[email protected]1c773ea12009-04-28 19:58:42473 EXPECT_EQ(ERR_IO_PENDING, rv);
initial.commit586acc5fe2008-07-26 22:42:52474
475 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42476 EXPECT_EQ(OK, rv);
initial.commit586acc5fe2008-07-26 22:42:52477
[email protected]1c773ea12009-04-28 19:58:42478 const HttpResponseInfo* response = trans->GetResponseInfo();
initial.commit586acc5fe2008-07-26 22:42:52479 EXPECT_TRUE(response != NULL);
480
481 EXPECT_TRUE(response->headers != NULL);
[email protected]3d2a59b2008-09-26 19:44:25482 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
initial.commit586acc5fe2008-07-26 22:42:52483
484 std::string response_data;
[email protected]af4876d2008-10-21 23:10:57485 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:42486 EXPECT_EQ(OK, rv);
[email protected]3d2a59b2008-09-26 19:44:25487 EXPECT_EQ(kExpectedResponseData[i], response_data);
initial.commit586acc5fe2008-07-26 22:42:52488 }
489}
490
491TEST_F(HttpNetworkTransactionTest, Ignores100) {
[email protected]228ff742009-06-05 01:19:59492 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:40493 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:43494 new HttpNetworkTransaction(CreateSession(&session_deps)));
initial.commit586acc5fe2008-07-26 22:42:52495
[email protected]1c773ea12009-04-28 19:58:42496 HttpRequestInfo request;
initial.commit586acc5fe2008-07-26 22:42:52497 request.method = "POST";
498 request.url = GURL("http://www.foo.com/");
[email protected]1c773ea12009-04-28 19:58:42499 request.upload_data = new UploadData;
initial.commit586acc5fe2008-07-26 22:42:52500 request.upload_data->AppendBytes("foo", 3);
501 request.load_flags = 0;
502
503 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35504 MockRead("HTTP/1.0 100 Continue\r\n\r\n"),
505 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
506 MockRead("hello world"),
[email protected]1c773ea12009-04-28 19:58:42507 MockRead(false, OK),
initial.commit586acc5fe2008-07-26 22:42:52508 };
[email protected]31a2bfe2010-02-09 08:03:39509 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:59510 session_deps.socket_factory.AddSocketDataProvider(&data);
initial.commit586acc5fe2008-07-26 22:42:52511
512 TestCompletionCallback callback;
513
[email protected]684970b2009-08-14 04:54:46514 int rv = trans->Start(&request, &callback, NULL);
[email protected]1c773ea12009-04-28 19:58:42515 EXPECT_EQ(ERR_IO_PENDING, rv);
initial.commit586acc5fe2008-07-26 22:42:52516
517 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42518 EXPECT_EQ(OK, rv);
initial.commit586acc5fe2008-07-26 22:42:52519
[email protected]1c773ea12009-04-28 19:58:42520 const HttpResponseInfo* response = trans->GetResponseInfo();
initial.commit586acc5fe2008-07-26 22:42:52521 EXPECT_TRUE(response != NULL);
522
523 EXPECT_TRUE(response->headers != NULL);
[email protected]3d2a59b2008-09-26 19:44:25524 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
initial.commit586acc5fe2008-07-26 22:42:52525
526 std::string response_data;
[email protected]af4876d2008-10-21 23:10:57527 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:42528 EXPECT_EQ(OK, rv);
[email protected]3d2a59b2008-09-26 19:44:25529 EXPECT_EQ("hello world", response_data);
initial.commit586acc5fe2008-07-26 22:42:52530}
531
[email protected]3a2d3662009-03-27 03:49:14532// This test is almost the same as Ignores100 above, but the response contains
533// a 102 instead of a 100. Also, instead of HTTP/1.0 the response is
[email protected]0877e3d2009-10-17 22:29:57534// HTTP/1.1 and the two status headers are read in one read.
[email protected]3a2d3662009-03-27 03:49:14535TEST_F(HttpNetworkTransactionTest, Ignores1xx) {
[email protected]228ff742009-06-05 01:19:59536 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:40537 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:43538 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]3a2d3662009-03-27 03:49:14539
[email protected]1c773ea12009-04-28 19:58:42540 HttpRequestInfo request;
[email protected]3a2d3662009-03-27 03:49:14541 request.method = "GET";
542 request.url = GURL("http://www.foo.com/");
543 request.load_flags = 0;
544
545 MockRead data_reads[] = {
[email protected]0877e3d2009-10-17 22:29:57546 MockRead("HTTP/1.1 102 Unspecified status code\r\n\r\n"
547 "HTTP/1.1 200 OK\r\n\r\n"),
[email protected]3a2d3662009-03-27 03:49:14548 MockRead("hello world"),
[email protected]1c773ea12009-04-28 19:58:42549 MockRead(false, OK),
[email protected]3a2d3662009-03-27 03:49:14550 };
[email protected]31a2bfe2010-02-09 08:03:39551 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:59552 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]3a2d3662009-03-27 03:49:14553
554 TestCompletionCallback callback;
555
[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);
[email protected]3a2d3662009-03-27 03:49:14558
559 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42560 EXPECT_EQ(OK, rv);
[email protected]3a2d3662009-03-27 03:49:14561
[email protected]1c773ea12009-04-28 19:58:42562 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]3a2d3662009-03-27 03:49:14563 EXPECT_TRUE(response != NULL);
564
565 EXPECT_TRUE(response->headers != NULL);
566 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
567
568 std::string response_data;
569 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:42570 EXPECT_EQ(OK, rv);
[email protected]3a2d3662009-03-27 03:49:14571 EXPECT_EQ("hello world", response_data);
572}
573
[email protected]ee9410e72010-01-07 01:42:38574TEST_F(HttpNetworkTransactionTest, Incomplete100ThenEOF) {
575 SessionDependencies session_deps;
576 scoped_ptr<HttpTransaction> trans(
577 new HttpNetworkTransaction(CreateSession(&session_deps)));
578
579 HttpRequestInfo request;
580 request.method = "POST";
581 request.url = GURL("http://www.foo.com/");
582 request.load_flags = 0;
583
584 MockRead data_reads[] = {
585 MockRead(false, "HTTP/1.0 100 Continue\r\n"),
586 MockRead(true, 0),
587 };
[email protected]31a2bfe2010-02-09 08:03:39588 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]ee9410e72010-01-07 01:42:38589 session_deps.socket_factory.AddSocketDataProvider(&data);
590
591 TestCompletionCallback callback;
592
593 int rv = trans->Start(&request, &callback, NULL);
594 EXPECT_EQ(ERR_IO_PENDING, rv);
595
596 rv = callback.WaitForResult();
597 EXPECT_EQ(OK, rv);
598
599 std::string response_data;
600 rv = ReadTransaction(trans.get(), &response_data);
601 EXPECT_EQ(OK, rv);
602 EXPECT_EQ("", response_data);
603}
604
605TEST_F(HttpNetworkTransactionTest, EmptyResponse) {
606 SessionDependencies session_deps;
607 scoped_ptr<HttpTransaction> trans(
608 new HttpNetworkTransaction(CreateSession(&session_deps)));
609
610 HttpRequestInfo request;
611 request.method = "POST";
612 request.url = GURL("http://www.foo.com/");
613 request.load_flags = 0;
614
615 MockRead data_reads[] = {
616 MockRead(true, 0),
617 };
[email protected]31a2bfe2010-02-09 08:03:39618 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]ee9410e72010-01-07 01:42:38619 session_deps.socket_factory.AddSocketDataProvider(&data);
620
621 TestCompletionCallback callback;
622
623 int rv = trans->Start(&request, &callback, NULL);
624 EXPECT_EQ(ERR_IO_PENDING, rv);
625
626 rv = callback.WaitForResult();
627 EXPECT_EQ(ERR_EMPTY_RESPONSE, rv);
628}
629
[email protected]3d2a59b2008-09-26 19:44:25630// read_failure specifies a read failure that should cause the network
631// transaction to resend the request.
632void HttpNetworkTransactionTest::KeepAliveConnectionResendRequestTest(
633 const MockRead& read_failure) {
[email protected]228ff742009-06-05 01:19:59634 SessionDependencies session_deps;
635 scoped_refptr<HttpNetworkSession> session = CreateSession(&session_deps);
initial.commit586acc5fe2008-07-26 22:42:52636
[email protected]1c773ea12009-04-28 19:58:42637 HttpRequestInfo request;
initial.commit586acc5fe2008-07-26 22:42:52638 request.method = "GET";
639 request.url = GURL("http://www.foo.com/");
640 request.load_flags = 0;
641
642 MockRead data1_reads[] = {
[email protected]217e6022008-09-29 18:18:35643 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
644 MockRead("hello"),
[email protected]3d2a59b2008-09-26 19:44:25645 read_failure, // Now, we reuse the connection and fail the first read.
initial.commit586acc5fe2008-07-26 22:42:52646 };
[email protected]31a2bfe2010-02-09 08:03:39647 StaticSocketDataProvider data1(data1_reads, arraysize(data1_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:59648 session_deps.socket_factory.AddSocketDataProvider(&data1);
initial.commit586acc5fe2008-07-26 22:42:52649
650 MockRead data2_reads[] = {
[email protected]217e6022008-09-29 18:18:35651 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
652 MockRead("world"),
[email protected]1c773ea12009-04-28 19:58:42653 MockRead(true, OK),
initial.commit586acc5fe2008-07-26 22:42:52654 };
[email protected]31a2bfe2010-02-09 08:03:39655 StaticSocketDataProvider data2(data2_reads, arraysize(data2_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:59656 session_deps.socket_factory.AddSocketDataProvider(&data2);
initial.commit586acc5fe2008-07-26 22:42:52657
658 const char* kExpectedResponseData[] = {
659 "hello", "world"
660 };
661
662 for (int i = 0; i < 2; ++i) {
663 TestCompletionCallback callback;
664
[email protected]5695b8c2009-09-30 21:36:43665 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
initial.commit586acc5fe2008-07-26 22:42:52666
[email protected]684970b2009-08-14 04:54:46667 int rv = trans->Start(&request, &callback, NULL);
[email protected]1c773ea12009-04-28 19:58:42668 EXPECT_EQ(ERR_IO_PENDING, rv);
initial.commit586acc5fe2008-07-26 22:42:52669
670 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42671 EXPECT_EQ(OK, rv);
initial.commit586acc5fe2008-07-26 22:42:52672
[email protected]1c773ea12009-04-28 19:58:42673 const HttpResponseInfo* response = trans->GetResponseInfo();
initial.commit586acc5fe2008-07-26 22:42:52674 EXPECT_TRUE(response != NULL);
675
676 EXPECT_TRUE(response->headers != NULL);
[email protected]3d2a59b2008-09-26 19:44:25677 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
initial.commit586acc5fe2008-07-26 22:42:52678
679 std::string response_data;
[email protected]af4876d2008-10-21 23:10:57680 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:42681 EXPECT_EQ(OK, rv);
[email protected]3d2a59b2008-09-26 19:44:25682 EXPECT_EQ(kExpectedResponseData[i], response_data);
initial.commit586acc5fe2008-07-26 22:42:52683 }
684}
[email protected]3d2a59b2008-09-26 19:44:25685
686TEST_F(HttpNetworkTransactionTest, KeepAliveConnectionReset) {
[email protected]1c773ea12009-04-28 19:58:42687 MockRead read_failure(true, ERR_CONNECTION_RESET);
[email protected]3d2a59b2008-09-26 19:44:25688 KeepAliveConnectionResendRequestTest(read_failure);
689}
690
691TEST_F(HttpNetworkTransactionTest, KeepAliveConnectionEOF) {
[email protected]1c773ea12009-04-28 19:58:42692 MockRead read_failure(false, OK); // EOF
[email protected]3d2a59b2008-09-26 19:44:25693 KeepAliveConnectionResendRequestTest(read_failure);
694}
695
696TEST_F(HttpNetworkTransactionTest, NonKeepAliveConnectionReset) {
[email protected]228ff742009-06-05 01:19:59697 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:40698 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:43699 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]3d2a59b2008-09-26 19:44:25700
[email protected]1c773ea12009-04-28 19:58:42701 HttpRequestInfo request;
[email protected]3d2a59b2008-09-26 19:44:25702 request.method = "GET";
703 request.url = GURL("http://www.google.com/");
704 request.load_flags = 0;
705
706 MockRead data_reads[] = {
[email protected]1c773ea12009-04-28 19:58:42707 MockRead(true, ERR_CONNECTION_RESET),
[email protected]217e6022008-09-29 18:18:35708 MockRead("HTTP/1.0 200 OK\r\n\r\n"), // Should not be used
709 MockRead("hello world"),
[email protected]1c773ea12009-04-28 19:58:42710 MockRead(false, OK),
[email protected]3d2a59b2008-09-26 19:44:25711 };
[email protected]31a2bfe2010-02-09 08:03:39712 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:59713 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]3d2a59b2008-09-26 19:44:25714
715 TestCompletionCallback callback;
716
[email protected]684970b2009-08-14 04:54:46717 int rv = trans->Start(&request, &callback, NULL);
[email protected]1c773ea12009-04-28 19:58:42718 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]3d2a59b2008-09-26 19:44:25719
720 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42721 EXPECT_EQ(ERR_CONNECTION_RESET, rv);
[email protected]3d2a59b2008-09-26 19:44:25722
[email protected]1c773ea12009-04-28 19:58:42723 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]3d2a59b2008-09-26 19:44:25724 EXPECT_TRUE(response == NULL);
[email protected]3d2a59b2008-09-26 19:44:25725}
726
727// What do various browsers do when the server closes a non-keepalive
728// connection without sending any response header or body?
729//
730// IE7: error page
731// Safari 3.1.2 (Windows): error page
732// Firefox 3.0.1: blank page
733// Opera 9.52: after five attempts, blank page
[email protected]1c773ea12009-04-28 19:58:42734// Us with WinHTTP: error page (ERR_INVALID_RESPONSE)
735// Us: error page (EMPTY_RESPONSE)
[email protected]3d2a59b2008-09-26 19:44:25736TEST_F(HttpNetworkTransactionTest, NonKeepAliveConnectionEOF) {
737 MockRead data_reads[] = {
[email protected]1c773ea12009-04-28 19:58:42738 MockRead(false, OK), // EOF
[email protected]217e6022008-09-29 18:18:35739 MockRead("HTTP/1.0 200 OK\r\n\r\n"), // Should not be used
740 MockRead("hello world"),
[email protected]1c773ea12009-04-28 19:58:42741 MockRead(false, OK),
[email protected]3d2a59b2008-09-26 19:44:25742 };
[email protected]31a2bfe2010-02-09 08:03:39743 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
744 arraysize(data_reads));
[email protected]1c773ea12009-04-28 19:58:42745 EXPECT_EQ(ERR_EMPTY_RESPONSE, out.rv);
[email protected]3d2a59b2008-09-26 19:44:25746}
[email protected]038e9a32008-10-08 22:40:16747
748// Test the request-challenge-retry sequence for basic auth.
749// (basic auth is the easiest to mock, because it has no randomness).
750TEST_F(HttpNetworkTransactionTest, BasicAuth) {
[email protected]228ff742009-06-05 01:19:59751 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:40752 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:43753 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]038e9a32008-10-08 22:40:16754
[email protected]1c773ea12009-04-28 19:58:42755 HttpRequestInfo request;
[email protected]038e9a32008-10-08 22:40:16756 request.method = "GET";
757 request.url = GURL("http://www.google.com/");
758 request.load_flags = 0;
759
[email protected]f9ee6b52008-11-08 06:46:23760 MockWrite data_writes1[] = {
761 MockWrite("GET / HTTP/1.1\r\n"
762 "Host: www.google.com\r\n"
763 "Connection: keep-alive\r\n\r\n"),
764 };
765
[email protected]038e9a32008-10-08 22:40:16766 MockRead data_reads1[] = {
767 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
768 // Give a couple authenticate options (only the middle one is actually
769 // supported).
[email protected]22927ad2009-09-21 19:56:19770 MockRead("WWW-Authenticate: Basic invalid\r\n"), // Malformed.
[email protected]038e9a32008-10-08 22:40:16771 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
772 MockRead("WWW-Authenticate: UNSUPPORTED realm=\"FOO\"\r\n"),
773 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
774 // Large content-length -- won't matter, as connection will be reset.
775 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:42776 MockRead(false, ERR_FAILED),
[email protected]038e9a32008-10-08 22:40:16777 };
778
779 // After calling trans->RestartWithAuth(), this is the request we should
780 // be issuing -- the final header line contains the credentials.
781 MockWrite data_writes2[] = {
782 MockWrite("GET / HTTP/1.1\r\n"
783 "Host: www.google.com\r\n"
784 "Connection: keep-alive\r\n"
785 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
786 };
787
788 // Lastly, the server responds with the actual content.
789 MockRead data_reads2[] = {
790 MockRead("HTTP/1.0 200 OK\r\n"),
791 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
792 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:42793 MockRead(false, OK),
[email protected]038e9a32008-10-08 22:40:16794 };
795
[email protected]31a2bfe2010-02-09 08:03:39796 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
797 data_writes1, arraysize(data_writes1));
798 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
799 data_writes2, arraysize(data_writes2));
[email protected]5ecc992a42009-11-11 01:41:59800 session_deps.socket_factory.AddSocketDataProvider(&data1);
801 session_deps.socket_factory.AddSocketDataProvider(&data2);
[email protected]038e9a32008-10-08 22:40:16802
803 TestCompletionCallback callback1;
804
[email protected]684970b2009-08-14 04:54:46805 int rv = trans->Start(&request, &callback1, NULL);
[email protected]1c773ea12009-04-28 19:58:42806 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]038e9a32008-10-08 22:40:16807
808 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42809 EXPECT_EQ(OK, rv);
[email protected]038e9a32008-10-08 22:40:16810
[email protected]1c773ea12009-04-28 19:58:42811 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]038e9a32008-10-08 22:40:16812 EXPECT_FALSE(response == NULL);
813
814 // The password prompt info should have been set in response->auth_challenge.
815 EXPECT_FALSE(response->auth_challenge.get() == NULL);
816
[email protected]71e4573a2009-05-21 22:03:00817 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
[email protected]038e9a32008-10-08 22:40:16818 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
819 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
820
821 TestCompletionCallback callback2;
822
823 rv = trans->RestartWithAuth(L"foo", L"bar", &callback2);
[email protected]1c773ea12009-04-28 19:58:42824 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]038e9a32008-10-08 22:40:16825
826 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42827 EXPECT_EQ(OK, rv);
[email protected]038e9a32008-10-08 22:40:16828
829 response = trans->GetResponseInfo();
830 EXPECT_FALSE(response == NULL);
831 EXPECT_TRUE(response->auth_challenge.get() == NULL);
832 EXPECT_EQ(100, response->headers->GetContentLength());
[email protected]038e9a32008-10-08 22:40:16833}
834
[email protected]861fcd52009-08-26 02:33:46835TEST_F(HttpNetworkTransactionTest, DoNotSendAuth) {
836 SessionDependencies session_deps;
837 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:43838 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]861fcd52009-08-26 02:33:46839
840 HttpRequestInfo request;
841 request.method = "GET";
842 request.url = GURL("http://www.google.com/");
843 request.load_flags = net::LOAD_DO_NOT_SEND_AUTH_DATA;
844
845 MockWrite data_writes[] = {
846 MockWrite("GET / HTTP/1.1\r\n"
847 "Host: www.google.com\r\n"
848 "Connection: keep-alive\r\n\r\n"),
849 };
850
851 MockRead data_reads[] = {
852 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
853 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
854 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
855 // Large content-length -- won't matter, as connection will be reset.
856 MockRead("Content-Length: 10000\r\n\r\n"),
857 MockRead(false, ERR_FAILED),
858 };
859
[email protected]31a2bfe2010-02-09 08:03:39860 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
861 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:59862 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]861fcd52009-08-26 02:33:46863 TestCompletionCallback callback;
864
865 int rv = trans->Start(&request, &callback, NULL);
866 EXPECT_EQ(ERR_IO_PENDING, rv);
867
868 rv = callback.WaitForResult();
869 EXPECT_EQ(0, rv);
870
871 const HttpResponseInfo* response = trans->GetResponseInfo();
872 ASSERT_FALSE(response == NULL);
873 EXPECT_TRUE(response->auth_challenge.get() == NULL);
874}
875
[email protected]2d2697f92009-02-18 21:00:32876// Test the request-challenge-retry sequence for basic auth, over a keep-alive
877// connection.
878TEST_F(HttpNetworkTransactionTest, BasicAuthKeepAlive) {
[email protected]228ff742009-06-05 01:19:59879 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:40880 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:43881 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]2d2697f92009-02-18 21:00:32882
[email protected]1c773ea12009-04-28 19:58:42883 HttpRequestInfo request;
[email protected]2d2697f92009-02-18 21:00:32884 request.method = "GET";
885 request.url = GURL("http://www.google.com/");
886 request.load_flags = 0;
887
888 MockWrite data_writes1[] = {
889 MockWrite("GET / HTTP/1.1\r\n"
890 "Host: www.google.com\r\n"
891 "Connection: keep-alive\r\n\r\n"),
892
893 // After calling trans->RestartWithAuth(), this is the request we should
894 // be issuing -- the final header line contains the credentials.
895 MockWrite("GET / HTTP/1.1\r\n"
896 "Host: www.google.com\r\n"
897 "Connection: keep-alive\r\n"
898 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
899 };
900
901 MockRead data_reads1[] = {
902 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
903 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
904 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
905 MockRead("Content-Length: 14\r\n\r\n"),
906 MockRead("Unauthorized\r\n"),
907
908 // Lastly, the server responds with the actual content.
909 MockRead("HTTP/1.1 200 OK\r\n"),
910 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
911 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:42912 MockRead(false, OK),
[email protected]2d2697f92009-02-18 21:00:32913 };
914
[email protected]31a2bfe2010-02-09 08:03:39915 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
916 data_writes1, arraysize(data_writes1));
[email protected]5ecc992a42009-11-11 01:41:59917 session_deps.socket_factory.AddSocketDataProvider(&data1);
[email protected]2d2697f92009-02-18 21:00:32918
919 TestCompletionCallback callback1;
920
[email protected]684970b2009-08-14 04:54:46921 int rv = trans->Start(&request, &callback1, NULL);
[email protected]1c773ea12009-04-28 19:58:42922 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:32923
924 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42925 EXPECT_EQ(OK, rv);
[email protected]2d2697f92009-02-18 21:00:32926
[email protected]1c773ea12009-04-28 19:58:42927 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]2d2697f92009-02-18 21:00:32928 EXPECT_FALSE(response == NULL);
929
930 // The password prompt info should have been set in response->auth_challenge.
931 EXPECT_FALSE(response->auth_challenge.get() == NULL);
932
[email protected]71e4573a2009-05-21 22:03:00933 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
[email protected]2d2697f92009-02-18 21:00:32934 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
935 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
936
937 TestCompletionCallback callback2;
938
939 rv = trans->RestartWithAuth(L"foo", L"bar", &callback2);
[email protected]1c773ea12009-04-28 19:58:42940 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:32941
942 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42943 EXPECT_EQ(OK, rv);
[email protected]2d2697f92009-02-18 21:00:32944
945 response = trans->GetResponseInfo();
946 EXPECT_FALSE(response == NULL);
947 EXPECT_TRUE(response->auth_challenge.get() == NULL);
948 EXPECT_EQ(100, response->headers->GetContentLength());
949}
950
951// Test the request-challenge-retry sequence for basic auth, over a keep-alive
952// connection and with no response body to drain.
953TEST_F(HttpNetworkTransactionTest, BasicAuthKeepAliveNoBody) {
[email protected]228ff742009-06-05 01:19:59954 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:40955 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:43956 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]2d2697f92009-02-18 21:00:32957
[email protected]1c773ea12009-04-28 19:58:42958 HttpRequestInfo request;
[email protected]2d2697f92009-02-18 21:00:32959 request.method = "GET";
960 request.url = GURL("http://www.google.com/");
961 request.load_flags = 0;
962
963 MockWrite data_writes1[] = {
964 MockWrite("GET / HTTP/1.1\r\n"
965 "Host: www.google.com\r\n"
966 "Connection: keep-alive\r\n\r\n"),
967
968 // After calling trans->RestartWithAuth(), this is the request we should
969 // be issuing -- the final header line contains the credentials.
970 MockWrite("GET / HTTP/1.1\r\n"
971 "Host: www.google.com\r\n"
972 "Connection: keep-alive\r\n"
973 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
974 };
975
[email protected]2d2697f92009-02-18 21:00:32976 MockRead data_reads1[] = {
977 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
978 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
[email protected]11203f012009-11-12 23:02:31979 MockRead("Content-Length: 0\r\n\r\n"), // No response body.
[email protected]2d2697f92009-02-18 21:00:32980
981 // Lastly, the server responds with the actual content.
982 MockRead("HTTP/1.1 200 OK\r\n"),
983 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
984 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:42985 MockRead(false, OK),
[email protected]2d2697f92009-02-18 21:00:32986 };
987
[email protected]31a2bfe2010-02-09 08:03:39988 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
989 data_writes1, arraysize(data_writes1));
[email protected]5ecc992a42009-11-11 01:41:59990 session_deps.socket_factory.AddSocketDataProvider(&data1);
[email protected]2d2697f92009-02-18 21:00:32991
992 TestCompletionCallback callback1;
993
[email protected]684970b2009-08-14 04:54:46994 int rv = trans->Start(&request, &callback1, NULL);
[email protected]1c773ea12009-04-28 19:58:42995 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:32996
997 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42998 EXPECT_EQ(OK, rv);
[email protected]2d2697f92009-02-18 21:00:32999
[email protected]1c773ea12009-04-28 19:58:421000 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]2d2697f92009-02-18 21:00:321001 EXPECT_FALSE(response == NULL);
1002
1003 // The password prompt info should have been set in response->auth_challenge.
1004 EXPECT_FALSE(response->auth_challenge.get() == NULL);
1005
[email protected]71e4573a2009-05-21 22:03:001006 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
[email protected]2d2697f92009-02-18 21:00:321007 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
1008 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
1009
1010 TestCompletionCallback callback2;
1011
1012 rv = trans->RestartWithAuth(L"foo", L"bar", &callback2);
[email protected]1c773ea12009-04-28 19:58:421013 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:321014
1015 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421016 EXPECT_EQ(OK, rv);
[email protected]2d2697f92009-02-18 21:00:321017
1018 response = trans->GetResponseInfo();
1019 EXPECT_FALSE(response == NULL);
1020 EXPECT_TRUE(response->auth_challenge.get() == NULL);
1021 EXPECT_EQ(100, response->headers->GetContentLength());
1022}
1023
1024// Test the request-challenge-retry sequence for basic auth, over a keep-alive
1025// connection and with a large response body to drain.
1026TEST_F(HttpNetworkTransactionTest, BasicAuthKeepAliveLargeBody) {
[email protected]228ff742009-06-05 01:19:591027 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:401028 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:431029 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]2d2697f92009-02-18 21:00:321030
[email protected]1c773ea12009-04-28 19:58:421031 HttpRequestInfo request;
[email protected]2d2697f92009-02-18 21:00:321032 request.method = "GET";
1033 request.url = GURL("http://www.google.com/");
1034 request.load_flags = 0;
1035
1036 MockWrite data_writes1[] = {
1037 MockWrite("GET / HTTP/1.1\r\n"
1038 "Host: www.google.com\r\n"
1039 "Connection: keep-alive\r\n\r\n"),
1040
1041 // After calling trans->RestartWithAuth(), this is the request we should
1042 // be issuing -- the final header line contains the credentials.
1043 MockWrite("GET / HTTP/1.1\r\n"
1044 "Host: www.google.com\r\n"
1045 "Connection: keep-alive\r\n"
1046 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
1047 };
1048
1049 // Respond with 5 kb of response body.
1050 std::string large_body_string("Unauthorized");
1051 large_body_string.append(5 * 1024, ' ');
1052 large_body_string.append("\r\n");
1053
1054 MockRead data_reads1[] = {
1055 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
1056 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1057 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1058 // 5134 = 12 + 5 * 1024 + 2
1059 MockRead("Content-Length: 5134\r\n\r\n"),
1060 MockRead(true, large_body_string.data(), large_body_string.size()),
1061
1062 // Lastly, the server responds with the actual content.
1063 MockRead("HTTP/1.1 200 OK\r\n"),
1064 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1065 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:421066 MockRead(false, OK),
[email protected]2d2697f92009-02-18 21:00:321067 };
1068
[email protected]31a2bfe2010-02-09 08:03:391069 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
1070 data_writes1, arraysize(data_writes1));
[email protected]5ecc992a42009-11-11 01:41:591071 session_deps.socket_factory.AddSocketDataProvider(&data1);
[email protected]2d2697f92009-02-18 21:00:321072
1073 TestCompletionCallback callback1;
1074
[email protected]684970b2009-08-14 04:54:461075 int rv = trans->Start(&request, &callback1, NULL);
[email protected]1c773ea12009-04-28 19:58:421076 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:321077
1078 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421079 EXPECT_EQ(OK, rv);
[email protected]2d2697f92009-02-18 21:00:321080
[email protected]1c773ea12009-04-28 19:58:421081 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]2d2697f92009-02-18 21:00:321082 EXPECT_FALSE(response == NULL);
1083
1084 // The password prompt info should have been set in response->auth_challenge.
1085 EXPECT_FALSE(response->auth_challenge.get() == NULL);
1086
[email protected]71e4573a2009-05-21 22:03:001087 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
[email protected]2d2697f92009-02-18 21:00:321088 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
1089 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
1090
1091 TestCompletionCallback callback2;
1092
1093 rv = trans->RestartWithAuth(L"foo", L"bar", &callback2);
[email protected]1c773ea12009-04-28 19:58:421094 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:321095
1096 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421097 EXPECT_EQ(OK, rv);
[email protected]2d2697f92009-02-18 21:00:321098
1099 response = trans->GetResponseInfo();
1100 EXPECT_FALSE(response == NULL);
1101 EXPECT_TRUE(response->auth_challenge.get() == NULL);
1102 EXPECT_EQ(100, response->headers->GetContentLength());
1103}
1104
1105// Test the request-challenge-retry sequence for basic auth, over a keep-alive
[email protected]11203f012009-11-12 23:02:311106// connection, but the server gets impatient and closes the connection.
1107TEST_F(HttpNetworkTransactionTest, BasicAuthKeepAliveImpatientServer) {
1108 SessionDependencies session_deps;
1109 scoped_ptr<HttpTransaction> trans(
1110 new HttpNetworkTransaction(CreateSession(&session_deps)));
1111
1112 HttpRequestInfo request;
1113 request.method = "GET";
1114 request.url = GURL("http://www.google.com/");
1115 request.load_flags = 0;
1116
1117 MockWrite data_writes1[] = {
1118 MockWrite("GET / HTTP/1.1\r\n"
1119 "Host: www.google.com\r\n"
1120 "Connection: keep-alive\r\n\r\n"),
1121 // This simulates the seemingly successful write to a closed connection
1122 // if the bug is not fixed.
1123 MockWrite("GET / HTTP/1.1\r\n"
1124 "Host: www.google.com\r\n"
1125 "Connection: keep-alive\r\n"
1126 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
1127 };
1128
1129 MockRead data_reads1[] = {
1130 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
1131 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1132 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1133 MockRead("Content-Length: 14\r\n\r\n"),
1134 // Tell MockTCPClientSocket to simulate the server closing the connection.
1135 MockRead(false, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
1136 MockRead("Unauthorized\r\n"),
1137 MockRead(false, OK), // The server closes the connection.
1138 };
1139
1140 // After calling trans->RestartWithAuth(), this is the request we should
1141 // be issuing -- the final header line contains the credentials.
1142 MockWrite data_writes2[] = {
1143 MockWrite("GET / HTTP/1.1\r\n"
1144 "Host: www.google.com\r\n"
1145 "Connection: keep-alive\r\n"
1146 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
1147 };
1148
1149 // Lastly, the server responds with the actual content.
1150 MockRead data_reads2[] = {
1151 MockRead("HTTP/1.1 200 OK\r\n"),
1152 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1153 MockRead("Content-Length: 100\r\n\r\n"),
1154 MockRead(false, OK),
1155 };
1156
[email protected]31a2bfe2010-02-09 08:03:391157 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
1158 data_writes1, arraysize(data_writes1));
1159 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
1160 data_writes2, arraysize(data_writes2));
[email protected]11203f012009-11-12 23:02:311161 session_deps.socket_factory.AddSocketDataProvider(&data1);
1162 session_deps.socket_factory.AddSocketDataProvider(&data2);
1163
1164 TestCompletionCallback callback1;
1165
1166 int rv = trans->Start(&request, &callback1, NULL);
1167 EXPECT_EQ(ERR_IO_PENDING, rv);
1168
1169 rv = callback1.WaitForResult();
1170 EXPECT_EQ(OK, rv);
1171
1172 const HttpResponseInfo* response = trans->GetResponseInfo();
1173 EXPECT_FALSE(response == NULL);
1174
1175 // The password prompt info should have been set in response->auth_challenge.
1176 EXPECT_FALSE(response->auth_challenge.get() == NULL);
1177
1178 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
1179 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
1180 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
1181
1182 TestCompletionCallback callback2;
1183
1184 rv = trans->RestartWithAuth(L"foo", L"bar", &callback2);
1185 EXPECT_EQ(ERR_IO_PENDING, rv);
1186
1187 rv = callback2.WaitForResult();
1188 EXPECT_EQ(OK, rv);
1189
1190 response = trans->GetResponseInfo();
1191 ASSERT_FALSE(response == NULL);
1192 EXPECT_TRUE(response->auth_challenge.get() == NULL);
1193 EXPECT_EQ(100, response->headers->GetContentLength());
1194}
1195
1196// Test the request-challenge-retry sequence for basic auth, over a keep-alive
[email protected]2d2697f92009-02-18 21:00:321197// proxy connection, when setting up an SSL tunnel.
1198TEST_F(HttpNetworkTransactionTest, BasicAuthProxyKeepAlive) {
1199 // Configure against proxy server "myproxy:70".
[email protected]228ff742009-06-05 01:19:591200 SessionDependencies session_deps(CreateFixedProxyService("myproxy:70"));
1201 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]2d2697f92009-02-18 21:00:321202
[email protected]5695b8c2009-09-30 21:36:431203 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]2d2697f92009-02-18 21:00:321204
[email protected]1c773ea12009-04-28 19:58:421205 HttpRequestInfo request;
[email protected]2d2697f92009-02-18 21:00:321206 request.method = "GET";
1207 request.url = GURL("https://www.google.com/");
[email protected]861fcd52009-08-26 02:33:461208 // Ensure that proxy authentication is attempted even
1209 // when the no authentication data flag is set.
1210 request.load_flags = net::LOAD_DO_NOT_SEND_AUTH_DATA;
[email protected]2d2697f92009-02-18 21:00:321211
1212 // Since we have proxy, should try to establish tunnel.
1213 MockWrite data_writes1[] = {
1214 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
[email protected]e44de5d2009-06-05 20:12:451215 "Host: www.google.com\r\n"
1216 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]2d2697f92009-02-18 21:00:321217
1218 // After calling trans->RestartWithAuth(), this is the request we should
1219 // be issuing -- the final header line contains the credentials.
1220 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
1221 "Host: www.google.com\r\n"
[email protected]e44de5d2009-06-05 20:12:451222 "Proxy-Connection: keep-alive\r\n"
[email protected]2d2697f92009-02-18 21:00:321223 "Proxy-Authorization: Basic Zm9vOmJheg==\r\n\r\n"),
1224 };
1225
1226 // The proxy responds to the connect with a 407, using a persistent
1227 // connection.
1228 MockRead data_reads1[] = {
1229 // No credentials.
1230 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
1231 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1232 MockRead("Content-Length: 10\r\n\r\n"),
1233 MockRead("0123456789"),
1234
1235 // Wrong credentials (wrong password).
1236 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
1237 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1238 MockRead("Content-Length: 10\r\n\r\n"),
1239 // No response body because the test stops reading here.
[email protected]1c773ea12009-04-28 19:58:421240 MockRead(false, ERR_UNEXPECTED), // Should not be reached.
[email protected]2d2697f92009-02-18 21:00:321241 };
1242
[email protected]31a2bfe2010-02-09 08:03:391243 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
1244 data_writes1, arraysize(data_writes1));
[email protected]5ecc992a42009-11-11 01:41:591245 session_deps.socket_factory.AddSocketDataProvider(&data1);
[email protected]2d2697f92009-02-18 21:00:321246
1247 TestCompletionCallback callback1;
1248
[email protected]684970b2009-08-14 04:54:461249 int rv = trans->Start(&request, &callback1, NULL);
[email protected]1c773ea12009-04-28 19:58:421250 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:321251
1252 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421253 EXPECT_EQ(OK, rv);
[email protected]2d2697f92009-02-18 21:00:321254
[email protected]1c773ea12009-04-28 19:58:421255 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]2d2697f92009-02-18 21:00:321256 EXPECT_FALSE(response == NULL);
1257
1258 EXPECT_TRUE(response->headers->IsKeepAlive());
1259 EXPECT_EQ(407, response->headers->response_code());
1260 EXPECT_EQ(10, response->headers->GetContentLength());
[email protected]1c773ea12009-04-28 19:58:421261 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
[email protected]2d2697f92009-02-18 21:00:321262
1263 // The password prompt info should have been set in response->auth_challenge.
1264 EXPECT_FALSE(response->auth_challenge.get() == NULL);
1265
[email protected]71e4573a2009-05-21 22:03:001266 EXPECT_EQ(L"myproxy:70", response->auth_challenge->host_and_port);
[email protected]2d2697f92009-02-18 21:00:321267 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
1268 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
1269
1270 TestCompletionCallback callback2;
1271
1272 // Wrong password (should be "bar").
1273 rv = trans->RestartWithAuth(L"foo", L"baz", &callback2);
[email protected]1c773ea12009-04-28 19:58:421274 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:321275
1276 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421277 EXPECT_EQ(OK, rv);
[email protected]2d2697f92009-02-18 21:00:321278
1279 response = trans->GetResponseInfo();
1280 EXPECT_FALSE(response == NULL);
1281
1282 EXPECT_TRUE(response->headers->IsKeepAlive());
1283 EXPECT_EQ(407, response->headers->response_code());
1284 EXPECT_EQ(10, response->headers->GetContentLength());
[email protected]1c773ea12009-04-28 19:58:421285 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
[email protected]2d2697f92009-02-18 21:00:321286
1287 // The password prompt info should have been set in response->auth_challenge.
1288 EXPECT_FALSE(response->auth_challenge.get() == NULL);
1289
[email protected]71e4573a2009-05-21 22:03:001290 EXPECT_EQ(L"myproxy:70", response->auth_challenge->host_and_port);
[email protected]2d2697f92009-02-18 21:00:321291 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
1292 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
1293}
1294
[email protected]a8e9b162009-03-12 00:06:441295// Test that we don't read the response body when we fail to establish a tunnel,
1296// even if the user cancels the proxy's auth attempt.
1297TEST_F(HttpNetworkTransactionTest, BasicAuthProxyCancelTunnel) {
1298 // Configure against proxy server "myproxy:70".
[email protected]228ff742009-06-05 01:19:591299 SessionDependencies session_deps(CreateFixedProxyService("myproxy:70"));
[email protected]a8e9b162009-03-12 00:06:441300
[email protected]e44de5d2009-06-05 20:12:451301 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]a8e9b162009-03-12 00:06:441302
[email protected]5695b8c2009-09-30 21:36:431303 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]a8e9b162009-03-12 00:06:441304
[email protected]1c773ea12009-04-28 19:58:421305 HttpRequestInfo request;
[email protected]a8e9b162009-03-12 00:06:441306 request.method = "GET";
1307 request.url = GURL("https://www.google.com/");
1308 request.load_flags = 0;
1309
1310 // Since we have proxy, should try to establish tunnel.
1311 MockWrite data_writes[] = {
1312 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
[email protected]e44de5d2009-06-05 20:12:451313 "Host: www.google.com\r\n"
1314 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]a8e9b162009-03-12 00:06:441315 };
1316
1317 // The proxy responds to the connect with a 407.
1318 MockRead data_reads[] = {
1319 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
1320 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1321 MockRead("Content-Length: 10\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:421322 MockRead(false, ERR_UNEXPECTED), // Should not be reached.
[email protected]a8e9b162009-03-12 00:06:441323 };
1324
[email protected]31a2bfe2010-02-09 08:03:391325 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
1326 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:591327 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]a8e9b162009-03-12 00:06:441328
1329 TestCompletionCallback callback;
1330
[email protected]684970b2009-08-14 04:54:461331 int rv = trans->Start(&request, &callback, NULL);
[email protected]1c773ea12009-04-28 19:58:421332 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]a8e9b162009-03-12 00:06:441333
1334 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421335 EXPECT_EQ(OK, rv);
[email protected]a8e9b162009-03-12 00:06:441336
[email protected]1c773ea12009-04-28 19:58:421337 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]a8e9b162009-03-12 00:06:441338 EXPECT_FALSE(response == NULL);
1339
1340 EXPECT_TRUE(response->headers->IsKeepAlive());
1341 EXPECT_EQ(407, response->headers->response_code());
1342 EXPECT_EQ(10, response->headers->GetContentLength());
[email protected]1c773ea12009-04-28 19:58:421343 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
[email protected]a8e9b162009-03-12 00:06:441344
1345 std::string response_data;
1346 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:421347 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED, rv);
[email protected]a8e9b162009-03-12 00:06:441348}
1349
[email protected]ff007e162009-05-23 09:13:151350void HttpNetworkTransactionTest::ConnectStatusHelperWithExpectedStatus(
[email protected]c744cf22009-02-27 07:28:081351 const MockRead& status, int expected_status) {
1352 // Configure against proxy server "myproxy:70".
[email protected]228ff742009-06-05 01:19:591353 SessionDependencies session_deps(CreateFixedProxyService("myproxy:70"));
[email protected]c744cf22009-02-27 07:28:081354
[email protected]228ff742009-06-05 01:19:591355 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]c744cf22009-02-27 07:28:081356
[email protected]5695b8c2009-09-30 21:36:431357 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]c744cf22009-02-27 07:28:081358
[email protected]1c773ea12009-04-28 19:58:421359 HttpRequestInfo request;
[email protected]c744cf22009-02-27 07:28:081360 request.method = "GET";
1361 request.url = GURL("https://www.google.com/");
1362 request.load_flags = 0;
1363
1364 // Since we have proxy, should try to establish tunnel.
1365 MockWrite data_writes[] = {
1366 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
[email protected]e44de5d2009-06-05 20:12:451367 "Host: www.google.com\r\n"
1368 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]c744cf22009-02-27 07:28:081369 };
1370
1371 MockRead data_reads[] = {
1372 status,
1373 MockRead("Content-Length: 10\r\n\r\n"),
1374 // No response body because the test stops reading here.
[email protected]1c773ea12009-04-28 19:58:421375 MockRead(false, ERR_UNEXPECTED), // Should not be reached.
[email protected]c744cf22009-02-27 07:28:081376 };
1377
[email protected]31a2bfe2010-02-09 08:03:391378 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
1379 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:591380 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]c744cf22009-02-27 07:28:081381
1382 TestCompletionCallback callback;
1383
[email protected]684970b2009-08-14 04:54:461384 int rv = trans->Start(&request, &callback, NULL);
[email protected]1c773ea12009-04-28 19:58:421385 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]c744cf22009-02-27 07:28:081386
1387 rv = callback.WaitForResult();
1388 EXPECT_EQ(expected_status, rv);
1389}
1390
[email protected]ff007e162009-05-23 09:13:151391void HttpNetworkTransactionTest::ConnectStatusHelper(const MockRead& status) {
[email protected]c744cf22009-02-27 07:28:081392 ConnectStatusHelperWithExpectedStatus(
[email protected]1c773ea12009-04-28 19:58:421393 status, ERR_TUNNEL_CONNECTION_FAILED);
[email protected]c744cf22009-02-27 07:28:081394}
1395
1396TEST_F(HttpNetworkTransactionTest, ConnectStatus100) {
1397 ConnectStatusHelper(MockRead("HTTP/1.1 100 Continue\r\n"));
1398}
1399
1400TEST_F(HttpNetworkTransactionTest, ConnectStatus101) {
1401 ConnectStatusHelper(MockRead("HTTP/1.1 101 Switching Protocols\r\n"));
1402}
1403
1404TEST_F(HttpNetworkTransactionTest, ConnectStatus201) {
1405 ConnectStatusHelper(MockRead("HTTP/1.1 201 Created\r\n"));
1406}
1407
1408TEST_F(HttpNetworkTransactionTest, ConnectStatus202) {
1409 ConnectStatusHelper(MockRead("HTTP/1.1 202 Accepted\r\n"));
1410}
1411
1412TEST_F(HttpNetworkTransactionTest, ConnectStatus203) {
1413 ConnectStatusHelper(
1414 MockRead("HTTP/1.1 203 Non-Authoritative Information\r\n"));
1415}
1416
1417TEST_F(HttpNetworkTransactionTest, ConnectStatus204) {
1418 ConnectStatusHelper(MockRead("HTTP/1.1 204 No Content\r\n"));
1419}
1420
1421TEST_F(HttpNetworkTransactionTest, ConnectStatus205) {
1422 ConnectStatusHelper(MockRead("HTTP/1.1 205 Reset Content\r\n"));
1423}
1424
1425TEST_F(HttpNetworkTransactionTest, ConnectStatus206) {
1426 ConnectStatusHelper(MockRead("HTTP/1.1 206 Partial Content\r\n"));
1427}
1428
1429TEST_F(HttpNetworkTransactionTest, ConnectStatus300) {
1430 ConnectStatusHelper(MockRead("HTTP/1.1 300 Multiple Choices\r\n"));
1431}
1432
1433TEST_F(HttpNetworkTransactionTest, ConnectStatus301) {
1434 ConnectStatusHelper(MockRead("HTTP/1.1 301 Moved Permanently\r\n"));
1435}
1436
1437TEST_F(HttpNetworkTransactionTest, ConnectStatus302) {
1438 ConnectStatusHelper(MockRead("HTTP/1.1 302 Found\r\n"));
1439}
1440
1441TEST_F(HttpNetworkTransactionTest, ConnectStatus303) {
1442 ConnectStatusHelper(MockRead("HTTP/1.1 303 See Other\r\n"));
1443}
1444
1445TEST_F(HttpNetworkTransactionTest, ConnectStatus304) {
1446 ConnectStatusHelper(MockRead("HTTP/1.1 304 Not Modified\r\n"));
1447}
1448
1449TEST_F(HttpNetworkTransactionTest, ConnectStatus305) {
1450 ConnectStatusHelper(MockRead("HTTP/1.1 305 Use Proxy\r\n"));
1451}
1452
1453TEST_F(HttpNetworkTransactionTest, ConnectStatus306) {
1454 ConnectStatusHelper(MockRead("HTTP/1.1 306\r\n"));
1455}
1456
1457TEST_F(HttpNetworkTransactionTest, ConnectStatus307) {
1458 ConnectStatusHelper(MockRead("HTTP/1.1 307 Temporary Redirect\r\n"));
1459}
1460
1461TEST_F(HttpNetworkTransactionTest, ConnectStatus400) {
1462 ConnectStatusHelper(MockRead("HTTP/1.1 400 Bad Request\r\n"));
1463}
1464
1465TEST_F(HttpNetworkTransactionTest, ConnectStatus401) {
1466 ConnectStatusHelper(MockRead("HTTP/1.1 401 Unauthorized\r\n"));
1467}
1468
1469TEST_F(HttpNetworkTransactionTest, ConnectStatus402) {
1470 ConnectStatusHelper(MockRead("HTTP/1.1 402 Payment Required\r\n"));
1471}
1472
1473TEST_F(HttpNetworkTransactionTest, ConnectStatus403) {
1474 ConnectStatusHelper(MockRead("HTTP/1.1 403 Forbidden\r\n"));
1475}
1476
1477TEST_F(HttpNetworkTransactionTest, ConnectStatus404) {
1478 ConnectStatusHelper(MockRead("HTTP/1.1 404 Not Found\r\n"));
1479}
1480
1481TEST_F(HttpNetworkTransactionTest, ConnectStatus405) {
1482 ConnectStatusHelper(MockRead("HTTP/1.1 405 Method Not Allowed\r\n"));
1483}
1484
1485TEST_F(HttpNetworkTransactionTest, ConnectStatus406) {
1486 ConnectStatusHelper(MockRead("HTTP/1.1 406 Not Acceptable\r\n"));
1487}
1488
1489TEST_F(HttpNetworkTransactionTest, ConnectStatus407) {
1490 ConnectStatusHelperWithExpectedStatus(
1491 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
[email protected]1c773ea12009-04-28 19:58:421492 ERR_PROXY_AUTH_REQUESTED);
[email protected]c744cf22009-02-27 07:28:081493}
1494
1495TEST_F(HttpNetworkTransactionTest, ConnectStatus408) {
1496 ConnectStatusHelper(MockRead("HTTP/1.1 408 Request Timeout\r\n"));
1497}
1498
1499TEST_F(HttpNetworkTransactionTest, ConnectStatus409) {
1500 ConnectStatusHelper(MockRead("HTTP/1.1 409 Conflict\r\n"));
1501}
1502
1503TEST_F(HttpNetworkTransactionTest, ConnectStatus410) {
1504 ConnectStatusHelper(MockRead("HTTP/1.1 410 Gone\r\n"));
1505}
1506
1507TEST_F(HttpNetworkTransactionTest, ConnectStatus411) {
1508 ConnectStatusHelper(MockRead("HTTP/1.1 411 Length Required\r\n"));
1509}
1510
1511TEST_F(HttpNetworkTransactionTest, ConnectStatus412) {
1512 ConnectStatusHelper(MockRead("HTTP/1.1 412 Precondition Failed\r\n"));
1513}
1514
1515TEST_F(HttpNetworkTransactionTest, ConnectStatus413) {
1516 ConnectStatusHelper(MockRead("HTTP/1.1 413 Request Entity Too Large\r\n"));
1517}
1518
1519TEST_F(HttpNetworkTransactionTest, ConnectStatus414) {
1520 ConnectStatusHelper(MockRead("HTTP/1.1 414 Request-URI Too Long\r\n"));
1521}
1522
1523TEST_F(HttpNetworkTransactionTest, ConnectStatus415) {
1524 ConnectStatusHelper(MockRead("HTTP/1.1 415 Unsupported Media Type\r\n"));
1525}
1526
1527TEST_F(HttpNetworkTransactionTest, ConnectStatus416) {
1528 ConnectStatusHelper(
1529 MockRead("HTTP/1.1 416 Requested Range Not Satisfiable\r\n"));
1530}
1531
1532TEST_F(HttpNetworkTransactionTest, ConnectStatus417) {
1533 ConnectStatusHelper(MockRead("HTTP/1.1 417 Expectation Failed\r\n"));
1534}
1535
1536TEST_F(HttpNetworkTransactionTest, ConnectStatus500) {
1537 ConnectStatusHelper(MockRead("HTTP/1.1 500 Internal Server Error\r\n"));
1538}
1539
1540TEST_F(HttpNetworkTransactionTest, ConnectStatus501) {
1541 ConnectStatusHelper(MockRead("HTTP/1.1 501 Not Implemented\r\n"));
1542}
1543
1544TEST_F(HttpNetworkTransactionTest, ConnectStatus502) {
1545 ConnectStatusHelper(MockRead("HTTP/1.1 502 Bad Gateway\r\n"));
1546}
1547
1548TEST_F(HttpNetworkTransactionTest, ConnectStatus503) {
1549 ConnectStatusHelper(MockRead("HTTP/1.1 503 Service Unavailable\r\n"));
1550}
1551
1552TEST_F(HttpNetworkTransactionTest, ConnectStatus504) {
1553 ConnectStatusHelper(MockRead("HTTP/1.1 504 Gateway Timeout\r\n"));
1554}
1555
1556TEST_F(HttpNetworkTransactionTest, ConnectStatus505) {
1557 ConnectStatusHelper(MockRead("HTTP/1.1 505 HTTP Version Not Supported\r\n"));
1558}
1559
[email protected]038e9a32008-10-08 22:40:161560// Test the flow when both the proxy server AND origin server require
1561// authentication. Again, this uses basic auth for both since that is
1562// the simplest to mock.
1563TEST_F(HttpNetworkTransactionTest, BasicAuthProxyThenServer) {
[email protected]228ff742009-06-05 01:19:591564 SessionDependencies session_deps(CreateFixedProxyService("myproxy:70"));
[email protected]db8f44c2008-12-13 04:52:011565
[email protected]038e9a32008-10-08 22:40:161566 // Configure against proxy server "myproxy:70".
[email protected]1c773ea12009-04-28 19:58:421567 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(
[email protected]5695b8c2009-09-30 21:36:431568 CreateSession(&session_deps)));
[email protected]038e9a32008-10-08 22:40:161569
[email protected]1c773ea12009-04-28 19:58:421570 HttpRequestInfo request;
[email protected]038e9a32008-10-08 22:40:161571 request.method = "GET";
1572 request.url = GURL("http://www.google.com/");
1573 request.load_flags = 0;
1574
[email protected]f9ee6b52008-11-08 06:46:231575 MockWrite data_writes1[] = {
1576 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
1577 "Host: www.google.com\r\n"
1578 "Proxy-Connection: keep-alive\r\n\r\n"),
1579 };
1580
[email protected]038e9a32008-10-08 22:40:161581 MockRead data_reads1[] = {
1582 MockRead("HTTP/1.0 407 Unauthorized\r\n"),
1583 // Give a couple authenticate options (only the middle one is actually
1584 // supported).
[email protected]22927ad2009-09-21 19:56:191585 MockRead("Proxy-Authenticate: Basic invalid\r\n"), // Malformed.
[email protected]038e9a32008-10-08 22:40:161586 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1587 MockRead("Proxy-Authenticate: UNSUPPORTED realm=\"FOO\"\r\n"),
1588 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1589 // Large content-length -- won't matter, as connection will be reset.
1590 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:421591 MockRead(false, ERR_FAILED),
[email protected]038e9a32008-10-08 22:40:161592 };
1593
1594 // After calling trans->RestartWithAuth() the first time, this is the
1595 // request we should be issuing -- the final header line contains the
1596 // proxy's credentials.
1597 MockWrite data_writes2[] = {
1598 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
1599 "Host: www.google.com\r\n"
1600 "Proxy-Connection: keep-alive\r\n"
1601 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
1602 };
1603
1604 // Now the proxy server lets the request pass through to origin server.
1605 // The origin server responds with a 401.
1606 MockRead data_reads2[] = {
1607 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
1608 // Note: We are using the same realm-name as the proxy server. This is
1609 // completely valid, as realms are unique across hosts.
1610 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1611 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1612 MockRead("Content-Length: 2000\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:421613 MockRead(false, ERR_FAILED), // Won't be reached.
[email protected]038e9a32008-10-08 22:40:161614 };
1615
1616 // After calling trans->RestartWithAuth() the second time, we should send
1617 // the credentials for both the proxy and origin server.
1618 MockWrite data_writes3[] = {
1619 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
1620 "Host: www.google.com\r\n"
1621 "Proxy-Connection: keep-alive\r\n"
1622 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n"
1623 "Authorization: Basic Zm9vMjpiYXIy\r\n\r\n"),
1624 };
1625
1626 // Lastly we get the desired content.
1627 MockRead data_reads3[] = {
1628 MockRead("HTTP/1.0 200 OK\r\n"),
1629 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1630 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:421631 MockRead(false, OK),
[email protected]038e9a32008-10-08 22:40:161632 };
1633
[email protected]31a2bfe2010-02-09 08:03:391634 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
1635 data_writes1, arraysize(data_writes1));
1636 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
1637 data_writes2, arraysize(data_writes2));
1638 StaticSocketDataProvider data3(data_reads3, arraysize(data_reads3),
1639 data_writes3, arraysize(data_writes3));
[email protected]5ecc992a42009-11-11 01:41:591640 session_deps.socket_factory.AddSocketDataProvider(&data1);
1641 session_deps.socket_factory.AddSocketDataProvider(&data2);
1642 session_deps.socket_factory.AddSocketDataProvider(&data3);
[email protected]038e9a32008-10-08 22:40:161643
1644 TestCompletionCallback callback1;
1645
[email protected]684970b2009-08-14 04:54:461646 int rv = trans->Start(&request, &callback1, NULL);
[email protected]1c773ea12009-04-28 19:58:421647 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]038e9a32008-10-08 22:40:161648
1649 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421650 EXPECT_EQ(OK, rv);
[email protected]038e9a32008-10-08 22:40:161651
[email protected]1c773ea12009-04-28 19:58:421652 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]038e9a32008-10-08 22:40:161653 EXPECT_FALSE(response == NULL);
1654
1655 // The password prompt info should have been set in response->auth_challenge.
1656 EXPECT_FALSE(response->auth_challenge.get() == NULL);
1657
[email protected]71e4573a2009-05-21 22:03:001658 EXPECT_EQ(L"myproxy:70", response->auth_challenge->host_and_port);
[email protected]038e9a32008-10-08 22:40:161659 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
1660 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
1661
1662 TestCompletionCallback callback2;
1663
1664 rv = trans->RestartWithAuth(L"foo", L"bar", &callback2);
[email protected]1c773ea12009-04-28 19:58:421665 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]038e9a32008-10-08 22:40:161666
1667 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421668 EXPECT_EQ(OK, rv);
[email protected]038e9a32008-10-08 22:40:161669
1670 response = trans->GetResponseInfo();
1671 EXPECT_FALSE(response == NULL);
1672 EXPECT_FALSE(response->auth_challenge.get() == NULL);
1673
[email protected]71e4573a2009-05-21 22:03:001674 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
[email protected]038e9a32008-10-08 22:40:161675 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
1676 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
1677
1678 TestCompletionCallback callback3;
1679
1680 rv = trans->RestartWithAuth(L"foo2", L"bar2", &callback3);
[email protected]1c773ea12009-04-28 19:58:421681 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]038e9a32008-10-08 22:40:161682
1683 rv = callback3.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421684 EXPECT_EQ(OK, rv);
[email protected]038e9a32008-10-08 22:40:161685
1686 response = trans->GetResponseInfo();
1687 EXPECT_TRUE(response->auth_challenge.get() == NULL);
1688 EXPECT_EQ(100, response->headers->GetContentLength());
[email protected]038e9a32008-10-08 22:40:161689}
[email protected]4ddaf2502008-10-23 18:26:191690
[email protected]ea9dc9a2009-09-05 00:43:321691// For the NTLM implementation using SSPI, we skip the NTLM tests since we
1692// can't hook into its internals to cause it to generate predictable NTLM
1693// authorization headers.
1694#if defined(NTLM_PORTABLE)
[email protected]385a4672009-03-11 22:21:291695// The NTLM authentication unit tests were generated by capturing the HTTP
1696// requests and responses using Fiddler 2 and inspecting the generated random
1697// bytes in the debugger.
1698
1699// Enter the correct password and authenticate successfully.
1700TEST_F(HttpNetworkTransactionTest, NTLMAuth1) {
[email protected]1c773ea12009-04-28 19:58:421701 HttpAuthHandlerNTLM::ScopedProcSetter proc_setter(MockGenerateRandom1,
[email protected]fe2bc6a2009-03-23 16:52:201702 MockGetHostName);
[email protected]228ff742009-06-05 01:19:591703 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:401704 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:431705 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]3f918782009-02-28 01:29:241706
[email protected]1c773ea12009-04-28 19:58:421707 HttpRequestInfo request;
[email protected]3f918782009-02-28 01:29:241708 request.method = "GET";
1709 request.url = GURL("http://172.22.68.17/kids/login.aspx");
1710 request.load_flags = 0;
1711
1712 MockWrite data_writes1[] = {
1713 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
1714 "Host: 172.22.68.17\r\n"
1715 "Connection: keep-alive\r\n\r\n"),
1716 };
1717
1718 MockRead data_reads1[] = {
1719 MockRead("HTTP/1.1 401 Access Denied\r\n"),
1720 // Negotiate and NTLM are often requested together. We only support NTLM.
1721 MockRead("WWW-Authenticate: Negotiate\r\n"),
1722 MockRead("WWW-Authenticate: NTLM\r\n"),
1723 MockRead("Connection: close\r\n"),
1724 MockRead("Content-Length: 42\r\n"),
[email protected]076c85082009-04-10 23:21:361725 MockRead("Content-Type: text/html\r\n\r\n"),
[email protected]3f918782009-02-28 01:29:241726 // Missing content -- won't matter, as connection will be reset.
[email protected]1c773ea12009-04-28 19:58:421727 MockRead(false, ERR_UNEXPECTED),
[email protected]3f918782009-02-28 01:29:241728 };
1729
1730 MockWrite data_writes2[] = {
[email protected]0757e7702009-03-27 04:00:221731 // After restarting with a null identity, this is the
[email protected]3f918782009-02-28 01:29:241732 // request we should be issuing -- the final header line contains a Type
1733 // 1 message.
1734 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
1735 "Host: 172.22.68.17\r\n"
1736 "Connection: keep-alive\r\n"
1737 "Authorization: NTLM "
1738 "TlRMTVNTUAABAAAAB4IIAAAAAAAAAAAAAAAAAAAAAAA=\r\n\r\n"),
1739
1740 // After calling trans->RestartWithAuth(), we should send a Type 3 message
1741 // (the credentials for the origin server). The second request continues
1742 // on the same connection.
1743 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
1744 "Host: 172.22.68.17\r\n"
1745 "Connection: keep-alive\r\n"
[email protected]385a4672009-03-11 22:21:291746 "Authorization: NTLM TlRMTVNTUAADAAAAGAAYAGgAAAAYABgAgA"
1747 "AAAAAAAABAAAAAGAAYAEAAAAAQABAAWAAAAAAAAAAAAAAABYIIAHQA"
1748 "ZQBzAHQAaQBuAGcALQBuAHQAbABtAFcAVABDAC0AVwBJAE4ANwBVKW"
1749 "Yma5xzVAAAAAAAAAAAAAAAAAAAAACH+gWcm+YsP9Tqb9zCR3WAeZZX"
1750 "ahlhx5I=\r\n\r\n"),
[email protected]3f918782009-02-28 01:29:241751 };
1752
1753 MockRead data_reads2[] = {
1754 // The origin server responds with a Type 2 message.
1755 MockRead("HTTP/1.1 401 Access Denied\r\n"),
1756 MockRead("WWW-Authenticate: NTLM "
[email protected]385a4672009-03-11 22:21:291757 "TlRMTVNTUAACAAAADAAMADgAAAAFgokCjGpMpPGlYKkAAAAAAAAAALo"
[email protected]3f918782009-02-28 01:29:241758 "AugBEAAAABQEoCgAAAA9HAE8ATwBHAEwARQACAAwARwBPAE8ARwBMAE"
1759 "UAAQAaAEEASwBFAEUAUwBBAFIAQQAtAEMATwBSAFAABAAeAGMAbwByA"
1760 "HAALgBnAG8AbwBnAGwAZQAuAGMAbwBtAAMAQABhAGsAZQBlAHMAYQBy"
1761 "AGEALQBjAG8AcgBwAC4AYQBkAC4AYwBvAHIAcAAuAGcAbwBvAGcAbAB"
1762 "lAC4AYwBvAG0ABQAeAGMAbwByAHAALgBnAG8AbwBnAGwAZQAuAGMAbw"
1763 "BtAAAAAAA=\r\n"),
1764 MockRead("Content-Length: 42\r\n"),
[email protected]076c85082009-04-10 23:21:361765 MockRead("Content-Type: text/html\r\n\r\n"),
[email protected]3f918782009-02-28 01:29:241766 MockRead("You are not authorized to view this page\r\n"),
1767
1768 // Lastly we get the desired content.
1769 MockRead("HTTP/1.1 200 OK\r\n"),
1770 MockRead("Content-Type: text/html; charset=utf-8\r\n"),
1771 MockRead("Content-Length: 13\r\n\r\n"),
1772 MockRead("Please Login\r\n"),
[email protected]1c773ea12009-04-28 19:58:421773 MockRead(false, OK),
[email protected]3f918782009-02-28 01:29:241774 };
1775
[email protected]31a2bfe2010-02-09 08:03:391776 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
1777 data_writes1, arraysize(data_writes1));
1778 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
1779 data_writes2, arraysize(data_writes2));
[email protected]5ecc992a42009-11-11 01:41:591780 session_deps.socket_factory.AddSocketDataProvider(&data1);
1781 session_deps.socket_factory.AddSocketDataProvider(&data2);
[email protected]3f918782009-02-28 01:29:241782
1783 TestCompletionCallback callback1;
1784
[email protected]684970b2009-08-14 04:54:461785 int rv = trans->Start(&request, &callback1, NULL);
[email protected]1c773ea12009-04-28 19:58:421786 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]3f918782009-02-28 01:29:241787
1788 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421789 EXPECT_EQ(OK, rv);
[email protected]3f918782009-02-28 01:29:241790
[email protected]0757e7702009-03-27 04:00:221791 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
1792 TestCompletionCallback callback2;
1793 rv = trans->RestartWithAuth(std::wstring(), std::wstring(), &callback2);
[email protected]1c773ea12009-04-28 19:58:421794 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]0757e7702009-03-27 04:00:221795 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421796 EXPECT_EQ(OK, rv);
[email protected]0757e7702009-03-27 04:00:221797 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
1798
[email protected]1c773ea12009-04-28 19:58:421799 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]3f918782009-02-28 01:29:241800 EXPECT_FALSE(response == NULL);
1801
1802 // The password prompt info should have been set in response->auth_challenge.
1803 EXPECT_FALSE(response->auth_challenge.get() == NULL);
1804
[email protected]71e4573a2009-05-21 22:03:001805 EXPECT_EQ(L"172.22.68.17:80", response->auth_challenge->host_and_port);
[email protected]3f918782009-02-28 01:29:241806 EXPECT_EQ(L"", response->auth_challenge->realm);
1807 EXPECT_EQ(L"ntlm", response->auth_challenge->scheme);
1808
[email protected]0757e7702009-03-27 04:00:221809 TestCompletionCallback callback3;
[email protected]3f918782009-02-28 01:29:241810
[email protected]0757e7702009-03-27 04:00:221811 rv = trans->RestartWithAuth(L"testing-ntlm", L"testing-ntlm", &callback3);
[email protected]1c773ea12009-04-28 19:58:421812 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]3f918782009-02-28 01:29:241813
[email protected]0757e7702009-03-27 04:00:221814 rv = callback3.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421815 EXPECT_EQ(OK, rv);
[email protected]3f918782009-02-28 01:29:241816
1817 response = trans->GetResponseInfo();
1818 EXPECT_TRUE(response->auth_challenge.get() == NULL);
1819 EXPECT_EQ(13, response->headers->GetContentLength());
1820}
1821
[email protected]385a4672009-03-11 22:21:291822// Enter a wrong password, and then the correct one.
1823TEST_F(HttpNetworkTransactionTest, NTLMAuth2) {
[email protected]1c773ea12009-04-28 19:58:421824 HttpAuthHandlerNTLM::ScopedProcSetter proc_setter(MockGenerateRandom2,
[email protected]fe2bc6a2009-03-23 16:52:201825 MockGetHostName);
[email protected]228ff742009-06-05 01:19:591826 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:401827 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:431828 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]385a4672009-03-11 22:21:291829
[email protected]1c773ea12009-04-28 19:58:421830 HttpRequestInfo request;
[email protected]385a4672009-03-11 22:21:291831 request.method = "GET";
1832 request.url = GURL("http://172.22.68.17/kids/login.aspx");
1833 request.load_flags = 0;
1834
1835 MockWrite data_writes1[] = {
1836 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
1837 "Host: 172.22.68.17\r\n"
1838 "Connection: keep-alive\r\n\r\n"),
1839 };
1840
1841 MockRead data_reads1[] = {
1842 MockRead("HTTP/1.1 401 Access Denied\r\n"),
1843 // Negotiate and NTLM are often requested together. We only support NTLM.
1844 MockRead("WWW-Authenticate: Negotiate\r\n"),
1845 MockRead("WWW-Authenticate: NTLM\r\n"),
1846 MockRead("Connection: close\r\n"),
1847 MockRead("Content-Length: 42\r\n"),
[email protected]076c85082009-04-10 23:21:361848 MockRead("Content-Type: text/html\r\n\r\n"),
[email protected]385a4672009-03-11 22:21:291849 // Missing content -- won't matter, as connection will be reset.
[email protected]1c773ea12009-04-28 19:58:421850 MockRead(false, ERR_UNEXPECTED),
[email protected]385a4672009-03-11 22:21:291851 };
1852
1853 MockWrite data_writes2[] = {
[email protected]0757e7702009-03-27 04:00:221854 // After restarting with a null identity, this is the
[email protected]385a4672009-03-11 22:21:291855 // request we should be issuing -- the final header line contains a Type
1856 // 1 message.
1857 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
1858 "Host: 172.22.68.17\r\n"
1859 "Connection: keep-alive\r\n"
1860 "Authorization: NTLM "
1861 "TlRMTVNTUAABAAAAB4IIAAAAAAAAAAAAAAAAAAAAAAA=\r\n\r\n"),
1862
1863 // After calling trans->RestartWithAuth(), we should send a Type 3 message
1864 // (the credentials for the origin server). The second request continues
1865 // on the same connection.
1866 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
1867 "Host: 172.22.68.17\r\n"
1868 "Connection: keep-alive\r\n"
1869 "Authorization: NTLM TlRMTVNTUAADAAAAGAAYAGgAAAAYABgAgA"
1870 "AAAAAAAABAAAAAGAAYAEAAAAAQABAAWAAAAAAAAAAAAAAABYIIAHQA"
1871 "ZQBzAHQAaQBuAGcALQBuAHQAbABtAFcAVABDAC0AVwBJAE4ANwCWeY"
1872 "XnSZNwoQAAAAAAAAAAAAAAAAAAAADLa34/phTTKzNTWdub+uyFleOj"
1873 "4Ww7b7E=\r\n\r\n"),
1874 };
1875
1876 MockRead data_reads2[] = {
1877 // The origin server responds with a Type 2 message.
1878 MockRead("HTTP/1.1 401 Access Denied\r\n"),
1879 MockRead("WWW-Authenticate: NTLM "
1880 "TlRMTVNTUAACAAAADAAMADgAAAAFgokCbVWUZezVGpAAAAAAAAAAALo"
1881 "AugBEAAAABQEoCgAAAA9HAE8ATwBHAEwARQACAAwARwBPAE8ARwBMAE"
1882 "UAAQAaAEEASwBFAEUAUwBBAFIAQQAtAEMATwBSAFAABAAeAGMAbwByA"
1883 "HAALgBnAG8AbwBnAGwAZQAuAGMAbwBtAAMAQABhAGsAZQBlAHMAYQBy"
1884 "AGEALQBjAG8AcgBwAC4AYQBkAC4AYwBvAHIAcAAuAGcAbwBvAGcAbAB"
1885 "lAC4AYwBvAG0ABQAeAGMAbwByAHAALgBnAG8AbwBnAGwAZQAuAGMAbw"
1886 "BtAAAAAAA=\r\n"),
1887 MockRead("Content-Length: 42\r\n"),
[email protected]076c85082009-04-10 23:21:361888 MockRead("Content-Type: text/html\r\n\r\n"),
[email protected]385a4672009-03-11 22:21:291889 MockRead("You are not authorized to view this page\r\n"),
1890
1891 // Wrong password.
1892 MockRead("HTTP/1.1 401 Access Denied\r\n"),
1893 MockRead("WWW-Authenticate: Negotiate\r\n"),
1894 MockRead("WWW-Authenticate: NTLM\r\n"),
1895 MockRead("Connection: close\r\n"),
1896 MockRead("Content-Length: 42\r\n"),
[email protected]076c85082009-04-10 23:21:361897 MockRead("Content-Type: text/html\r\n\r\n"),
[email protected]385a4672009-03-11 22:21:291898 // Missing content -- won't matter, as connection will be reset.
[email protected]1c773ea12009-04-28 19:58:421899 MockRead(false, ERR_UNEXPECTED),
[email protected]385a4672009-03-11 22:21:291900 };
1901
1902 MockWrite data_writes3[] = {
[email protected]0757e7702009-03-27 04:00:221903 // After restarting with a null identity, this is the
[email protected]385a4672009-03-11 22:21:291904 // request we should be issuing -- the final header line contains a Type
1905 // 1 message.
1906 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
1907 "Host: 172.22.68.17\r\n"
1908 "Connection: keep-alive\r\n"
1909 "Authorization: NTLM "
1910 "TlRMTVNTUAABAAAAB4IIAAAAAAAAAAAAAAAAAAAAAAA=\r\n\r\n"),
1911
1912 // After calling trans->RestartWithAuth(), we should send a Type 3 message
1913 // (the credentials for the origin server). The second request continues
1914 // on the same connection.
1915 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
1916 "Host: 172.22.68.17\r\n"
1917 "Connection: keep-alive\r\n"
1918 "Authorization: NTLM TlRMTVNTUAADAAAAGAAYAGgAAAAYABgAgA"
1919 "AAAAAAAABAAAAAGAAYAEAAAAAQABAAWAAAAAAAAAAAAAAABYIIAHQA"
1920 "ZQBzAHQAaQBuAGcALQBuAHQAbABtAFcAVABDAC0AVwBJAE4ANwBO54"
1921 "dFMVvTHwAAAAAAAAAAAAAAAAAAAACS7sT6Uzw7L0L//WUqlIaVWpbI"
1922 "+4MUm7c=\r\n\r\n"),
1923 };
1924
1925 MockRead data_reads3[] = {
1926 // The origin server responds with a Type 2 message.
1927 MockRead("HTTP/1.1 401 Access Denied\r\n"),
1928 MockRead("WWW-Authenticate: NTLM "
1929 "TlRMTVNTUAACAAAADAAMADgAAAAFgokCL24VN8dgOR8AAAAAAAAAALo"
1930 "AugBEAAAABQEoCgAAAA9HAE8ATwBHAEwARQACAAwARwBPAE8ARwBMAE"
1931 "UAAQAaAEEASwBFAEUAUwBBAFIAQQAtAEMATwBSAFAABAAeAGMAbwByA"
1932 "HAALgBnAG8AbwBnAGwAZQAuAGMAbwBtAAMAQABhAGsAZQBlAHMAYQBy"
1933 "AGEALQBjAG8AcgBwAC4AYQBkAC4AYwBvAHIAcAAuAGcAbwBvAGcAbAB"
1934 "lAC4AYwBvAG0ABQAeAGMAbwByAHAALgBnAG8AbwBnAGwAZQAuAGMAbw"
1935 "BtAAAAAAA=\r\n"),
1936 MockRead("Content-Length: 42\r\n"),
[email protected]076c85082009-04-10 23:21:361937 MockRead("Content-Type: text/html\r\n\r\n"),
[email protected]385a4672009-03-11 22:21:291938 MockRead("You are not authorized to view this page\r\n"),
1939
1940 // Lastly we get the desired content.
1941 MockRead("HTTP/1.1 200 OK\r\n"),
1942 MockRead("Content-Type: text/html; charset=utf-8\r\n"),
1943 MockRead("Content-Length: 13\r\n\r\n"),
1944 MockRead("Please Login\r\n"),
[email protected]1c773ea12009-04-28 19:58:421945 MockRead(false, OK),
[email protected]385a4672009-03-11 22:21:291946 };
1947
[email protected]31a2bfe2010-02-09 08:03:391948 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
1949 data_writes1, arraysize(data_writes1));
1950 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
1951 data_writes2, arraysize(data_writes2));
1952 StaticSocketDataProvider data3(data_reads3, arraysize(data_reads3),
1953 data_writes3, arraysize(data_writes3));
[email protected]5ecc992a42009-11-11 01:41:591954 session_deps.socket_factory.AddSocketDataProvider(&data1);
1955 session_deps.socket_factory.AddSocketDataProvider(&data2);
1956 session_deps.socket_factory.AddSocketDataProvider(&data3);
[email protected]385a4672009-03-11 22:21:291957
1958 TestCompletionCallback callback1;
1959
[email protected]684970b2009-08-14 04:54:461960 int rv = trans->Start(&request, &callback1, NULL);
[email protected]1c773ea12009-04-28 19:58:421961 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]385a4672009-03-11 22:21:291962
1963 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421964 EXPECT_EQ(OK, rv);
[email protected]385a4672009-03-11 22:21:291965
[email protected]0757e7702009-03-27 04:00:221966 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
[email protected]385a4672009-03-11 22:21:291967 TestCompletionCallback callback2;
[email protected]0757e7702009-03-27 04:00:221968 rv = trans->RestartWithAuth(std::wstring(), std::wstring(), &callback2);
[email protected]1c773ea12009-04-28 19:58:421969 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]385a4672009-03-11 22:21:291970 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421971 EXPECT_EQ(OK, rv);
[email protected]0757e7702009-03-27 04:00:221972 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
[email protected]385a4672009-03-11 22:21:291973
[email protected]1c773ea12009-04-28 19:58:421974 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]385a4672009-03-11 22:21:291975 EXPECT_FALSE(response == NULL);
1976
1977 // The password prompt info should have been set in response->auth_challenge.
1978 EXPECT_FALSE(response->auth_challenge.get() == NULL);
1979
[email protected]71e4573a2009-05-21 22:03:001980 EXPECT_EQ(L"172.22.68.17:80", response->auth_challenge->host_and_port);
[email protected]385a4672009-03-11 22:21:291981 EXPECT_EQ(L"", response->auth_challenge->realm);
1982 EXPECT_EQ(L"ntlm", response->auth_challenge->scheme);
1983
1984 TestCompletionCallback callback3;
1985
[email protected]0757e7702009-03-27 04:00:221986 // Enter the wrong password.
1987 rv = trans->RestartWithAuth(L"testing-ntlm", L"wrongpassword", &callback3);
[email protected]1c773ea12009-04-28 19:58:421988 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]385a4672009-03-11 22:21:291989
1990 rv = callback3.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421991 EXPECT_EQ(OK, rv);
[email protected]385a4672009-03-11 22:21:291992
[email protected]0757e7702009-03-27 04:00:221993 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
1994 TestCompletionCallback callback4;
1995 rv = trans->RestartWithAuth(std::wstring(), std::wstring(), &callback4);
[email protected]1c773ea12009-04-28 19:58:421996 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]0757e7702009-03-27 04:00:221997 rv = callback4.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421998 EXPECT_EQ(OK, rv);
[email protected]0757e7702009-03-27 04:00:221999 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
2000
2001 response = trans->GetResponseInfo();
2002 EXPECT_FALSE(response == NULL);
2003
2004 // The password prompt info should have been set in response->auth_challenge.
2005 EXPECT_FALSE(response->auth_challenge.get() == NULL);
2006
[email protected]71e4573a2009-05-21 22:03:002007 EXPECT_EQ(L"172.22.68.17:80", response->auth_challenge->host_and_port);
[email protected]0757e7702009-03-27 04:00:222008 EXPECT_EQ(L"", response->auth_challenge->realm);
2009 EXPECT_EQ(L"ntlm", response->auth_challenge->scheme);
2010
2011 TestCompletionCallback callback5;
2012
2013 // Now enter the right password.
2014 rv = trans->RestartWithAuth(L"testing-ntlm", L"testing-ntlm", &callback5);
[email protected]1c773ea12009-04-28 19:58:422015 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]0757e7702009-03-27 04:00:222016
2017 rv = callback5.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422018 EXPECT_EQ(OK, rv);
[email protected]0757e7702009-03-27 04:00:222019
[email protected]385a4672009-03-11 22:21:292020 response = trans->GetResponseInfo();
2021 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2022 EXPECT_EQ(13, response->headers->GetContentLength());
2023}
[email protected]ea9dc9a2009-09-05 00:43:322024#endif // NTLM_PORTABLE
[email protected]385a4672009-03-11 22:21:292025
[email protected]4ddaf2502008-10-23 18:26:192026// Test reading a server response which has only headers, and no body.
2027// After some maximum number of bytes is consumed, the transaction should
2028// fail with ERR_RESPONSE_HEADERS_TOO_BIG.
2029TEST_F(HttpNetworkTransactionTest, LargeHeadersNoBody) {
[email protected]228ff742009-06-05 01:19:592030 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:402031 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:432032 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]4ddaf2502008-10-23 18:26:192033
[email protected]1c773ea12009-04-28 19:58:422034 HttpRequestInfo request;
[email protected]4ddaf2502008-10-23 18:26:192035 request.method = "GET";
2036 request.url = GURL("http://www.google.com/");
2037 request.load_flags = 0;
2038
[email protected]b75b7b2f2009-10-06 00:54:532039 // Respond with 300 kb of headers (we should fail after 256 kb).
[email protected]15a5ccf82008-10-23 19:57:432040 std::string large_headers_string;
[email protected]b75b7b2f2009-10-06 00:54:532041 FillLargeHeadersString(&large_headers_string, 300 * 1024);
[email protected]4ddaf2502008-10-23 18:26:192042
2043 MockRead data_reads[] = {
2044 MockRead("HTTP/1.0 200 OK\r\n"),
[email protected]15a5ccf82008-10-23 19:57:432045 MockRead(true, large_headers_string.data(), large_headers_string.size()),
[email protected]4ddaf2502008-10-23 18:26:192046 MockRead("\r\nBODY"),
[email protected]1c773ea12009-04-28 19:58:422047 MockRead(false, OK),
[email protected]4ddaf2502008-10-23 18:26:192048 };
[email protected]31a2bfe2010-02-09 08:03:392049 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:592050 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]4ddaf2502008-10-23 18:26:192051
2052 TestCompletionCallback callback;
2053
[email protected]684970b2009-08-14 04:54:462054 int rv = trans->Start(&request, &callback, NULL);
[email protected]1c773ea12009-04-28 19:58:422055 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]4ddaf2502008-10-23 18:26:192056
2057 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422058 EXPECT_EQ(ERR_RESPONSE_HEADERS_TOO_BIG, rv);
[email protected]4ddaf2502008-10-23 18:26:192059
[email protected]1c773ea12009-04-28 19:58:422060 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]4ddaf2502008-10-23 18:26:192061 EXPECT_TRUE(response == NULL);
2062}
[email protected]f4e426b2008-11-05 00:24:492063
2064// Make sure that we don't try to reuse a TCPClientSocket when failing to
2065// establish tunnel.
2066// http://code.google.com/p/chromium/issues/detail?id=3772
2067TEST_F(HttpNetworkTransactionTest, DontRecycleTCPSocketForSSLTunnel) {
2068 // Configure against proxy server "myproxy:70".
[email protected]228ff742009-06-05 01:19:592069 SessionDependencies session_deps(CreateFixedProxyService("myproxy:70"));
[email protected]db8f44c2008-12-13 04:52:012070
[email protected]228ff742009-06-05 01:19:592071 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]f4e426b2008-11-05 00:24:492072
[email protected]5695b8c2009-09-30 21:36:432073 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]f4e426b2008-11-05 00:24:492074
[email protected]1c773ea12009-04-28 19:58:422075 HttpRequestInfo request;
[email protected]f4e426b2008-11-05 00:24:492076 request.method = "GET";
2077 request.url = GURL("https://www.google.com/");
2078 request.load_flags = 0;
2079
2080 // Since we have proxy, should try to establish tunnel.
2081 MockWrite data_writes1[] = {
2082 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
[email protected]e44de5d2009-06-05 20:12:452083 "Host: www.google.com\r\n"
2084 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]f4e426b2008-11-05 00:24:492085 };
2086
[email protected]77848d12008-11-14 00:00:222087 // The proxy responds to the connect with a 404, using a persistent
[email protected]f4e426b2008-11-05 00:24:492088 // connection. Usually a proxy would return 501 (not implemented),
2089 // or 200 (tunnel established).
2090 MockRead data_reads1[] = {
2091 MockRead("HTTP/1.1 404 Not Found\r\n"),
2092 MockRead("Content-Length: 10\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422093 MockRead(false, ERR_UNEXPECTED), // Should not be reached.
[email protected]f4e426b2008-11-05 00:24:492094 };
2095
[email protected]31a2bfe2010-02-09 08:03:392096 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2097 data_writes1, arraysize(data_writes1));
[email protected]5ecc992a42009-11-11 01:41:592098 session_deps.socket_factory.AddSocketDataProvider(&data1);
[email protected]f4e426b2008-11-05 00:24:492099
2100 TestCompletionCallback callback1;
2101
[email protected]684970b2009-08-14 04:54:462102 int rv = trans->Start(&request, &callback1, NULL);
[email protected]1c773ea12009-04-28 19:58:422103 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f4e426b2008-11-05 00:24:492104
2105 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422106 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED, rv);
[email protected]f4e426b2008-11-05 00:24:492107
[email protected]1c773ea12009-04-28 19:58:422108 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]c744cf22009-02-27 07:28:082109 EXPECT_TRUE(response == NULL);
[email protected]f4e426b2008-11-05 00:24:492110
[email protected]b4404c02009-04-10 16:38:522111 // Empty the current queue. This is necessary because idle sockets are
2112 // added to the connection pool asynchronously with a PostTask.
2113 MessageLoop::current()->RunAllPending();
2114
[email protected]f4e426b2008-11-05 00:24:492115 // We now check to make sure the TCPClientSocket was not added back to
2116 // the pool.
[email protected]a937a06d2009-08-19 21:19:242117 EXPECT_EQ(0, session->tcp_socket_pool()->IdleSocketCount());
[email protected]f4e426b2008-11-05 00:24:492118 trans.reset();
[email protected]b4404c02009-04-10 16:38:522119 MessageLoop::current()->RunAllPending();
[email protected]f4e426b2008-11-05 00:24:492120 // Make sure that the socket didn't get recycled after calling the destructor.
[email protected]a937a06d2009-08-19 21:19:242121 EXPECT_EQ(0, session->tcp_socket_pool()->IdleSocketCount());
[email protected]f4e426b2008-11-05 00:24:492122}
[email protected]372d34a2008-11-05 21:30:512123
[email protected]1b157c02009-04-21 01:55:402124// Make sure that we recycle a socket after reading all of the response body.
2125TEST_F(HttpNetworkTransactionTest, RecycleSocket) {
[email protected]228ff742009-06-05 01:19:592126 SessionDependencies session_deps;
2127 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]1b157c02009-04-21 01:55:402128
[email protected]5695b8c2009-09-30 21:36:432129 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]1b157c02009-04-21 01:55:402130
[email protected]1c773ea12009-04-28 19:58:422131 HttpRequestInfo request;
[email protected]1b157c02009-04-21 01:55:402132 request.method = "GET";
2133 request.url = GURL("http://www.google.com/");
2134 request.load_flags = 0;
2135
2136 MockRead data_reads[] = {
2137 // A part of the response body is received with the response headers.
2138 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 11\r\n\r\nhel"),
2139 // The rest of the response body is received in two parts.
2140 MockRead("lo"),
2141 MockRead(" world"),
2142 MockRead("junk"), // Should not be read!!
[email protected]1c773ea12009-04-28 19:58:422143 MockRead(false, OK),
[email protected]1b157c02009-04-21 01:55:402144 };
2145
[email protected]31a2bfe2010-02-09 08:03:392146 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:592147 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1b157c02009-04-21 01:55:402148
2149 TestCompletionCallback callback;
2150
[email protected]684970b2009-08-14 04:54:462151 int rv = trans->Start(&request, &callback, NULL);
[email protected]1c773ea12009-04-28 19:58:422152 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]1b157c02009-04-21 01:55:402153
2154 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422155 EXPECT_EQ(OK, rv);
[email protected]1b157c02009-04-21 01:55:402156
[email protected]1c773ea12009-04-28 19:58:422157 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]1b157c02009-04-21 01:55:402158 EXPECT_TRUE(response != NULL);
2159
2160 EXPECT_TRUE(response->headers != NULL);
2161 std::string status_line = response->headers->GetStatusLine();
2162 EXPECT_EQ("HTTP/1.1 200 OK", status_line);
2163
[email protected]a937a06d2009-08-19 21:19:242164 EXPECT_EQ(0, session->tcp_socket_pool()->IdleSocketCount());
[email protected]1b157c02009-04-21 01:55:402165
2166 std::string response_data;
2167 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:422168 EXPECT_EQ(OK, rv);
[email protected]1b157c02009-04-21 01:55:402169 EXPECT_EQ("hello world", response_data);
2170
2171 // Empty the current queue. This is necessary because idle sockets are
2172 // added to the connection pool asynchronously with a PostTask.
2173 MessageLoop::current()->RunAllPending();
2174
2175 // We now check to make sure the socket was added back to the pool.
[email protected]a937a06d2009-08-19 21:19:242176 EXPECT_EQ(1, session->tcp_socket_pool()->IdleSocketCount());
[email protected]1b157c02009-04-21 01:55:402177}
2178
[email protected]b4404c02009-04-10 16:38:522179// Make sure that we recycle a socket after a zero-length response.
2180// http://crbug.com/9880
2181TEST_F(HttpNetworkTransactionTest, RecycleSocketAfterZeroContentLength) {
[email protected]228ff742009-06-05 01:19:592182 SessionDependencies session_deps;
2183 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]b4404c02009-04-10 16:38:522184
[email protected]5695b8c2009-09-30 21:36:432185 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]b4404c02009-04-10 16:38:522186
[email protected]1c773ea12009-04-28 19:58:422187 HttpRequestInfo request;
[email protected]b4404c02009-04-10 16:38:522188 request.method = "GET";
2189 request.url = GURL("http://www.google.com/csi?v=3&s=web&action=&"
2190 "tran=undefined&ei=mAXcSeegAo-SMurloeUN&"
2191 "e=17259,18167,19592,19773,19981,20133,20173,20233&"
2192 "rt=prt.2642,ol.2649,xjs.2951");
2193 request.load_flags = 0;
2194
2195 MockRead data_reads[] = {
2196 MockRead("HTTP/1.1 204 No Content\r\n"
2197 "Content-Length: 0\r\n"
2198 "Content-Type: text/html\r\n\r\n"),
2199 MockRead("junk"), // Should not be read!!
[email protected]1c773ea12009-04-28 19:58:422200 MockRead(false, OK),
[email protected]b4404c02009-04-10 16:38:522201 };
2202
[email protected]31a2bfe2010-02-09 08:03:392203 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:592204 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]b4404c02009-04-10 16:38:522205
2206 TestCompletionCallback callback;
2207
[email protected]684970b2009-08-14 04:54:462208 int rv = trans->Start(&request, &callback, NULL);
[email protected]1c773ea12009-04-28 19:58:422209 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]b4404c02009-04-10 16:38:522210
2211 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422212 EXPECT_EQ(OK, rv);
[email protected]b4404c02009-04-10 16:38:522213
[email protected]1c773ea12009-04-28 19:58:422214 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]b4404c02009-04-10 16:38:522215 EXPECT_TRUE(response != NULL);
2216
2217 EXPECT_TRUE(response->headers != NULL);
2218 std::string status_line = response->headers->GetStatusLine();
2219 EXPECT_EQ("HTTP/1.1 204 No Content", status_line);
2220
[email protected]a937a06d2009-08-19 21:19:242221 EXPECT_EQ(0, session->tcp_socket_pool()->IdleSocketCount());
[email protected]b4404c02009-04-10 16:38:522222
2223 std::string response_data;
2224 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:422225 EXPECT_EQ(OK, rv);
[email protected]b4404c02009-04-10 16:38:522226 EXPECT_EQ("", response_data);
2227
2228 // Empty the current queue. This is necessary because idle sockets are
2229 // added to the connection pool asynchronously with a PostTask.
2230 MessageLoop::current()->RunAllPending();
2231
2232 // We now check to make sure the socket was added back to the pool.
[email protected]a937a06d2009-08-19 21:19:242233 EXPECT_EQ(1, session->tcp_socket_pool()->IdleSocketCount());
[email protected]b4404c02009-04-10 16:38:522234}
2235
[email protected]372d34a2008-11-05 21:30:512236TEST_F(HttpNetworkTransactionTest, ResendRequestOnWriteBodyError) {
[email protected]1c773ea12009-04-28 19:58:422237 HttpRequestInfo request[2];
[email protected]372d34a2008-11-05 21:30:512238 // Transaction 1: a GET request that succeeds. The socket is recycled
2239 // after use.
2240 request[0].method = "GET";
2241 request[0].url = GURL("http://www.google.com/");
2242 request[0].load_flags = 0;
2243 // Transaction 2: a POST request. Reuses the socket kept alive from
2244 // transaction 1. The first attempts fails when writing the POST data.
2245 // This causes the transaction to retry with a new socket. The second
2246 // attempt succeeds.
2247 request[1].method = "POST";
2248 request[1].url = GURL("http://www.google.com/login.cgi");
[email protected]1c773ea12009-04-28 19:58:422249 request[1].upload_data = new UploadData;
[email protected]372d34a2008-11-05 21:30:512250 request[1].upload_data->AppendBytes("foo", 3);
2251 request[1].load_flags = 0;
2252
[email protected]228ff742009-06-05 01:19:592253 SessionDependencies session_deps;
2254 scoped_refptr<HttpNetworkSession> session = CreateSession(&session_deps);
[email protected]372d34a2008-11-05 21:30:512255
2256 // The first socket is used for transaction 1 and the first attempt of
2257 // transaction 2.
2258
2259 // The response of transaction 1.
2260 MockRead data_reads1[] = {
2261 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 11\r\n\r\n"),
2262 MockRead("hello world"),
[email protected]1c773ea12009-04-28 19:58:422263 MockRead(false, OK),
[email protected]372d34a2008-11-05 21:30:512264 };
2265 // The mock write results of transaction 1 and the first attempt of
2266 // transaction 2.
2267 MockWrite data_writes1[] = {
2268 MockWrite(false, 64), // GET
2269 MockWrite(false, 93), // POST
[email protected]1c773ea12009-04-28 19:58:422270 MockWrite(false, ERR_CONNECTION_ABORTED), // POST data
[email protected]372d34a2008-11-05 21:30:512271 };
[email protected]31a2bfe2010-02-09 08:03:392272 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2273 data_writes1, arraysize(data_writes1));
[email protected]372d34a2008-11-05 21:30:512274
2275 // The second socket is used for the second attempt of transaction 2.
2276
2277 // The response of transaction 2.
2278 MockRead data_reads2[] = {
2279 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 7\r\n\r\n"),
2280 MockRead("welcome"),
[email protected]1c773ea12009-04-28 19:58:422281 MockRead(false, OK),
[email protected]372d34a2008-11-05 21:30:512282 };
2283 // The mock write results of the second attempt of transaction 2.
2284 MockWrite data_writes2[] = {
2285 MockWrite(false, 93), // POST
2286 MockWrite(false, 3), // POST data
2287 };
[email protected]31a2bfe2010-02-09 08:03:392288 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
2289 data_writes2, arraysize(data_writes2));
[email protected]372d34a2008-11-05 21:30:512290
[email protected]5ecc992a42009-11-11 01:41:592291 session_deps.socket_factory.AddSocketDataProvider(&data1);
2292 session_deps.socket_factory.AddSocketDataProvider(&data2);
[email protected]372d34a2008-11-05 21:30:512293
2294 const char* kExpectedResponseData[] = {
2295 "hello world", "welcome"
2296 };
2297
2298 for (int i = 0; i < 2; ++i) {
[email protected]1c773ea12009-04-28 19:58:422299 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:432300 new HttpNetworkTransaction(session));
[email protected]372d34a2008-11-05 21:30:512301
2302 TestCompletionCallback callback;
2303
[email protected]684970b2009-08-14 04:54:462304 int rv = trans->Start(&request[i], &callback, NULL);
[email protected]1c773ea12009-04-28 19:58:422305 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]372d34a2008-11-05 21:30:512306
2307 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422308 EXPECT_EQ(OK, rv);
[email protected]372d34a2008-11-05 21:30:512309
[email protected]1c773ea12009-04-28 19:58:422310 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]372d34a2008-11-05 21:30:512311 EXPECT_TRUE(response != NULL);
2312
2313 EXPECT_TRUE(response->headers != NULL);
2314 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
2315
2316 std::string response_data;
2317 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:422318 EXPECT_EQ(OK, rv);
[email protected]372d34a2008-11-05 21:30:512319 EXPECT_EQ(kExpectedResponseData[i], response_data);
2320 }
2321}
[email protected]f9ee6b52008-11-08 06:46:232322
2323// Test the request-challenge-retry sequence for basic auth when there is
2324// an identity in the URL. The request should be sent as normal, but when
2325// it fails the identity from the URL is used to answer the challenge.
[email protected]ea9dc9a2009-09-05 00:43:322326TEST_F(HttpNetworkTransactionTest, AuthIdentityInURL) {
[email protected]228ff742009-06-05 01:19:592327 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:402328 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:432329 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]f9ee6b52008-11-08 06:46:232330
[email protected]1c773ea12009-04-28 19:58:422331 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:232332 request.method = "GET";
2333 // Note: the URL has a username:password in it.
[email protected]a97cca42009-08-14 01:00:292334 request.url = GURL("http://foo:b@[email protected]/");
2335
2336 // The password contains an escaped character -- for this test to pass it
2337 // will need to be unescaped by HttpNetworkTransaction.
2338 EXPECT_EQ("b%40r", request.url.password());
2339
[email protected]ea9dc9a2009-09-05 00:43:322340 request.load_flags = LOAD_NORMAL;
[email protected]f9ee6b52008-11-08 06:46:232341
2342 MockWrite data_writes1[] = {
2343 MockWrite("GET / HTTP/1.1\r\n"
2344 "Host: www.google.com\r\n"
2345 "Connection: keep-alive\r\n\r\n"),
2346 };
2347
2348 MockRead data_reads1[] = {
2349 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
2350 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2351 MockRead("Content-Length: 10\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422352 MockRead(false, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:232353 };
2354
2355 // After the challenge above, the transaction will be restarted using the
[email protected]ea9dc9a2009-09-05 00:43:322356 // identity from the url (foo, b@r) to answer the challenge.
[email protected]f9ee6b52008-11-08 06:46:232357 MockWrite data_writes2[] = {
2358 MockWrite("GET / HTTP/1.1\r\n"
2359 "Host: www.google.com\r\n"
2360 "Connection: keep-alive\r\n"
[email protected]a97cca42009-08-14 01:00:292361 "Authorization: Basic Zm9vOmJAcg==\r\n\r\n"),
[email protected]f9ee6b52008-11-08 06:46:232362 };
2363
2364 MockRead data_reads2[] = {
2365 MockRead("HTTP/1.0 200 OK\r\n"),
2366 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422367 MockRead(false, OK),
[email protected]f9ee6b52008-11-08 06:46:232368 };
2369
[email protected]31a2bfe2010-02-09 08:03:392370 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2371 data_writes1, arraysize(data_writes1));
2372 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
2373 data_writes2, arraysize(data_writes2));
[email protected]5ecc992a42009-11-11 01:41:592374 session_deps.socket_factory.AddSocketDataProvider(&data1);
2375 session_deps.socket_factory.AddSocketDataProvider(&data2);
[email protected]f9ee6b52008-11-08 06:46:232376
2377 TestCompletionCallback callback1;
2378
[email protected]684970b2009-08-14 04:54:462379 int rv = trans->Start(&request, &callback1, NULL);
[email protected]1c773ea12009-04-28 19:58:422380 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:232381
2382 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422383 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:232384
[email protected]0757e7702009-03-27 04:00:222385 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
2386 TestCompletionCallback callback2;
2387 rv = trans->RestartWithAuth(std::wstring(), std::wstring(), &callback2);
[email protected]1c773ea12009-04-28 19:58:422388 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]0757e7702009-03-27 04:00:222389 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422390 EXPECT_EQ(OK, rv);
[email protected]0757e7702009-03-27 04:00:222391 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
2392
[email protected]1c773ea12009-04-28 19:58:422393 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]f9ee6b52008-11-08 06:46:232394 EXPECT_FALSE(response == NULL);
2395
2396 // There is no challenge info, since the identity in URL worked.
2397 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2398
2399 EXPECT_EQ(100, response->headers->GetContentLength());
2400
2401 // Empty the current queue.
2402 MessageLoop::current()->RunAllPending();
2403}
2404
[email protected]ea9dc9a2009-09-05 00:43:322405// Test the request-challenge-retry sequence for basic auth when there is
2406// an incorrect identity in the URL. The identity from the URL should be used
2407// only once.
2408TEST_F(HttpNetworkTransactionTest, WrongAuthIdentityInURL) {
2409 SessionDependencies session_deps;
2410 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:432411 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]ea9dc9a2009-09-05 00:43:322412
2413 HttpRequestInfo request;
2414 request.method = "GET";
2415 // Note: the URL has a username:password in it. The password "baz" is
2416 // wrong (should be "bar").
2417 request.url = GURL("http://foo:[email protected]/");
2418
2419 request.load_flags = LOAD_NORMAL;
2420
2421 MockWrite data_writes1[] = {
2422 MockWrite("GET / HTTP/1.1\r\n"
2423 "Host: www.google.com\r\n"
2424 "Connection: keep-alive\r\n\r\n"),
2425 };
2426
2427 MockRead data_reads1[] = {
2428 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
2429 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2430 MockRead("Content-Length: 10\r\n\r\n"),
2431 MockRead(false, ERR_FAILED),
2432 };
2433
2434 // After the challenge above, the transaction will be restarted using the
2435 // identity from the url (foo, baz) to answer the challenge.
2436 MockWrite data_writes2[] = {
2437 MockWrite("GET / HTTP/1.1\r\n"
2438 "Host: www.google.com\r\n"
2439 "Connection: keep-alive\r\n"
2440 "Authorization: Basic Zm9vOmJheg==\r\n\r\n"),
2441 };
2442
2443 MockRead data_reads2[] = {
2444 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
2445 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2446 MockRead("Content-Length: 10\r\n\r\n"),
2447 MockRead(false, ERR_FAILED),
2448 };
2449
2450 // After the challenge above, the transaction will be restarted using the
2451 // identity supplied by the user (foo, bar) to answer the challenge.
2452 MockWrite data_writes3[] = {
2453 MockWrite("GET / HTTP/1.1\r\n"
2454 "Host: www.google.com\r\n"
2455 "Connection: keep-alive\r\n"
2456 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2457 };
2458
2459 MockRead data_reads3[] = {
2460 MockRead("HTTP/1.0 200 OK\r\n"),
2461 MockRead("Content-Length: 100\r\n\r\n"),
2462 MockRead(false, OK),
2463 };
2464
[email protected]31a2bfe2010-02-09 08:03:392465 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2466 data_writes1, arraysize(data_writes1));
2467 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
2468 data_writes2, arraysize(data_writes2));
2469 StaticSocketDataProvider data3(data_reads3, arraysize(data_reads3),
2470 data_writes3, arraysize(data_writes3));
[email protected]5ecc992a42009-11-11 01:41:592471 session_deps.socket_factory.AddSocketDataProvider(&data1);
2472 session_deps.socket_factory.AddSocketDataProvider(&data2);
2473 session_deps.socket_factory.AddSocketDataProvider(&data3);
[email protected]ea9dc9a2009-09-05 00:43:322474
2475 TestCompletionCallback callback1;
2476
2477 int rv = trans->Start(&request, &callback1, NULL);
2478 EXPECT_EQ(ERR_IO_PENDING, rv);
2479
2480 rv = callback1.WaitForResult();
2481 EXPECT_EQ(OK, rv);
2482
2483 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
2484 TestCompletionCallback callback2;
2485 rv = trans->RestartWithAuth(std::wstring(), std::wstring(), &callback2);
2486 EXPECT_EQ(ERR_IO_PENDING, rv);
2487 rv = callback2.WaitForResult();
2488 EXPECT_EQ(OK, rv);
2489 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
2490
2491 const HttpResponseInfo* response = trans->GetResponseInfo();
2492 EXPECT_FALSE(response == NULL);
2493 // The password prompt info should have been set in response->auth_challenge.
2494 EXPECT_FALSE(response->auth_challenge.get() == NULL);
2495
2496 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
2497 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
2498 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
2499
2500 TestCompletionCallback callback3;
2501 rv = trans->RestartWithAuth(L"foo", L"bar", &callback3);
2502 EXPECT_EQ(ERR_IO_PENDING, rv);
2503 rv = callback3.WaitForResult();
2504 EXPECT_EQ(OK, rv);
2505 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
2506
2507 response = trans->GetResponseInfo();
2508 EXPECT_FALSE(response == NULL);
2509
2510 // There is no challenge info, since the identity worked.
2511 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2512
2513 EXPECT_EQ(100, response->headers->GetContentLength());
2514
2515 // Empty the current queue.
2516 MessageLoop::current()->RunAllPending();
2517}
2518
[email protected]f9ee6b52008-11-08 06:46:232519// Test that previously tried username/passwords for a realm get re-used.
2520TEST_F(HttpNetworkTransactionTest, BasicAuthCacheAndPreauth) {
[email protected]228ff742009-06-05 01:19:592521 SessionDependencies session_deps;
2522 scoped_refptr<HttpNetworkSession> session = CreateSession(&session_deps);
[email protected]f9ee6b52008-11-08 06:46:232523
2524 // Transaction 1: authenticate (foo, bar) on MyRealm1
2525 {
[email protected]5695b8c2009-09-30 21:36:432526 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]f9ee6b52008-11-08 06:46:232527
[email protected]1c773ea12009-04-28 19:58:422528 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:232529 request.method = "GET";
2530 request.url = GURL("http://www.google.com/x/y/z");
2531 request.load_flags = 0;
2532
2533 MockWrite data_writes1[] = {
2534 MockWrite("GET /x/y/z HTTP/1.1\r\n"
2535 "Host: www.google.com\r\n"
2536 "Connection: keep-alive\r\n\r\n"),
2537 };
2538
2539 MockRead data_reads1[] = {
2540 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
2541 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2542 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422543 MockRead(false, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:232544 };
2545
2546 // Resend with authorization (username=foo, password=bar)
2547 MockWrite data_writes2[] = {
2548 MockWrite("GET /x/y/z HTTP/1.1\r\n"
2549 "Host: www.google.com\r\n"
2550 "Connection: keep-alive\r\n"
2551 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2552 };
2553
2554 // Sever accepts the authorization.
2555 MockRead data_reads2[] = {
2556 MockRead("HTTP/1.0 200 OK\r\n"),
2557 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422558 MockRead(false, OK),
[email protected]f9ee6b52008-11-08 06:46:232559 };
2560
[email protected]31a2bfe2010-02-09 08:03:392561 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2562 data_writes1, arraysize(data_writes1));
2563 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
2564 data_writes2, arraysize(data_writes2));
[email protected]5ecc992a42009-11-11 01:41:592565 session_deps.socket_factory.AddSocketDataProvider(&data1);
2566 session_deps.socket_factory.AddSocketDataProvider(&data2);
[email protected]f9ee6b52008-11-08 06:46:232567
2568 TestCompletionCallback callback1;
2569
[email protected]684970b2009-08-14 04:54:462570 int rv = trans->Start(&request, &callback1, NULL);
[email protected]1c773ea12009-04-28 19:58:422571 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:232572
2573 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422574 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:232575
[email protected]1c773ea12009-04-28 19:58:422576 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]f9ee6b52008-11-08 06:46:232577 EXPECT_FALSE(response == NULL);
2578
2579 // The password prompt info should have been set in
2580 // response->auth_challenge.
2581 EXPECT_FALSE(response->auth_challenge.get() == NULL);
2582
[email protected]71e4573a2009-05-21 22:03:002583 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
[email protected]f9ee6b52008-11-08 06:46:232584 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
2585 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
2586
2587 TestCompletionCallback callback2;
2588
2589 rv = trans->RestartWithAuth(L"foo", L"bar", &callback2);
[email protected]1c773ea12009-04-28 19:58:422590 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:232591
2592 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422593 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:232594
2595 response = trans->GetResponseInfo();
2596 EXPECT_FALSE(response == NULL);
2597 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2598 EXPECT_EQ(100, response->headers->GetContentLength());
2599 }
2600
2601 // ------------------------------------------------------------------------
2602
2603 // Transaction 2: authenticate (foo2, bar2) on MyRealm2
2604 {
[email protected]5695b8c2009-09-30 21:36:432605 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]f9ee6b52008-11-08 06:46:232606
[email protected]1c773ea12009-04-28 19:58:422607 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:232608 request.method = "GET";
2609 // Note that Transaction 1 was at /x/y/z, so this is in the same
2610 // protection space as MyRealm1.
2611 request.url = GURL("http://www.google.com/x/y/a/b");
2612 request.load_flags = 0;
2613
2614 MockWrite data_writes1[] = {
2615 MockWrite("GET /x/y/a/b HTTP/1.1\r\n"
2616 "Host: www.google.com\r\n"
2617 "Connection: keep-alive\r\n"
2618 // Send preemptive authorization for MyRealm1
2619 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2620 };
2621
2622 // The server didn't like the preemptive authorization, and
2623 // challenges us for a different realm (MyRealm2).
2624 MockRead data_reads1[] = {
2625 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
2626 MockRead("WWW-Authenticate: Basic realm=\"MyRealm2\"\r\n"),
2627 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422628 MockRead(false, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:232629 };
2630
2631 // Resend with authorization for MyRealm2 (username=foo2, password=bar2)
2632 MockWrite data_writes2[] = {
2633 MockWrite("GET /x/y/a/b HTTP/1.1\r\n"
2634 "Host: www.google.com\r\n"
2635 "Connection: keep-alive\r\n"
2636 "Authorization: Basic Zm9vMjpiYXIy\r\n\r\n"),
2637 };
2638
2639 // Sever accepts the authorization.
2640 MockRead data_reads2[] = {
2641 MockRead("HTTP/1.0 200 OK\r\n"),
2642 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422643 MockRead(false, OK),
[email protected]f9ee6b52008-11-08 06:46:232644 };
2645
[email protected]31a2bfe2010-02-09 08:03:392646 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2647 data_writes1, arraysize(data_writes1));
2648 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
2649 data_writes2, arraysize(data_writes2));
[email protected]5ecc992a42009-11-11 01:41:592650 session_deps.socket_factory.AddSocketDataProvider(&data1);
2651 session_deps.socket_factory.AddSocketDataProvider(&data2);
[email protected]f9ee6b52008-11-08 06:46:232652
2653 TestCompletionCallback callback1;
2654
[email protected]684970b2009-08-14 04:54:462655 int rv = trans->Start(&request, &callback1, NULL);
[email protected]1c773ea12009-04-28 19:58:422656 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:232657
2658 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422659 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:232660
[email protected]1c773ea12009-04-28 19:58:422661 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]f9ee6b52008-11-08 06:46:232662 EXPECT_FALSE(response == NULL);
2663
2664 // The password prompt info should have been set in
2665 // response->auth_challenge.
2666 EXPECT_FALSE(response->auth_challenge.get() == NULL);
2667
[email protected]71e4573a2009-05-21 22:03:002668 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
[email protected]f9ee6b52008-11-08 06:46:232669 EXPECT_EQ(L"MyRealm2", response->auth_challenge->realm);
2670 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
2671
2672 TestCompletionCallback callback2;
2673
2674 rv = trans->RestartWithAuth(L"foo2", L"bar2", &callback2);
[email protected]1c773ea12009-04-28 19:58:422675 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:232676
2677 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422678 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:232679
2680 response = trans->GetResponseInfo();
2681 EXPECT_FALSE(response == NULL);
2682 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2683 EXPECT_EQ(100, response->headers->GetContentLength());
2684 }
2685
2686 // ------------------------------------------------------------------------
2687
2688 // Transaction 3: Resend a request in MyRealm's protection space --
2689 // succeed with preemptive authorization.
2690 {
[email protected]5695b8c2009-09-30 21:36:432691 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]f9ee6b52008-11-08 06:46:232692
[email protected]1c773ea12009-04-28 19:58:422693 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:232694 request.method = "GET";
2695 request.url = GURL("http://www.google.com/x/y/z2");
2696 request.load_flags = 0;
2697
2698 MockWrite data_writes1[] = {
2699 MockWrite("GET /x/y/z2 HTTP/1.1\r\n"
2700 "Host: www.google.com\r\n"
2701 "Connection: keep-alive\r\n"
2702 // The authorization for MyRealm1 gets sent preemptively
2703 // (since the url is in the same protection space)
2704 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2705 };
2706
2707 // Sever accepts the preemptive authorization
2708 MockRead data_reads1[] = {
2709 MockRead("HTTP/1.0 200 OK\r\n"),
2710 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422711 MockRead(false, OK),
[email protected]f9ee6b52008-11-08 06:46:232712 };
2713
[email protected]31a2bfe2010-02-09 08:03:392714 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2715 data_writes1, arraysize(data_writes1));
[email protected]5ecc992a42009-11-11 01:41:592716 session_deps.socket_factory.AddSocketDataProvider(&data1);
[email protected]f9ee6b52008-11-08 06:46:232717
2718 TestCompletionCallback callback1;
2719
[email protected]684970b2009-08-14 04:54:462720 int rv = trans->Start(&request, &callback1, NULL);
[email protected]1c773ea12009-04-28 19:58:422721 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:232722
2723 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422724 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:232725
[email protected]1c773ea12009-04-28 19:58:422726 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]f9ee6b52008-11-08 06:46:232727 EXPECT_FALSE(response == NULL);
2728
2729 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2730 EXPECT_EQ(100, response->headers->GetContentLength());
2731 }
2732
2733 // ------------------------------------------------------------------------
2734
2735 // Transaction 4: request another URL in MyRealm (however the
2736 // url is not known to belong to the protection space, so no pre-auth).
2737 {
[email protected]5695b8c2009-09-30 21:36:432738 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]f9ee6b52008-11-08 06:46:232739
[email protected]1c773ea12009-04-28 19:58:422740 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:232741 request.method = "GET";
2742 request.url = GURL("http://www.google.com/x/1");
2743 request.load_flags = 0;
2744
2745 MockWrite data_writes1[] = {
2746 MockWrite("GET /x/1 HTTP/1.1\r\n"
2747 "Host: www.google.com\r\n"
2748 "Connection: keep-alive\r\n\r\n"),
2749 };
2750
2751 MockRead data_reads1[] = {
2752 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
2753 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2754 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422755 MockRead(false, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:232756 };
2757
2758 // Resend with authorization from MyRealm's cache.
2759 MockWrite data_writes2[] = {
2760 MockWrite("GET /x/1 HTTP/1.1\r\n"
2761 "Host: www.google.com\r\n"
2762 "Connection: keep-alive\r\n"
2763 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2764 };
2765
2766 // Sever accepts the authorization.
2767 MockRead data_reads2[] = {
2768 MockRead("HTTP/1.0 200 OK\r\n"),
2769 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422770 MockRead(false, OK),
[email protected]f9ee6b52008-11-08 06:46:232771 };
2772
[email protected]31a2bfe2010-02-09 08:03:392773 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2774 data_writes1, arraysize(data_writes1));
2775 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
2776 data_writes2, arraysize(data_writes2));
[email protected]5ecc992a42009-11-11 01:41:592777 session_deps.socket_factory.AddSocketDataProvider(&data1);
2778 session_deps.socket_factory.AddSocketDataProvider(&data2);
[email protected]f9ee6b52008-11-08 06:46:232779
2780 TestCompletionCallback callback1;
2781
[email protected]684970b2009-08-14 04:54:462782 int rv = trans->Start(&request, &callback1, NULL);
[email protected]1c773ea12009-04-28 19:58:422783 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:232784
2785 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422786 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:232787
[email protected]0757e7702009-03-27 04:00:222788 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
2789 TestCompletionCallback callback2;
2790 rv = trans->RestartWithAuth(std::wstring(), std::wstring(), &callback2);
[email protected]1c773ea12009-04-28 19:58:422791 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]0757e7702009-03-27 04:00:222792 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422793 EXPECT_EQ(OK, rv);
[email protected]0757e7702009-03-27 04:00:222794 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
2795
[email protected]1c773ea12009-04-28 19:58:422796 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]f9ee6b52008-11-08 06:46:232797 EXPECT_FALSE(response == NULL);
2798 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2799 EXPECT_EQ(100, response->headers->GetContentLength());
2800 }
2801
2802 // ------------------------------------------------------------------------
2803
2804 // Transaction 5: request a URL in MyRealm, but the server rejects the
2805 // cached identity. Should invalidate and re-prompt.
2806 {
[email protected]5695b8c2009-09-30 21:36:432807 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]f9ee6b52008-11-08 06:46:232808
[email protected]1c773ea12009-04-28 19:58:422809 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:232810 request.method = "GET";
2811 request.url = GURL("http://www.google.com/p/q/t");
2812 request.load_flags = 0;
2813
2814 MockWrite data_writes1[] = {
2815 MockWrite("GET /p/q/t HTTP/1.1\r\n"
2816 "Host: www.google.com\r\n"
2817 "Connection: keep-alive\r\n\r\n"),
2818 };
2819
2820 MockRead data_reads1[] = {
2821 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
2822 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2823 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422824 MockRead(false, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:232825 };
2826
2827 // Resend with authorization from cache for MyRealm.
2828 MockWrite data_writes2[] = {
2829 MockWrite("GET /p/q/t HTTP/1.1\r\n"
2830 "Host: www.google.com\r\n"
2831 "Connection: keep-alive\r\n"
2832 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2833 };
2834
2835 // Sever rejects the authorization.
2836 MockRead data_reads2[] = {
2837 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
2838 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2839 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422840 MockRead(false, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:232841 };
2842
2843 // At this point we should prompt for new credentials for MyRealm.
2844 // Restart with username=foo3, password=foo4.
2845 MockWrite data_writes3[] = {
2846 MockWrite("GET /p/q/t HTTP/1.1\r\n"
2847 "Host: www.google.com\r\n"
2848 "Connection: keep-alive\r\n"
2849 "Authorization: Basic Zm9vMzpiYXIz\r\n\r\n"),
2850 };
2851
2852 // Sever accepts the authorization.
2853 MockRead data_reads3[] = {
2854 MockRead("HTTP/1.0 200 OK\r\n"),
2855 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422856 MockRead(false, OK),
[email protected]f9ee6b52008-11-08 06:46:232857 };
2858
[email protected]31a2bfe2010-02-09 08:03:392859 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2860 data_writes1, arraysize(data_writes1));
2861 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
2862 data_writes2, arraysize(data_writes2));
2863 StaticSocketDataProvider data3(data_reads3, arraysize(data_reads3),
2864 data_writes3, arraysize(data_writes3));
[email protected]5ecc992a42009-11-11 01:41:592865 session_deps.socket_factory.AddSocketDataProvider(&data1);
2866 session_deps.socket_factory.AddSocketDataProvider(&data2);
2867 session_deps.socket_factory.AddSocketDataProvider(&data3);
[email protected]f9ee6b52008-11-08 06:46:232868
2869 TestCompletionCallback callback1;
2870
[email protected]684970b2009-08-14 04:54:462871 int rv = trans->Start(&request, &callback1, NULL);
[email protected]1c773ea12009-04-28 19:58:422872 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:232873
2874 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422875 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:232876
[email protected]0757e7702009-03-27 04:00:222877 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
2878 TestCompletionCallback callback2;
2879 rv = trans->RestartWithAuth(std::wstring(), std::wstring(), &callback2);
[email protected]1c773ea12009-04-28 19:58:422880 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]0757e7702009-03-27 04:00:222881 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422882 EXPECT_EQ(OK, rv);
[email protected]0757e7702009-03-27 04:00:222883 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
2884
[email protected]1c773ea12009-04-28 19:58:422885 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]f9ee6b52008-11-08 06:46:232886 EXPECT_FALSE(response == NULL);
2887
2888 // The password prompt info should have been set in
2889 // response->auth_challenge.
2890 EXPECT_FALSE(response->auth_challenge.get() == NULL);
2891
[email protected]71e4573a2009-05-21 22:03:002892 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
[email protected]f9ee6b52008-11-08 06:46:232893 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
2894 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
2895
[email protected]0757e7702009-03-27 04:00:222896 TestCompletionCallback callback3;
[email protected]f9ee6b52008-11-08 06:46:232897
[email protected]0757e7702009-03-27 04:00:222898 rv = trans->RestartWithAuth(L"foo3", L"bar3", &callback3);
[email protected]1c773ea12009-04-28 19:58:422899 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:232900
[email protected]0757e7702009-03-27 04:00:222901 rv = callback3.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422902 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:232903
2904 response = trans->GetResponseInfo();
2905 EXPECT_FALSE(response == NULL);
2906 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2907 EXPECT_EQ(100, response->headers->GetContentLength());
2908 }
2909}
[email protected]89ceba9a2009-03-21 03:46:062910
2911// Test the ResetStateForRestart() private method.
2912TEST_F(HttpNetworkTransactionTest, ResetStateForRestart) {
2913 // Create a transaction (the dependencies aren't important).
[email protected]228ff742009-06-05 01:19:592914 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:402915 scoped_ptr<HttpNetworkTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:432916 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]89ceba9a2009-03-21 03:46:062917
2918 // Setup some state (which we expect ResetStateForRestart() will clear).
[email protected]89ceba9a2009-03-21 03:46:062919 trans->read_buf_ = new IOBuffer(15);
2920 trans->read_buf_len_ = 15;
[email protected]0877e3d2009-10-17 22:29:572921 trans->request_headers_ = "Authorization: NTLM";
[email protected]89ceba9a2009-03-21 03:46:062922
2923 // Setup state in response_
[email protected]a7e41312009-12-16 23:18:142924 HttpResponseInfo* response = &trans->response_;
[email protected]0877e3d2009-10-17 22:29:572925 response->auth_challenge = new AuthChallengeInfo();
2926 response->ssl_info.cert_status = -15;
2927 response->response_time = base::Time::Now();
2928 response->was_cached = true; // (Wouldn't ever actually be true...)
[email protected]89ceba9a2009-03-21 03:46:062929
2930 { // Setup state for response_.vary_data
2931 HttpRequestInfo request;
2932 std::string temp("HTTP/1.1 200 OK\nVary: foo, bar\n\n");
2933 std::replace(temp.begin(), temp.end(), '\n', '\0');
[email protected]0877e3d2009-10-17 22:29:572934 scoped_refptr<HttpResponseHeaders> headers = new HttpResponseHeaders(temp);
[email protected]8c76ae22010-04-20 22:15:432935 request.extra_headers.SetHeader("Foo", "1");
2936 request.extra_headers.SetHeader("bar", "23");
[email protected]0877e3d2009-10-17 22:29:572937 EXPECT_TRUE(response->vary_data.Init(request, *headers));
[email protected]89ceba9a2009-03-21 03:46:062938 }
2939
2940 // Cause the above state to be reset.
2941 trans->ResetStateForRestart();
2942
2943 // Verify that the state that needed to be reset, has been reset.
[email protected]9b6fee12009-09-29 18:13:072944 EXPECT_TRUE(trans->read_buf_.get() == NULL);
[email protected]89ceba9a2009-03-21 03:46:062945 EXPECT_EQ(0, trans->read_buf_len_);
[email protected]0877e3d2009-10-17 22:29:572946 EXPECT_EQ(0U, trans->request_headers_.size());
2947 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2948 EXPECT_TRUE(response->headers.get() == NULL);
2949 EXPECT_EQ(false, response->was_cached);
2950 EXPECT_EQ(0, response->ssl_info.cert_status);
2951 EXPECT_FALSE(response->vary_data.is_valid());
[email protected]89ceba9a2009-03-21 03:46:062952}
2953
[email protected]bacff652009-03-31 17:50:332954// Test HTTPS connections to a site with a bad certificate
2955TEST_F(HttpNetworkTransactionTest, HTTPSBadCertificate) {
[email protected]228ff742009-06-05 01:19:592956 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:402957 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:432958 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]bacff652009-03-31 17:50:332959
2960 HttpRequestInfo request;
2961 request.method = "GET";
2962 request.url = GURL("https://www.google.com/");
2963 request.load_flags = 0;
2964
2965 MockWrite data_writes[] = {
2966 MockWrite("GET / HTTP/1.1\r\n"
2967 "Host: www.google.com\r\n"
2968 "Connection: keep-alive\r\n\r\n"),
2969 };
2970
2971 MockRead data_reads[] = {
2972 MockRead("HTTP/1.0 200 OK\r\n"),
2973 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2974 MockRead("Content-Length: 100\r\n\r\n"),
2975 MockRead(false, OK),
2976 };
2977
[email protected]5ecc992a42009-11-11 01:41:592978 StaticSocketDataProvider ssl_bad_certificate;
[email protected]31a2bfe2010-02-09 08:03:392979 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
2980 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:592981 SSLSocketDataProvider ssl_bad(true, ERR_CERT_AUTHORITY_INVALID);
2982 SSLSocketDataProvider ssl(true, OK);
[email protected]bacff652009-03-31 17:50:332983
[email protected]5ecc992a42009-11-11 01:41:592984 session_deps.socket_factory.AddSocketDataProvider(&ssl_bad_certificate);
2985 session_deps.socket_factory.AddSocketDataProvider(&data);
2986 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl_bad);
2987 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
[email protected]bacff652009-03-31 17:50:332988
2989 TestCompletionCallback callback;
2990
[email protected]684970b2009-08-14 04:54:462991 int rv = trans->Start(&request, &callback, NULL);
[email protected]bacff652009-03-31 17:50:332992 EXPECT_EQ(ERR_IO_PENDING, rv);
2993
2994 rv = callback.WaitForResult();
2995 EXPECT_EQ(ERR_CERT_AUTHORITY_INVALID, rv);
2996
2997 rv = trans->RestartIgnoringLastError(&callback);
2998 EXPECT_EQ(ERR_IO_PENDING, rv);
2999
3000 rv = callback.WaitForResult();
3001 EXPECT_EQ(OK, rv);
3002
3003 const HttpResponseInfo* response = trans->GetResponseInfo();
3004
3005 EXPECT_FALSE(response == NULL);
3006 EXPECT_EQ(100, response->headers->GetContentLength());
3007}
3008
3009// Test HTTPS connections to a site with a bad certificate, going through a
3010// proxy
3011TEST_F(HttpNetworkTransactionTest, HTTPSBadCertificateViaProxy) {
[email protected]228ff742009-06-05 01:19:593012 SessionDependencies session_deps(CreateFixedProxyService("myproxy:70"));
[email protected]bacff652009-03-31 17:50:333013
3014 HttpRequestInfo request;
3015 request.method = "GET";
3016 request.url = GURL("https://www.google.com/");
3017 request.load_flags = 0;
3018
3019 MockWrite proxy_writes[] = {
3020 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
[email protected]e44de5d2009-06-05 20:12:453021 "Host: www.google.com\r\n"
3022 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]bacff652009-03-31 17:50:333023 };
3024
3025 MockRead proxy_reads[] = {
3026 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:423027 MockRead(false, OK)
[email protected]bacff652009-03-31 17:50:333028 };
3029
3030 MockWrite data_writes[] = {
3031 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
[email protected]e44de5d2009-06-05 20:12:453032 "Host: www.google.com\r\n"
3033 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]bacff652009-03-31 17:50:333034 MockWrite("GET / HTTP/1.1\r\n"
3035 "Host: www.google.com\r\n"
3036 "Connection: keep-alive\r\n\r\n"),
3037 };
3038
3039 MockRead data_reads[] = {
3040 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
3041 MockRead("HTTP/1.0 200 OK\r\n"),
3042 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3043 MockRead("Content-Length: 100\r\n\r\n"),
3044 MockRead(false, OK),
3045 };
3046
[email protected]31a2bfe2010-02-09 08:03:393047 StaticSocketDataProvider ssl_bad_certificate(
3048 proxy_reads, arraysize(proxy_reads),
3049 proxy_writes, arraysize(proxy_writes));
3050 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
3051 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:593052 SSLSocketDataProvider ssl_bad(true, ERR_CERT_AUTHORITY_INVALID);
3053 SSLSocketDataProvider ssl(true, OK);
[email protected]bacff652009-03-31 17:50:333054
[email protected]5ecc992a42009-11-11 01:41:593055 session_deps.socket_factory.AddSocketDataProvider(&ssl_bad_certificate);
3056 session_deps.socket_factory.AddSocketDataProvider(&data);
3057 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl_bad);
3058 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
[email protected]bacff652009-03-31 17:50:333059
3060 TestCompletionCallback callback;
3061
3062 for (int i = 0; i < 2; i++) {
[email protected]228ff742009-06-05 01:19:593063 session_deps.socket_factory.ResetNextMockIndexes();
[email protected]bacff652009-03-31 17:50:333064
[email protected]d207a5f2009-06-04 05:28:403065 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:433066 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]bacff652009-03-31 17:50:333067
[email protected]684970b2009-08-14 04:54:463068 int rv = trans->Start(&request, &callback, NULL);
[email protected]bacff652009-03-31 17:50:333069 EXPECT_EQ(ERR_IO_PENDING, rv);
3070
3071 rv = callback.WaitForResult();
3072 EXPECT_EQ(ERR_CERT_AUTHORITY_INVALID, rv);
3073
3074 rv = trans->RestartIgnoringLastError(&callback);
3075 EXPECT_EQ(ERR_IO_PENDING, rv);
3076
3077 rv = callback.WaitForResult();
3078 EXPECT_EQ(OK, rv);
3079
3080 const HttpResponseInfo* response = trans->GetResponseInfo();
3081
3082 EXPECT_FALSE(response == NULL);
3083 EXPECT_EQ(100, response->headers->GetContentLength());
3084 }
3085}
3086
[email protected]1c773ea12009-04-28 19:58:423087TEST_F(HttpNetworkTransactionTest, BuildRequest_UserAgent) {
[email protected]228ff742009-06-05 01:19:593088 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:403089 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:433090 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]1c773ea12009-04-28 19:58:423091
3092 HttpRequestInfo request;
3093 request.method = "GET";
3094 request.url = GURL("http://www.google.com/");
[email protected]8c76ae22010-04-20 22:15:433095 request.extra_headers.SetHeader(HttpRequestHeaders::kUserAgent,
3096 "Chromium Ultra Awesome X Edition");
[email protected]1c773ea12009-04-28 19:58:423097
3098 MockWrite data_writes[] = {
3099 MockWrite("GET / HTTP/1.1\r\n"
3100 "Host: www.google.com\r\n"
3101 "Connection: keep-alive\r\n"
3102 "User-Agent: Chromium Ultra Awesome X Edition\r\n\r\n"),
3103 };
3104
3105 // Lastly, the server responds with the actual content.
3106 MockRead data_reads[] = {
3107 MockRead("HTTP/1.0 200 OK\r\n"),
3108 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3109 MockRead("Content-Length: 100\r\n\r\n"),
3110 MockRead(false, OK),
3111 };
3112
[email protected]31a2bfe2010-02-09 08:03:393113 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
3114 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:593115 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:423116
3117 TestCompletionCallback callback;
3118
[email protected]684970b2009-08-14 04:54:463119 int rv = trans->Start(&request, &callback, NULL);
[email protected]1c773ea12009-04-28 19:58:423120 EXPECT_EQ(ERR_IO_PENDING, rv);
3121
3122 rv = callback.WaitForResult();
3123 EXPECT_EQ(OK, rv);
3124}
3125
3126TEST_F(HttpNetworkTransactionTest, BuildRequest_Referer) {
[email protected]228ff742009-06-05 01:19:593127 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:403128 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:433129 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]1c773ea12009-04-28 19:58:423130
3131 HttpRequestInfo request;
3132 request.method = "GET";
3133 request.url = GURL("http://www.google.com/");
3134 request.load_flags = 0;
3135 request.referrer = GURL("http://the.previous.site.com/");
3136
3137 MockWrite data_writes[] = {
3138 MockWrite("GET / HTTP/1.1\r\n"
3139 "Host: www.google.com\r\n"
3140 "Connection: keep-alive\r\n"
3141 "Referer: http://the.previous.site.com/\r\n\r\n"),
3142 };
3143
3144 // Lastly, the server responds with the actual content.
3145 MockRead data_reads[] = {
3146 MockRead("HTTP/1.0 200 OK\r\n"),
3147 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3148 MockRead("Content-Length: 100\r\n\r\n"),
3149 MockRead(false, OK),
3150 };
3151
[email protected]31a2bfe2010-02-09 08:03:393152 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
3153 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:593154 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:423155
3156 TestCompletionCallback callback;
3157
[email protected]684970b2009-08-14 04:54:463158 int rv = trans->Start(&request, &callback, NULL);
[email protected]1c773ea12009-04-28 19:58:423159 EXPECT_EQ(ERR_IO_PENDING, rv);
3160
3161 rv = callback.WaitForResult();
3162 EXPECT_EQ(OK, rv);
3163}
3164
3165TEST_F(HttpNetworkTransactionTest, BuildRequest_PostContentLengthZero) {
[email protected]228ff742009-06-05 01:19:593166 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:403167 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:433168 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]1c773ea12009-04-28 19:58:423169
3170 HttpRequestInfo request;
3171 request.method = "POST";
3172 request.url = GURL("http://www.google.com/");
3173
3174 MockWrite data_writes[] = {
3175 MockWrite("POST / HTTP/1.1\r\n"
3176 "Host: www.google.com\r\n"
3177 "Connection: keep-alive\r\n"
3178 "Content-Length: 0\r\n\r\n"),
3179 };
3180
3181 // Lastly, the server responds with the actual content.
3182 MockRead data_reads[] = {
3183 MockRead("HTTP/1.0 200 OK\r\n"),
3184 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3185 MockRead("Content-Length: 100\r\n\r\n"),
3186 MockRead(false, OK),
3187 };
3188
[email protected]31a2bfe2010-02-09 08:03:393189 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
3190 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:593191 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:423192
3193 TestCompletionCallback callback;
3194
[email protected]684970b2009-08-14 04:54:463195 int rv = trans->Start(&request, &callback, NULL);
[email protected]1c773ea12009-04-28 19:58:423196 EXPECT_EQ(ERR_IO_PENDING, rv);
3197
3198 rv = callback.WaitForResult();
3199 EXPECT_EQ(OK, rv);
3200}
3201
3202TEST_F(HttpNetworkTransactionTest, BuildRequest_PutContentLengthZero) {
[email protected]228ff742009-06-05 01:19:593203 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:403204 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:433205 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]1c773ea12009-04-28 19:58:423206
3207 HttpRequestInfo request;
3208 request.method = "PUT";
3209 request.url = GURL("http://www.google.com/");
3210
3211 MockWrite data_writes[] = {
3212 MockWrite("PUT / HTTP/1.1\r\n"
3213 "Host: www.google.com\r\n"
3214 "Connection: keep-alive\r\n"
3215 "Content-Length: 0\r\n\r\n"),
3216 };
3217
3218 // Lastly, the server responds with the actual content.
3219 MockRead data_reads[] = {
3220 MockRead("HTTP/1.0 200 OK\r\n"),
3221 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3222 MockRead("Content-Length: 100\r\n\r\n"),
3223 MockRead(false, OK),
3224 };
3225
[email protected]31a2bfe2010-02-09 08:03:393226 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
3227 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:593228 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:423229
3230 TestCompletionCallback callback;
3231
[email protected]684970b2009-08-14 04:54:463232 int rv = trans->Start(&request, &callback, NULL);
[email protected]1c773ea12009-04-28 19:58:423233 EXPECT_EQ(ERR_IO_PENDING, rv);
3234
3235 rv = callback.WaitForResult();
3236 EXPECT_EQ(OK, rv);
3237}
3238
3239TEST_F(HttpNetworkTransactionTest, BuildRequest_HeadContentLengthZero) {
[email protected]228ff742009-06-05 01:19:593240 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:403241 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:433242 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]1c773ea12009-04-28 19:58:423243
3244 HttpRequestInfo request;
3245 request.method = "HEAD";
3246 request.url = GURL("http://www.google.com/");
3247
3248 MockWrite data_writes[] = {
3249 MockWrite("HEAD / HTTP/1.1\r\n"
3250 "Host: www.google.com\r\n"
3251 "Connection: keep-alive\r\n"
3252 "Content-Length: 0\r\n\r\n"),
3253 };
3254
3255 // Lastly, the server responds with the actual content.
3256 MockRead data_reads[] = {
3257 MockRead("HTTP/1.0 200 OK\r\n"),
3258 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3259 MockRead("Content-Length: 100\r\n\r\n"),
3260 MockRead(false, OK),
3261 };
3262
[email protected]31a2bfe2010-02-09 08:03:393263 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
3264 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:593265 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:423266
3267 TestCompletionCallback callback;
3268
[email protected]684970b2009-08-14 04:54:463269 int rv = trans->Start(&request, &callback, NULL);
[email protected]1c773ea12009-04-28 19:58:423270 EXPECT_EQ(ERR_IO_PENDING, rv);
3271
3272 rv = callback.WaitForResult();
3273 EXPECT_EQ(OK, rv);
3274}
3275
3276TEST_F(HttpNetworkTransactionTest, BuildRequest_CacheControlNoCache) {
[email protected]228ff742009-06-05 01:19:593277 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:403278 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:433279 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]1c773ea12009-04-28 19:58:423280
3281 HttpRequestInfo request;
3282 request.method = "GET";
3283 request.url = GURL("http://www.google.com/");
3284 request.load_flags = LOAD_BYPASS_CACHE;
3285
3286 MockWrite data_writes[] = {
3287 MockWrite("GET / HTTP/1.1\r\n"
3288 "Host: www.google.com\r\n"
3289 "Connection: keep-alive\r\n"
3290 "Pragma: no-cache\r\n"
3291 "Cache-Control: no-cache\r\n\r\n"),
3292 };
3293
3294 // Lastly, the server responds with the actual content.
3295 MockRead data_reads[] = {
3296 MockRead("HTTP/1.0 200 OK\r\n"),
3297 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3298 MockRead("Content-Length: 100\r\n\r\n"),
3299 MockRead(false, OK),
3300 };
3301
[email protected]31a2bfe2010-02-09 08:03:393302 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
3303 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:593304 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:423305
3306 TestCompletionCallback callback;
3307
[email protected]684970b2009-08-14 04:54:463308 int rv = trans->Start(&request, &callback, NULL);
[email protected]1c773ea12009-04-28 19:58:423309 EXPECT_EQ(ERR_IO_PENDING, rv);
3310
3311 rv = callback.WaitForResult();
3312 EXPECT_EQ(OK, rv);
3313}
3314
3315TEST_F(HttpNetworkTransactionTest,
3316 BuildRequest_CacheControlValidateCache) {
[email protected]228ff742009-06-05 01:19:593317 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:403318 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:433319 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]1c773ea12009-04-28 19:58:423320
3321 HttpRequestInfo request;
3322 request.method = "GET";
3323 request.url = GURL("http://www.google.com/");
3324 request.load_flags = LOAD_VALIDATE_CACHE;
3325
3326 MockWrite data_writes[] = {
3327 MockWrite("GET / HTTP/1.1\r\n"
3328 "Host: www.google.com\r\n"
3329 "Connection: keep-alive\r\n"
3330 "Cache-Control: max-age=0\r\n\r\n"),
3331 };
3332
3333 // Lastly, the server responds with the actual content.
3334 MockRead data_reads[] = {
3335 MockRead("HTTP/1.0 200 OK\r\n"),
3336 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3337 MockRead("Content-Length: 100\r\n\r\n"),
3338 MockRead(false, OK),
3339 };
3340
[email protected]31a2bfe2010-02-09 08:03:393341 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
3342 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:593343 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:423344
3345 TestCompletionCallback callback;
3346
[email protected]684970b2009-08-14 04:54:463347 int rv = trans->Start(&request, &callback, NULL);
[email protected]1c773ea12009-04-28 19:58:423348 EXPECT_EQ(ERR_IO_PENDING, rv);
3349
3350 rv = callback.WaitForResult();
3351 EXPECT_EQ(OK, rv);
3352}
3353
3354TEST_F(HttpNetworkTransactionTest, BuildRequest_ExtraHeaders) {
[email protected]228ff742009-06-05 01:19:593355 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:403356 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:433357 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]1c773ea12009-04-28 19:58:423358
3359 HttpRequestInfo request;
3360 request.method = "GET";
3361 request.url = GURL("http://www.google.com/");
[email protected]8c76ae22010-04-20 22:15:433362 request.extra_headers.SetHeader("FooHeader", "Bar");
[email protected]1c773ea12009-04-28 19:58:423363
3364 MockWrite data_writes[] = {
3365 MockWrite("GET / HTTP/1.1\r\n"
3366 "Host: www.google.com\r\n"
3367 "Connection: keep-alive\r\n"
3368 "FooHeader: Bar\r\n\r\n"),
3369 };
3370
3371 // Lastly, the server responds with the actual content.
3372 MockRead data_reads[] = {
3373 MockRead("HTTP/1.0 200 OK\r\n"),
3374 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3375 MockRead("Content-Length: 100\r\n\r\n"),
3376 MockRead(false, OK),
3377 };
3378
[email protected]31a2bfe2010-02-09 08:03:393379 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
3380 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:593381 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:423382
3383 TestCompletionCallback callback;
3384
[email protected]684970b2009-08-14 04:54:463385 int rv = trans->Start(&request, &callback, NULL);
[email protected]1c773ea12009-04-28 19:58:423386 EXPECT_EQ(ERR_IO_PENDING, rv);
3387
3388 rv = callback.WaitForResult();
3389 EXPECT_EQ(OK, rv);
3390}
3391
[email protected]270c6412010-03-29 22:02:473392TEST_F(HttpNetworkTransactionTest, BuildRequest_ExtraHeadersStripped) {
3393 SessionDependencies session_deps;
3394 scoped_ptr<HttpTransaction> trans(
3395 new HttpNetworkTransaction(CreateSession(&session_deps)));
3396
3397 HttpRequestInfo request;
3398 request.method = "GET";
3399 request.url = GURL("http://www.google.com/");
[email protected]8c76ae22010-04-20 22:15:433400 request.extra_headers.SetHeader("referer", "www.foo.com");
3401 request.extra_headers.SetHeader("hEllo", "Kitty");
3402 request.extra_headers.SetHeader("FoO", "bar");
[email protected]270c6412010-03-29 22:02:473403
3404 MockWrite data_writes[] = {
3405 MockWrite("GET / HTTP/1.1\r\n"
3406 "Host: www.google.com\r\n"
3407 "Connection: keep-alive\r\n"
3408 "hEllo: Kitty\r\n"
3409 "FoO: bar\r\n\r\n"),
3410 };
3411
3412 // Lastly, the server responds with the actual content.
3413 MockRead data_reads[] = {
3414 MockRead("HTTP/1.0 200 OK\r\n"),
3415 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3416 MockRead("Content-Length: 100\r\n\r\n"),
3417 MockRead(false, OK),
3418 };
3419
3420 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
3421 data_writes, arraysize(data_writes));
3422 session_deps.socket_factory.AddSocketDataProvider(&data);
3423
3424 TestCompletionCallback callback;
3425
3426 int rv = trans->Start(&request, &callback, NULL);
3427 EXPECT_EQ(ERR_IO_PENDING, rv);
3428
3429 rv = callback.WaitForResult();
3430 EXPECT_EQ(OK, rv);
3431}
3432
[email protected]3cd17242009-06-23 02:59:023433TEST_F(HttpNetworkTransactionTest, SOCKS4_HTTP_GET) {
[email protected]80d6524d2009-08-18 03:58:093434 SessionDependencies session_deps(
3435 CreateFixedProxyService("socks4://myproxy:1080"));
[email protected]3cd17242009-06-23 02:59:023436
3437 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:433438 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]3cd17242009-06-23 02:59:023439
3440 HttpRequestInfo request;
3441 request.method = "GET";
3442 request.url = GURL("http://www.google.com/");
3443 request.load_flags = 0;
3444
3445 char write_buffer[] = { 0x04, 0x01, 0x00, 0x50, 127, 0, 0, 1, 0 };
3446 char read_buffer[] = { 0x00, 0x5A, 0x00, 0x00, 0, 0, 0, 0 };
3447
3448 MockWrite data_writes[] = {
[email protected]e0c27be2009-07-15 13:09:353449 MockWrite(true, write_buffer, arraysize(write_buffer)),
[email protected]3cd17242009-06-23 02:59:023450 MockWrite("GET / HTTP/1.1\r\n"
3451 "Host: www.google.com\r\n"
3452 "Connection: keep-alive\r\n\r\n")
3453 };
3454
3455 MockRead data_reads[] = {
[email protected]5ecc992a42009-11-11 01:41:593456 MockRead(true, read_buffer, arraysize(read_buffer)),
[email protected]3cd17242009-06-23 02:59:023457 MockRead("HTTP/1.0 200 OK\r\n"),
3458 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
3459 MockRead("Payload"),
3460 MockRead(false, OK)
3461 };
3462
[email protected]31a2bfe2010-02-09 08:03:393463 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
3464 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:593465 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]3cd17242009-06-23 02:59:023466
3467 TestCompletionCallback callback;
3468
[email protected]684970b2009-08-14 04:54:463469 int rv = trans->Start(&request, &callback, NULL);
[email protected]3cd17242009-06-23 02:59:023470 EXPECT_EQ(ERR_IO_PENDING, rv);
3471
3472 rv = callback.WaitForResult();
3473 EXPECT_EQ(OK, rv);
3474
3475 const HttpResponseInfo* response = trans->GetResponseInfo();
3476 EXPECT_FALSE(response == NULL);
3477
3478 std::string response_text;
3479 rv = ReadTransaction(trans.get(), &response_text);
3480 EXPECT_EQ(OK, rv);
3481 EXPECT_EQ("Payload", response_text);
3482}
3483
3484TEST_F(HttpNetworkTransactionTest, SOCKS4_SSL_GET) {
[email protected]80d6524d2009-08-18 03:58:093485 SessionDependencies session_deps(
3486 CreateFixedProxyService("socks4://myproxy:1080"));
[email protected]3cd17242009-06-23 02:59:023487
3488 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:433489 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]3cd17242009-06-23 02:59:023490
3491 HttpRequestInfo request;
3492 request.method = "GET";
3493 request.url = GURL("https://www.google.com/");
3494 request.load_flags = 0;
3495
3496 unsigned char write_buffer[] = { 0x04, 0x01, 0x01, 0xBB, 127, 0, 0, 1, 0 };
3497 unsigned char read_buffer[] = { 0x00, 0x5A, 0x00, 0x00, 0, 0, 0, 0 };
3498
3499 MockWrite data_writes[] = {
[email protected]e0c27be2009-07-15 13:09:353500 MockWrite(true, reinterpret_cast<char*>(write_buffer),
3501 arraysize(write_buffer)),
[email protected]3cd17242009-06-23 02:59:023502 MockWrite("GET / HTTP/1.1\r\n"
3503 "Host: www.google.com\r\n"
3504 "Connection: keep-alive\r\n\r\n")
3505 };
3506
3507 MockRead data_reads[] = {
[email protected]e0c27be2009-07-15 13:09:353508 MockWrite(true, reinterpret_cast<char*>(read_buffer),
3509 arraysize(read_buffer)),
3510 MockRead("HTTP/1.0 200 OK\r\n"),
3511 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
3512 MockRead("Payload"),
3513 MockRead(false, OK)
3514 };
3515
[email protected]31a2bfe2010-02-09 08:03:393516 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
3517 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:593518 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]e0c27be2009-07-15 13:09:353519
[email protected]5ecc992a42009-11-11 01:41:593520 SSLSocketDataProvider ssl(true, OK);
3521 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
[email protected]e0c27be2009-07-15 13:09:353522
3523 TestCompletionCallback callback;
3524
[email protected]684970b2009-08-14 04:54:463525 int rv = trans->Start(&request, &callback, NULL);
[email protected]e0c27be2009-07-15 13:09:353526 EXPECT_EQ(ERR_IO_PENDING, rv);
3527
3528 rv = callback.WaitForResult();
3529 EXPECT_EQ(OK, rv);
3530
3531 const HttpResponseInfo* response = trans->GetResponseInfo();
3532 EXPECT_FALSE(response == NULL);
3533
3534 std::string response_text;
3535 rv = ReadTransaction(trans.get(), &response_text);
3536 EXPECT_EQ(OK, rv);
3537 EXPECT_EQ("Payload", response_text);
3538}
3539
3540TEST_F(HttpNetworkTransactionTest, SOCKS5_HTTP_GET) {
[email protected]80d6524d2009-08-18 03:58:093541 SessionDependencies session_deps(
3542 CreateFixedProxyService("socks5://myproxy:1080"));
[email protected]e0c27be2009-07-15 13:09:353543
3544 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:433545 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]e0c27be2009-07-15 13:09:353546
3547 HttpRequestInfo request;
3548 request.method = "GET";
3549 request.url = GURL("http://www.google.com/");
3550 request.load_flags = 0;
3551
3552 const char kSOCKS5GreetRequest[] = { 0x05, 0x01, 0x00 };
3553 const char kSOCKS5GreetResponse[] = { 0x05, 0x00 };
[email protected]f209dba2009-12-18 00:24:373554 const char kSOCKS5OkRequest[] = {
3555 0x05, // Version
3556 0x01, // Command (CONNECT)
3557 0x00, // Reserved.
3558 0x03, // Address type (DOMAINNAME).
3559 0x0E, // Length of domain (14)
3560 // Domain string:
3561 'w', 'w', 'w', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'c', 'o', 'm',
3562 0x00, 0x50, // 16-bit port (80)
3563 };
[email protected]e0c27be2009-07-15 13:09:353564 const char kSOCKS5OkResponse[] =
3565 { 0x05, 0x00, 0x00, 0x01, 127, 0, 0, 1, 0x00, 0x50 };
3566
3567 MockWrite data_writes[] = {
3568 MockWrite(true, kSOCKS5GreetRequest, arraysize(kSOCKS5GreetRequest)),
3569 MockWrite(true, kSOCKS5OkRequest, arraysize(kSOCKS5OkRequest)),
3570 MockWrite("GET / HTTP/1.1\r\n"
3571 "Host: www.google.com\r\n"
3572 "Connection: keep-alive\r\n\r\n")
3573 };
3574
3575 MockRead data_reads[] = {
3576 MockWrite(true, kSOCKS5GreetResponse, arraysize(kSOCKS5GreetResponse)),
3577 MockWrite(true, kSOCKS5OkResponse, arraysize(kSOCKS5OkResponse)),
3578 MockRead("HTTP/1.0 200 OK\r\n"),
3579 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
3580 MockRead("Payload"),
3581 MockRead(false, OK)
3582 };
3583
[email protected]31a2bfe2010-02-09 08:03:393584 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
3585 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:593586 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]e0c27be2009-07-15 13:09:353587
3588 TestCompletionCallback callback;
3589
[email protected]684970b2009-08-14 04:54:463590 int rv = trans->Start(&request, &callback, NULL);
[email protected]e0c27be2009-07-15 13:09:353591 EXPECT_EQ(ERR_IO_PENDING, rv);
3592
3593 rv = callback.WaitForResult();
3594 EXPECT_EQ(OK, rv);
3595
3596 const HttpResponseInfo* response = trans->GetResponseInfo();
3597 EXPECT_FALSE(response == NULL);
3598
3599 std::string response_text;
3600 rv = ReadTransaction(trans.get(), &response_text);
3601 EXPECT_EQ(OK, rv);
3602 EXPECT_EQ("Payload", response_text);
3603}
3604
3605TEST_F(HttpNetworkTransactionTest, SOCKS5_SSL_GET) {
[email protected]80d6524d2009-08-18 03:58:093606 SessionDependencies session_deps(
3607 CreateFixedProxyService("socks5://myproxy:1080"));
[email protected]e0c27be2009-07-15 13:09:353608
3609 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:433610 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]e0c27be2009-07-15 13:09:353611
3612 HttpRequestInfo request;
3613 request.method = "GET";
3614 request.url = GURL("https://www.google.com/");
3615 request.load_flags = 0;
3616
3617 const char kSOCKS5GreetRequest[] = { 0x05, 0x01, 0x00 };
3618 const char kSOCKS5GreetResponse[] = { 0x05, 0x00 };
[email protected]f209dba2009-12-18 00:24:373619 const unsigned char kSOCKS5OkRequest[] = {
3620 0x05, // Version
3621 0x01, // Command (CONNECT)
3622 0x00, // Reserved.
3623 0x03, // Address type (DOMAINNAME).
3624 0x0E, // Length of domain (14)
3625 // Domain string:
3626 'w', 'w', 'w', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'c', 'o', 'm',
3627 0x01, 0xBB, // 16-bit port (443)
3628 };
3629
[email protected]e0c27be2009-07-15 13:09:353630 const char kSOCKS5OkResponse[] =
3631 { 0x05, 0x00, 0x00, 0x01, 0, 0, 0, 0, 0x00, 0x00 };
3632
3633 MockWrite data_writes[] = {
3634 MockWrite(true, kSOCKS5GreetRequest, arraysize(kSOCKS5GreetRequest)),
3635 MockWrite(true, reinterpret_cast<const char*>(kSOCKS5OkRequest),
3636 arraysize(kSOCKS5OkRequest)),
3637 MockWrite("GET / HTTP/1.1\r\n"
3638 "Host: www.google.com\r\n"
3639 "Connection: keep-alive\r\n\r\n")
3640 };
3641
3642 MockRead data_reads[] = {
3643 MockWrite(true, kSOCKS5GreetResponse, arraysize(kSOCKS5GreetResponse)),
3644 MockWrite(true, kSOCKS5OkResponse, arraysize(kSOCKS5OkResponse)),
[email protected]3cd17242009-06-23 02:59:023645 MockRead("HTTP/1.0 200 OK\r\n"),
3646 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
3647 MockRead("Payload"),
3648 MockRead(false, OK)
3649 };
3650
[email protected]31a2bfe2010-02-09 08:03:393651 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
3652 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:593653 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]3cd17242009-06-23 02:59:023654
[email protected]5ecc992a42009-11-11 01:41:593655 SSLSocketDataProvider ssl(true, OK);
3656 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
[email protected]3cd17242009-06-23 02:59:023657
3658 TestCompletionCallback callback;
3659
[email protected]684970b2009-08-14 04:54:463660 int rv = trans->Start(&request, &callback, NULL);
[email protected]3cd17242009-06-23 02:59:023661 EXPECT_EQ(ERR_IO_PENDING, rv);
3662
3663 rv = callback.WaitForResult();
3664 EXPECT_EQ(OK, rv);
3665
3666 const HttpResponseInfo* response = trans->GetResponseInfo();
3667 EXPECT_FALSE(response == NULL);
3668
3669 std::string response_text;
3670 rv = ReadTransaction(trans.get(), &response_text);
3671 EXPECT_EQ(OK, rv);
3672 EXPECT_EQ("Payload", response_text);
3673}
3674
[email protected]04e5be32009-06-26 20:00:313675// Tests that for connection endpoints the group names are correctly set.
3676TEST_F(HttpNetworkTransactionTest, GroupNameForProxyConnections) {
3677 const struct {
3678 const std::string proxy_server;
3679 const std::string url;
3680 const std::string expected_group_name;
3681 } tests[] = {
3682 {
3683 "", // no proxy (direct)
3684 "http://www.google.com/direct",
[email protected]2ff8b312010-04-26 22:20:543685 "www.google.com:80",
3686 },
3687 {
3688 "", // no proxy (direct)
3689 "http://[2001:1418:13:1::25]/direct",
3690 "[2001:1418:13:1::25]:80",
[email protected]04e5be32009-06-26 20:00:313691 },
3692 {
3693 "http_proxy",
3694 "http://www.google.com/http_proxy_normal",
3695 "proxy/http_proxy:80/",
3696 },
3697 {
3698 "socks4://socks_proxy:1080",
3699 "http://www.google.com/socks4_direct",
[email protected]2ff8b312010-04-26 22:20:543700 "proxy/socks4://socks_proxy:1080/www.google.com:80",
[email protected]04e5be32009-06-26 20:00:313701 },
3702
3703 // SSL Tests
3704 {
3705 "",
3706 "https://www.google.com/direct_ssl",
[email protected]2ff8b312010-04-26 22:20:543707 "www.google.com:443",
[email protected]04e5be32009-06-26 20:00:313708 },
3709 {
3710 "http_proxy",
3711 "https://www.google.com/http_connect_ssl",
[email protected]2ff8b312010-04-26 22:20:543712 "proxy/http_proxy:80/www.google.com:443",
[email protected]04e5be32009-06-26 20:00:313713 },
3714 {
3715 "socks4://socks_proxy:1080",
3716 "https://www.google.com/socks4_ssl",
[email protected]2ff8b312010-04-26 22:20:543717 "proxy/socks4://socks_proxy:1080/www.google.com:443",
[email protected]04e5be32009-06-26 20:00:313718 },
[email protected]2ff8b312010-04-26 22:20:543719 {
3720 "", // no proxy (direct)
3721 "http://host.with.alternate/direct",
3722 "host.with.alternate:443",
3723 },
3724
3725 // TODO(willchan): Uncomment these tests when they work.
3726// {
3727// "http_proxy",
3728// "http://host.with.alternate/direct",
3729// "proxy/http_proxy:80/host.with.alternate:443",
3730// },
3731// {
3732// "socks4://socks_proxy:1080",
3733// "http://host.with.alternate/direct",
3734// "proxy/socks4://socks_proxy:1080/host.with.alternate:443",
3735// },
[email protected]04e5be32009-06-26 20:00:313736 };
3737
[email protected]2ff8b312010-04-26 22:20:543738 HttpNetworkTransaction::SetUseAlternateProtocols(true);
3739
[email protected]04e5be32009-06-26 20:00:313740 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) {
[email protected]80d6524d2009-08-18 03:58:093741 SessionDependencies session_deps(
3742 CreateFixedProxyService(tests[i].proxy_server));
[email protected]04e5be32009-06-26 20:00:313743
[email protected]04e5be32009-06-26 20:00:313744 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]a796bcec2010-03-22 17:17:263745
[email protected]2ff8b312010-04-26 22:20:543746 HttpAlternateProtocols* alternate_protocols =
3747 session->mutable_alternate_protocols();
3748 alternate_protocols->SetAlternateProtocolFor(
3749 HostPortPair("host.with.alternate", 80), 443,
3750 HttpAlternateProtocols::NPN_SPDY_1);
3751
[email protected]a796bcec2010-03-22 17:17:263752 scoped_refptr<CaptureGroupNameTCPSocketPool> tcp_conn_pool(
3753 new CaptureGroupNameTCPSocketPool(session.get(),
3754 session->socket_factory()));
3755 session->tcp_socket_pool_ = tcp_conn_pool.get();
3756 scoped_refptr<CaptureGroupNameSOCKSSocketPool> socks_conn_pool(
3757 new CaptureGroupNameSOCKSSocketPool(session.get(),
3758 tcp_conn_pool.get()));
3759 session->socks_socket_pool_ = socks_conn_pool.get();
[email protected]04e5be32009-06-26 20:00:313760
[email protected]5695b8c2009-09-30 21:36:433761 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]04e5be32009-06-26 20:00:313762
3763 HttpRequestInfo request;
3764 request.method = "GET";
3765 request.url = GURL(tests[i].url);
3766 request.load_flags = 0;
3767
3768 TestCompletionCallback callback;
3769
3770 // We do not complete this request, the dtor will clean the transaction up.
[email protected]684970b2009-08-14 04:54:463771 EXPECT_EQ(ERR_IO_PENDING, trans->Start(&request, &callback, NULL));
[email protected]a796bcec2010-03-22 17:17:263772 std::string allgroups = tcp_conn_pool->last_group_name_received() +
3773 socks_conn_pool->last_group_name_received();
3774 EXPECT_EQ(tests[i].expected_group_name, allgroups);
[email protected]04e5be32009-06-26 20:00:313775 }
[email protected]2ff8b312010-04-26 22:20:543776
3777 HttpNetworkTransaction::SetUseAlternateProtocols(false);
[email protected]04e5be32009-06-26 20:00:313778}
3779
[email protected]9172a982009-06-06 00:30:253780TEST_F(HttpNetworkTransactionTest, ReconsiderProxyAfterFailedConnection) {
[email protected]5c6a17e2009-06-10 00:54:543781 SessionDependencies session_deps(
3782 CreateFixedProxyService("myproxy:70;foobar:80"));
[email protected]b59ff372009-07-15 22:04:323783
[email protected]69719062010-01-05 20:09:213784 // This simulates failure resolving all hostnames; that means we will fail
3785 // connecting to both proxies (myproxy:70 and foobar:80).
[email protected]b59ff372009-07-15 22:04:323786 session_deps.host_resolver->rules()->AddSimulatedFailure("*");
3787
[email protected]9172a982009-06-06 00:30:253788 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:433789 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]9172a982009-06-06 00:30:253790
3791 HttpRequestInfo request;
3792 request.method = "GET";
3793 request.url = GURL("http://www.google.com/");
3794
3795 TestCompletionCallback callback;
3796
[email protected]684970b2009-08-14 04:54:463797 int rv = trans->Start(&request, &callback, NULL);
[email protected]9172a982009-06-06 00:30:253798 EXPECT_EQ(ERR_IO_PENDING, rv);
3799
[email protected]9172a982009-06-06 00:30:253800 rv = callback.WaitForResult();
3801 EXPECT_EQ(ERR_NAME_NOT_RESOLVED, rv);
3802}
3803
[email protected]f3e6c1e2009-06-15 20:52:123804// Host resolution observer used by
3805// HttpNetworkTransactionTest.ResolveMadeWithReferrer to check that host
3806// resovle requests are issued with a referrer of |expected_referrer|.
3807class ResolutionReferrerObserver : public HostResolver::Observer {
3808 public:
3809 explicit ResolutionReferrerObserver(const GURL& expected_referrer)
3810 : expected_referrer_(expected_referrer),
3811 called_start_with_referrer_(false),
3812 called_finish_with_referrer_(false) {
3813 }
3814
3815 virtual void OnStartResolution(int id,
3816 const HostResolver::RequestInfo& info) {
3817 if (info.referrer() == expected_referrer_)
3818 called_start_with_referrer_ = true;
3819 }
3820
3821 virtual void OnFinishResolutionWithStatus(
3822 int id, bool was_resolved, const HostResolver::RequestInfo& info ) {
3823 if (info.referrer() == expected_referrer_)
3824 called_finish_with_referrer_ = true;
3825 }
3826
[email protected]eb255d32009-06-17 02:11:033827 virtual void OnCancelResolution(int id,
3828 const HostResolver::RequestInfo& info ) {
3829 FAIL() << "Should not be cancelling any requests!";
3830 }
3831
[email protected]f3e6c1e2009-06-15 20:52:123832 bool did_complete_with_expected_referrer() const {
3833 return called_start_with_referrer_ && called_finish_with_referrer_;
3834 }
3835
3836 private:
3837 GURL expected_referrer_;
3838 bool called_start_with_referrer_;
3839 bool called_finish_with_referrer_;
3840
3841 DISALLOW_COPY_AND_ASSIGN(ResolutionReferrerObserver);
3842};
3843
3844// Make sure that when HostResolver::Resolve() is invoked, it passes through
3845// the "referrer". This is depended on by the DNS prefetch observer.
3846TEST_F(HttpNetworkTransactionTest, ResolveMadeWithReferrer) {
3847 GURL referrer = GURL("http://expected-referrer/");
3848 EXPECT_TRUE(referrer.is_valid());
3849 ResolutionReferrerObserver resolution_observer(referrer);
3850
3851 SessionDependencies session_deps;
3852 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(
[email protected]5695b8c2009-09-30 21:36:433853 CreateSession(&session_deps)));
[email protected]f3e6c1e2009-06-15 20:52:123854
3855 // Attach an observer to watch the host resolutions being made.
[email protected]94a0d3d92009-06-27 01:50:143856 session_deps.host_resolver->AddObserver(&resolution_observer);
[email protected]f3e6c1e2009-06-15 20:52:123857
3858 // Connect up a mock socket which will fail when reading.
3859 MockRead data_reads[] = {
3860 MockRead(false, ERR_FAILED),
3861 };
[email protected]31a2bfe2010-02-09 08:03:393862 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:593863 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]f3e6c1e2009-06-15 20:52:123864
3865 // Issue a request, containing an HTTP referrer.
3866 HttpRequestInfo request;
3867 request.method = "GET";
3868 request.referrer = referrer;
3869 request.url = GURL("http://www.google.com/");
3870
3871 // Run the request until it fails reading from the socket.
3872 TestCompletionCallback callback;
[email protected]684970b2009-08-14 04:54:463873 int rv = trans->Start(&request, &callback, NULL);
[email protected]f3e6c1e2009-06-15 20:52:123874 EXPECT_EQ(ERR_IO_PENDING, rv);
3875 rv = callback.WaitForResult();
3876 EXPECT_EQ(ERR_FAILED, rv);
3877
3878 // Check that the host resolution observer saw |referrer|.
3879 EXPECT_TRUE(resolution_observer.did_complete_with_expected_referrer());
3880}
3881
[email protected]3b9cca42009-06-16 01:08:283882// Make sure that when the load flags contain LOAD_BYPASS_CACHE, the resolver's
3883// host cache is bypassed.
3884TEST_F(HttpNetworkTransactionTest, BypassHostCacheOnRefresh) {
3885 SessionDependencies session_deps;
[email protected]b59ff372009-07-15 22:04:323886
[email protected]a2c2fb92009-07-18 07:31:043887 // Select a host resolver that does caching.
3888 session_deps.host_resolver = new MockCachingHostResolver;
[email protected]b59ff372009-07-15 22:04:323889
[email protected]3b9cca42009-06-16 01:08:283890 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(
[email protected]5695b8c2009-09-30 21:36:433891 CreateSession(&session_deps)));
[email protected]3b9cca42009-06-16 01:08:283892
3893 // Warm up the host cache so it has an entry for "www.google.com" (by doing
3894 // a synchronous lookup.)
3895 AddressList addrlist;
[email protected]94a0d3d92009-06-27 01:50:143896 int rv = session_deps.host_resolver->Resolve(
[email protected]684970b2009-08-14 04:54:463897 HostResolver::RequestInfo("www.google.com", 80), &addrlist,
3898 NULL, NULL, NULL);
[email protected]3b9cca42009-06-16 01:08:283899 EXPECT_EQ(OK, rv);
3900
3901 // Verify that it was added to host cache, by doing a subsequent async lookup
3902 // and confirming it completes synchronously.
3903 TestCompletionCallback resolve_callback;
[email protected]684970b2009-08-14 04:54:463904 rv = session_deps.host_resolver->Resolve(
[email protected]3b9cca42009-06-16 01:08:283905 HostResolver::RequestInfo("www.google.com", 80), &addrlist,
[email protected]684970b2009-08-14 04:54:463906 &resolve_callback, NULL, NULL);
[email protected]b59ff372009-07-15 22:04:323907 ASSERT_EQ(OK, rv);
[email protected]3b9cca42009-06-16 01:08:283908
3909 // Inject a failure the next time that "www.google.com" is resolved. This way
3910 // we can tell if the next lookup hit the cache, or the "network".
3911 // (cache --> success, "network" --> failure).
[email protected]b59ff372009-07-15 22:04:323912 session_deps.host_resolver->rules()->AddSimulatedFailure("www.google.com");
[email protected]3b9cca42009-06-16 01:08:283913
3914 // Connect up a mock socket which will fail with ERR_UNEXPECTED during the
3915 // first read -- this won't be reached as the host resolution will fail first.
3916 MockRead data_reads[] = { MockRead(false, ERR_UNEXPECTED) };
[email protected]31a2bfe2010-02-09 08:03:393917 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:593918 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]3b9cca42009-06-16 01:08:283919
3920 // Issue a request, asking to bypass the cache(s).
3921 HttpRequestInfo request;
3922 request.method = "GET";
3923 request.load_flags = LOAD_BYPASS_CACHE;
3924 request.url = GURL("http://www.google.com/");
3925
3926 // Run the request.
3927 TestCompletionCallback callback;
[email protected]684970b2009-08-14 04:54:463928 rv = trans->Start(&request, &callback, NULL);
[email protected]3b9cca42009-06-16 01:08:283929 ASSERT_EQ(ERR_IO_PENDING, rv);
3930 rv = callback.WaitForResult();
3931
3932 // If we bypassed the cache, we would have gotten a failure while resolving
3933 // "www.google.com".
3934 EXPECT_EQ(ERR_NAME_NOT_RESOLVED, rv);
3935}
3936
[email protected]0877e3d2009-10-17 22:29:573937// Make sure we can handle an error when writing the request.
3938TEST_F(HttpNetworkTransactionTest, RequestWriteError) {
3939 SessionDependencies session_deps;
3940 scoped_refptr<HttpNetworkSession> session = CreateSession(&session_deps);
3941
3942 HttpRequestInfo request;
3943 request.method = "GET";
3944 request.url = GURL("http://www.foo.com/");
3945 request.load_flags = 0;
3946
3947 MockWrite write_failure[] = {
3948 MockWrite(true, ERR_CONNECTION_RESET),
3949 };
[email protected]31a2bfe2010-02-09 08:03:393950 StaticSocketDataProvider data(NULL, 0,
3951 write_failure, arraysize(write_failure));
[email protected]5ecc992a42009-11-11 01:41:593952 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]0877e3d2009-10-17 22:29:573953
3954 TestCompletionCallback callback;
3955
3956 scoped_ptr<HttpTransaction> trans(
3957 new HttpNetworkTransaction(CreateSession(&session_deps)));
3958
3959 int rv = trans->Start(&request, &callback, NULL);
3960 EXPECT_EQ(ERR_IO_PENDING, rv);
3961
3962 rv = callback.WaitForResult();
3963 EXPECT_EQ(ERR_CONNECTION_RESET, rv);
3964}
3965
3966// Check that a connection closed after the start of the headers finishes ok.
3967TEST_F(HttpNetworkTransactionTest, ConnectionClosedAfterStartOfHeaders) {
3968 SessionDependencies session_deps;
3969 scoped_refptr<HttpNetworkSession> session = CreateSession(&session_deps);
3970
3971 HttpRequestInfo request;
3972 request.method = "GET";
3973 request.url = GURL("http://www.foo.com/");
3974 request.load_flags = 0;
3975
3976 MockRead data_reads[] = {
3977 MockRead("HTTP/1."),
3978 MockRead(false, OK),
3979 };
3980
[email protected]31a2bfe2010-02-09 08:03:393981 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:593982 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]0877e3d2009-10-17 22:29:573983
3984 TestCompletionCallback callback;
3985
3986 scoped_ptr<HttpTransaction> trans(
3987 new HttpNetworkTransaction(CreateSession(&session_deps)));
3988
3989 int rv = trans->Start(&request, &callback, NULL);
3990 EXPECT_EQ(ERR_IO_PENDING, rv);
3991
3992 rv = callback.WaitForResult();
3993 EXPECT_EQ(OK, rv);
3994
3995 const HttpResponseInfo* response = trans->GetResponseInfo();
3996 EXPECT_TRUE(response != NULL);
3997
3998 EXPECT_TRUE(response->headers != NULL);
3999 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
4000
4001 std::string response_data;
4002 rv = ReadTransaction(trans.get(), &response_data);
4003 EXPECT_EQ(OK, rv);
4004 EXPECT_EQ("", response_data);
4005}
4006
4007// Make sure that a dropped connection while draining the body for auth
4008// restart does the right thing.
4009TEST_F(HttpNetworkTransactionTest, DrainResetOK) {
4010 SessionDependencies session_deps;
4011 scoped_ptr<HttpTransaction> trans(
4012 new HttpNetworkTransaction(CreateSession(&session_deps)));
4013
4014 HttpRequestInfo request;
4015 request.method = "GET";
4016 request.url = GURL("http://www.google.com/");
4017 request.load_flags = 0;
4018
4019 MockWrite data_writes1[] = {
4020 MockWrite("GET / HTTP/1.1\r\n"
4021 "Host: www.google.com\r\n"
4022 "Connection: keep-alive\r\n\r\n"),
4023 };
4024
4025 MockRead data_reads1[] = {
4026 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
4027 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
4028 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
4029 MockRead("Content-Length: 14\r\n\r\n"),
4030 MockRead("Unauth"),
4031 MockRead(true, ERR_CONNECTION_RESET),
4032 };
4033
[email protected]31a2bfe2010-02-09 08:03:394034 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
4035 data_writes1, arraysize(data_writes1));
[email protected]5ecc992a42009-11-11 01:41:594036 session_deps.socket_factory.AddSocketDataProvider(&data1);
[email protected]0877e3d2009-10-17 22:29:574037
4038 // After calling trans->RestartWithAuth(), this is the request we should
4039 // be issuing -- the final header line contains the credentials.
4040 MockWrite data_writes2[] = {
4041 MockWrite("GET / HTTP/1.1\r\n"
4042 "Host: www.google.com\r\n"
4043 "Connection: keep-alive\r\n"
4044 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
4045 };
4046
4047 // Lastly, the server responds with the actual content.
4048 MockRead data_reads2[] = {
4049 MockRead("HTTP/1.1 200 OK\r\n"),
4050 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
4051 MockRead("Content-Length: 100\r\n\r\n"),
4052 MockRead(false, OK),
4053 };
4054
[email protected]31a2bfe2010-02-09 08:03:394055 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
4056 data_writes2, arraysize(data_writes2));
[email protected]5ecc992a42009-11-11 01:41:594057 session_deps.socket_factory.AddSocketDataProvider(&data2);
[email protected]0877e3d2009-10-17 22:29:574058
4059 TestCompletionCallback callback1;
4060
4061 int rv = trans->Start(&request, &callback1, NULL);
4062 EXPECT_EQ(ERR_IO_PENDING, rv);
4063
4064 rv = callback1.WaitForResult();
4065 EXPECT_EQ(OK, rv);
4066
4067 const HttpResponseInfo* response = trans->GetResponseInfo();
4068 EXPECT_FALSE(response == NULL);
4069
4070 // The password prompt info should have been set in response->auth_challenge.
4071 EXPECT_FALSE(response->auth_challenge.get() == NULL);
4072
4073 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
4074 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
4075 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
4076
4077 TestCompletionCallback callback2;
4078
4079 rv = trans->RestartWithAuth(L"foo", L"bar", &callback2);
4080 EXPECT_EQ(ERR_IO_PENDING, rv);
4081
4082 rv = callback2.WaitForResult();
4083 EXPECT_EQ(OK, rv);
4084
4085 response = trans->GetResponseInfo();
4086 EXPECT_FALSE(response == NULL);
4087 EXPECT_TRUE(response->auth_challenge.get() == NULL);
4088 EXPECT_EQ(100, response->headers->GetContentLength());
4089}
4090
4091// Test HTTPS connections going through a proxy that sends extra data.
4092TEST_F(HttpNetworkTransactionTest, HTTPSViaProxyWithExtraData) {
4093 SessionDependencies session_deps(CreateFixedProxyService("myproxy:70"));
4094
4095 HttpRequestInfo request;
4096 request.method = "GET";
4097 request.url = GURL("https://www.google.com/");
4098 request.load_flags = 0;
4099
4100 MockRead proxy_reads[] = {
4101 MockRead("HTTP/1.0 200 Connected\r\n\r\nExtra data"),
4102 MockRead(false, OK)
4103 };
4104
[email protected]31a2bfe2010-02-09 08:03:394105 StaticSocketDataProvider data(proxy_reads, arraysize(proxy_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:594106 SSLSocketDataProvider ssl(true, OK);
[email protected]0877e3d2009-10-17 22:29:574107
[email protected]5ecc992a42009-11-11 01:41:594108 session_deps.socket_factory.AddSocketDataProvider(&data);
4109 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
[email protected]0877e3d2009-10-17 22:29:574110
4111 TestCompletionCallback callback;
4112
4113 session_deps.socket_factory.ResetNextMockIndexes();
4114
4115 scoped_ptr<HttpTransaction> trans(
4116 new HttpNetworkTransaction(CreateSession(&session_deps)));
4117
4118 int rv = trans->Start(&request, &callback, NULL);
4119 EXPECT_EQ(ERR_IO_PENDING, rv);
4120
4121 rv = callback.WaitForResult();
4122 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED, rv);
4123}
4124
[email protected]e22e1362009-11-23 21:31:124125TEST_F(HttpNetworkTransactionTest, LargeContentLengthThenClose) {
[email protected]9492e4a2010-02-24 00:58:464126 SessionDependencies session_deps;
4127 scoped_ptr<HttpTransaction> trans(
4128 new HttpNetworkTransaction(CreateSession(&session_deps)));
4129
4130 HttpRequestInfo request;
4131 request.method = "GET";
4132 request.url = GURL("http://www.google.com/");
4133 request.load_flags = 0;
4134
[email protected]e22e1362009-11-23 21:31:124135 MockRead data_reads[] = {
4136 MockRead("HTTP/1.0 200 OK\r\nContent-Length:6719476739\r\n\r\n"),
4137 MockRead(false, OK),
4138 };
[email protected]9492e4a2010-02-24 00:58:464139
4140 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
4141 session_deps.socket_factory.AddSocketDataProvider(&data);
4142
4143 TestCompletionCallback callback;
4144
4145 int rv = trans->Start(&request, &callback, NULL);
4146 EXPECT_EQ(ERR_IO_PENDING, rv);
4147
4148 EXPECT_EQ(OK, callback.WaitForResult());
4149
4150 const HttpResponseInfo* response = trans->GetResponseInfo();
4151 EXPECT_TRUE(response != NULL);
4152
4153 EXPECT_TRUE(response->headers != NULL);
4154 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
4155
4156 std::string response_data;
4157 rv = ReadTransaction(trans.get(), &response_data);
4158 EXPECT_EQ(ERR_CONNECTION_CLOSED, rv);
[email protected]e22e1362009-11-23 21:31:124159}
4160
[email protected]95d88ffe2010-02-04 21:25:334161TEST_F(HttpNetworkTransactionTest, UploadFileSmallerThanLength) {
4162 SessionDependencies session_deps;
4163 scoped_ptr<HttpTransaction> trans(
4164 new HttpNetworkTransaction(CreateSession(&session_deps)));
4165
4166 HttpRequestInfo request;
4167 request.method = "POST";
4168 request.url = GURL("http://www.google.com/upload");
4169 request.upload_data = new UploadData;
4170 request.load_flags = 0;
4171
4172 FilePath temp_file_path;
4173 ASSERT_TRUE(file_util::CreateTemporaryFile(&temp_file_path));
4174 const uint64 kFakeSize = 100000; // file is actually blank
4175
4176 std::vector<UploadData::Element> elements;
4177 UploadData::Element element;
4178 element.SetToFilePath(temp_file_path);
4179 element.SetContentLength(kFakeSize);
4180 elements.push_back(element);
4181 request.upload_data->set_elements(elements);
4182 EXPECT_EQ(kFakeSize, request.upload_data->GetContentLength());
4183
4184 MockRead data_reads[] = {
4185 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
4186 MockRead("hello world"),
4187 MockRead(false, OK),
4188 };
[email protected]31a2bfe2010-02-09 08:03:394189 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]95d88ffe2010-02-04 21:25:334190 session_deps.socket_factory.AddSocketDataProvider(&data);
4191
4192 TestCompletionCallback callback;
4193
4194 int rv = trans->Start(&request, &callback, NULL);
4195 EXPECT_EQ(ERR_IO_PENDING, rv);
4196
4197 rv = callback.WaitForResult();
4198 EXPECT_EQ(OK, rv);
4199
4200 const HttpResponseInfo* response = trans->GetResponseInfo();
4201 EXPECT_TRUE(response != NULL);
4202
4203 EXPECT_TRUE(response->headers != NULL);
4204 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
4205
4206 std::string response_data;
4207 rv = ReadTransaction(trans.get(), &response_data);
4208 EXPECT_EQ(OK, rv);
4209 EXPECT_EQ("hello world", response_data);
4210
4211 file_util::Delete(temp_file_path, false);
4212}
4213
[email protected]6624b4622010-03-29 19:58:364214TEST_F(HttpNetworkTransactionTest, UploadUnreadableFile) {
4215 // If we try to upload an unreadable file, the network stack should report
4216 // the file size as zero and upload zero bytes for that file.
4217 SessionDependencies session_deps;
4218 scoped_ptr<HttpTransaction> trans(
4219 new HttpNetworkTransaction(CreateSession(&session_deps)));
4220
4221 FilePath temp_file;
4222 ASSERT_TRUE(file_util::CreateTemporaryFile(&temp_file));
4223 std::string temp_file_content("Unreadable file.");
4224 ASSERT_TRUE(file_util::WriteFile(temp_file, temp_file_content.c_str(),
4225 temp_file_content.length()));
4226 ASSERT_TRUE(file_util::MakeFileUnreadable(temp_file));
4227
4228 HttpRequestInfo request;
4229 request.method = "POST";
4230 request.url = GURL("http://www.google.com/upload");
4231 request.upload_data = new UploadData;
4232 request.load_flags = 0;
4233
4234 std::vector<UploadData::Element> elements;
4235 UploadData::Element element;
4236 element.SetToFilePath(temp_file);
4237 elements.push_back(element);
4238 request.upload_data->set_elements(elements);
4239
4240 MockRead data_reads[] = {
4241 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
4242 MockRead(false, OK),
4243 };
4244 MockWrite data_writes[] = {
4245 MockWrite("POST /upload HTTP/1.1\r\n"
4246 "Host: www.google.com\r\n"
4247 "Connection: keep-alive\r\n"
4248 "Content-Length: 0\r\n\r\n"),
4249 MockWrite(false, OK),
4250 };
4251 StaticSocketDataProvider data(data_reads, arraysize(data_reads), data_writes,
4252 arraysize(data_writes));
4253 session_deps.socket_factory.AddSocketDataProvider(&data);
4254
4255 TestCompletionCallback callback;
4256
4257 int rv = trans->Start(&request, &callback, NULL);
4258 EXPECT_EQ(ERR_IO_PENDING, rv);
4259
4260 rv = callback.WaitForResult();
4261 EXPECT_EQ(OK, rv);
4262
4263 const HttpResponseInfo* response = trans->GetResponseInfo();
4264 EXPECT_TRUE(response != NULL);
4265 EXPECT_TRUE(response->headers != NULL);
4266 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
4267
4268 file_util::Delete(temp_file, false);
4269}
4270
4271TEST_F(HttpNetworkTransactionTest, UnreadableUploadFileAfterAuthRestart) {
4272 SessionDependencies session_deps;
4273 scoped_ptr<HttpTransaction> trans(
4274 new HttpNetworkTransaction(CreateSession(&session_deps)));
4275
4276 FilePath temp_file;
4277 ASSERT_TRUE(file_util::CreateTemporaryFile(&temp_file));
4278 std::string temp_file_contents("Unreadable file.");
4279 std::string unreadable_contents(temp_file_contents.length(), '\0');
4280 ASSERT_TRUE(file_util::WriteFile(temp_file, temp_file_contents.c_str(),
4281 temp_file_contents.length()));
4282
4283 HttpRequestInfo request;
4284 request.method = "POST";
4285 request.url = GURL("http://www.google.com/upload");
4286 request.upload_data = new UploadData;
4287 request.load_flags = 0;
4288
4289 std::vector<UploadData::Element> elements;
4290 UploadData::Element element;
4291 element.SetToFilePath(temp_file);
4292 elements.push_back(element);
4293 request.upload_data->set_elements(elements);
4294
4295 MockRead data_reads[] = {
4296 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
4297 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
4298 MockRead("Content-Length: 0\r\n\r\n"), // No response body.
4299
4300 MockRead("HTTP/1.1 200 OK\r\n"),
4301 MockRead("Content-Length: 0\r\n\r\n"),
4302 MockRead(false, OK),
4303 };
4304 MockWrite data_writes[] = {
4305 MockWrite("POST /upload HTTP/1.1\r\n"
4306 "Host: www.google.com\r\n"
4307 "Connection: keep-alive\r\n"
4308 "Content-Length: 16\r\n\r\n"),
4309 MockWrite(false, temp_file_contents.c_str()),
4310
4311 MockWrite("POST /upload HTTP/1.1\r\n"
4312 "Host: www.google.com\r\n"
4313 "Connection: keep-alive\r\n"
4314 "Content-Length: 16\r\n"
4315 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
4316 MockWrite(false, unreadable_contents.c_str(), temp_file_contents.length()),
4317 MockWrite(false, OK),
4318 };
4319 StaticSocketDataProvider data(data_reads, arraysize(data_reads), data_writes,
4320 arraysize(data_writes));
4321 session_deps.socket_factory.AddSocketDataProvider(&data);
4322
4323 TestCompletionCallback callback1;
4324
4325 int rv = trans->Start(&request, &callback1, NULL);
4326 EXPECT_EQ(ERR_IO_PENDING, rv);
4327
4328 rv = callback1.WaitForResult();
4329 EXPECT_EQ(OK, rv);
4330
4331 const HttpResponseInfo* response = trans->GetResponseInfo();
4332 EXPECT_TRUE(response != NULL);
4333 EXPECT_TRUE(response->headers != NULL);
4334 EXPECT_EQ("HTTP/1.1 401 Unauthorized", response->headers->GetStatusLine());
4335
4336 // The password prompt info should have been set in response->auth_challenge.
4337 EXPECT_TRUE(response->auth_challenge.get() != NULL);
4338 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
4339 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
4340 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
4341
4342 // Now make the file unreadable and try again.
4343 ASSERT_TRUE(file_util::MakeFileUnreadable(temp_file));
4344
4345 TestCompletionCallback callback2;
4346
4347 rv = trans->RestartWithAuth(L"foo", L"bar", &callback2);
4348 EXPECT_EQ(ERR_IO_PENDING, rv);
4349
4350 rv = callback2.WaitForResult();
4351 EXPECT_EQ(OK, rv);
4352
4353 response = trans->GetResponseInfo();
4354 EXPECT_TRUE(response != NULL);
4355 EXPECT_TRUE(response->headers != NULL);
4356 EXPECT_TRUE(response->auth_challenge.get() == NULL);
4357 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
4358
4359 file_util::Delete(temp_file, false);
4360}
4361
[email protected]aeefc9e82010-02-19 16:18:274362// Tests that changes to Auth realms are treated like auth rejections.
4363TEST_F(HttpNetworkTransactionTest, ChangeAuthRealms) {
4364 SessionDependencies session_deps;
4365 scoped_ptr<HttpTransaction> trans(
4366 new HttpNetworkTransaction(CreateSession(&session_deps)));
4367
4368 HttpRequestInfo request;
4369 request.method = "GET";
4370 request.url = GURL("http://www.google.com/");
4371 request.load_flags = 0;
4372
4373 // First transaction will request a resource and receive a Basic challenge
4374 // with realm="first_realm".
4375 MockWrite data_writes1[] = {
4376 MockWrite("GET / HTTP/1.1\r\n"
4377 "Host: www.google.com\r\n"
4378 "Connection: keep-alive\r\n"
4379 "\r\n"),
4380 };
4381 MockRead data_reads1[] = {
4382 MockRead("HTTP/1.1 401 Unauthorized\r\n"
4383 "WWW-Authenticate: Basic realm=\"first_realm\"\r\n"
4384 "\r\n"),
4385 };
4386
4387 // After calling trans->RestartWithAuth(), provide an Authentication header
4388 // for first_realm. The server will reject and provide a challenge with
4389 // second_realm.
4390 MockWrite data_writes2[] = {
4391 MockWrite("GET / HTTP/1.1\r\n"
4392 "Host: www.google.com\r\n"
4393 "Connection: keep-alive\r\n"
4394 "Authorization: Basic Zmlyc3Q6YmF6\r\n"
4395 "\r\n"),
4396 };
4397 MockRead data_reads2[] = {
4398 MockRead("HTTP/1.1 401 Unauthorized\r\n"
4399 "WWW-Authenticate: Basic realm=\"second_realm\"\r\n"
4400 "\r\n"),
4401 };
4402
4403 // This again fails, and goes back to first_realm. Make sure that the
4404 // entry is removed from cache.
4405 MockWrite data_writes3[] = {
4406 MockWrite("GET / HTTP/1.1\r\n"
4407 "Host: www.google.com\r\n"
4408 "Connection: keep-alive\r\n"
4409 "Authorization: Basic c2Vjb25kOmZvdQ==\r\n"
4410 "\r\n"),
4411 };
4412 MockRead data_reads3[] = {
4413 MockRead("HTTP/1.1 401 Unauthorized\r\n"
4414 "WWW-Authenticate: Basic realm=\"first_realm\"\r\n"
4415 "\r\n"),
4416 };
4417
4418 // Try one last time (with the correct password) and get the resource.
4419 MockWrite data_writes4[] = {
4420 MockWrite("GET / HTTP/1.1\r\n"
4421 "Host: www.google.com\r\n"
4422 "Connection: keep-alive\r\n"
4423 "Authorization: Basic Zmlyc3Q6YmFy\r\n"
4424 "\r\n"),
4425 };
4426 MockRead data_reads4[] = {
4427 MockRead("HTTP/1.1 200 OK\r\n"
4428 "Content-Type: text/html; charset=iso-8859-1\r\n"
4429 "Content-Length: 100\r\n"
4430 "\r\n"),
4431 };
4432
4433 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
4434 data_writes1, arraysize(data_writes1));
4435 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
4436 data_writes2, arraysize(data_writes2));
4437 StaticSocketDataProvider data3(data_reads3, arraysize(data_reads3),
4438 data_writes3, arraysize(data_writes3));
4439 StaticSocketDataProvider data4(data_reads4, arraysize(data_reads4),
4440 data_writes4, arraysize(data_writes4));
4441 session_deps.socket_factory.AddSocketDataProvider(&data1);
4442 session_deps.socket_factory.AddSocketDataProvider(&data2);
4443 session_deps.socket_factory.AddSocketDataProvider(&data3);
4444 session_deps.socket_factory.AddSocketDataProvider(&data4);
4445
4446 TestCompletionCallback callback1;
4447
4448 // Issue the first request with Authorize headers. There should be a
4449 // password prompt for first_realm waiting to be filled in after the
4450 // transaction completes.
4451 int rv = trans->Start(&request, &callback1, NULL);
4452 EXPECT_EQ(ERR_IO_PENDING, rv);
4453 rv = callback1.WaitForResult();
4454 EXPECT_EQ(OK, rv);
4455 const HttpResponseInfo* response = trans->GetResponseInfo();
4456 ASSERT_FALSE(response == NULL);
4457 ASSERT_FALSE(response->auth_challenge.get() == NULL);
4458 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
4459 EXPECT_EQ(L"first_realm", response->auth_challenge->realm);
4460 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
4461
4462 // Issue the second request with an incorrect password. There should be a
4463 // password prompt for second_realm waiting to be filled in after the
4464 // transaction completes.
4465 TestCompletionCallback callback2;
4466 rv = trans->RestartWithAuth(L"first", L"baz", &callback2);
4467 EXPECT_EQ(ERR_IO_PENDING, rv);
4468 rv = callback2.WaitForResult();
4469 EXPECT_EQ(OK, rv);
4470 response = trans->GetResponseInfo();
4471 ASSERT_FALSE(response == NULL);
4472 ASSERT_FALSE(response->auth_challenge.get() == NULL);
4473 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
4474 EXPECT_EQ(L"second_realm", response->auth_challenge->realm);
4475 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
4476
4477 // Issue the third request with another incorrect password. There should be
4478 // a password prompt for first_realm waiting to be filled in. If the password
4479 // prompt is not present, it indicates that the HttpAuthCacheEntry for
4480 // first_realm was not correctly removed.
4481 TestCompletionCallback callback3;
4482 rv = trans->RestartWithAuth(L"second", L"fou", &callback3);
4483 EXPECT_EQ(ERR_IO_PENDING, rv);
4484 rv = callback3.WaitForResult();
4485 EXPECT_EQ(OK, rv);
4486 response = trans->GetResponseInfo();
4487 ASSERT_FALSE(response == NULL);
4488 ASSERT_FALSE(response->auth_challenge.get() == NULL);
4489 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
4490 EXPECT_EQ(L"first_realm", response->auth_challenge->realm);
4491 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
4492
4493 // Issue the fourth request with the correct password and username.
4494 TestCompletionCallback callback4;
4495 rv = trans->RestartWithAuth(L"first", L"bar", &callback4);
4496 EXPECT_EQ(ERR_IO_PENDING, rv);
4497 rv = callback4.WaitForResult();
4498 EXPECT_EQ(OK, rv);
4499 response = trans->GetResponseInfo();
4500 ASSERT_FALSE(response == NULL);
4501 EXPECT_TRUE(response->auth_challenge.get() == NULL);
4502}
4503
[email protected]564b4912010-03-09 16:30:424504TEST_F(HttpNetworkTransactionTest, HonorAlternateProtocolHeader) {
[email protected]a2cb8122010-03-10 17:22:424505 HttpNetworkTransaction::SetNextProtos("needs_to_be_set_for_this_test");
[email protected]31e2c69e2010-04-15 18:06:064506 HttpNetworkTransaction::SetUseAlternateProtocols(true);
[email protected]a2cb8122010-03-10 17:22:424507
[email protected]564b4912010-03-09 16:30:424508 SessionDependencies session_deps;
4509
4510 MockRead data_reads[] = {
4511 MockRead("HTTP/1.1 200 OK\r\n"),
[email protected]31e2c69e2010-04-15 18:06:064512 MockRead("Alternate-Protocol: 443:npn-spdy/1\r\n\r\n"),
[email protected]564b4912010-03-09 16:30:424513 MockRead("hello world"),
4514 MockRead(false, OK),
4515 };
4516
4517 HttpRequestInfo request;
4518 request.method = "GET";
4519 request.url = GURL("http://www.google.com/");
4520 request.load_flags = 0;
4521
4522 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
4523
4524 session_deps.socket_factory.AddSocketDataProvider(&data);
4525
4526 TestCompletionCallback callback;
4527
4528 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
4529 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
4530
4531 int rv = trans->Start(&request, &callback, NULL);
4532 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]9e743cd2010-03-16 07:03:534533
[email protected]564b4912010-03-09 16:30:424534 HostPortPair http_host_port_pair;
4535 http_host_port_pair.host = "www.google.com";
4536 http_host_port_pair.port = 80;
4537 const HttpAlternateProtocols& alternate_protocols =
4538 session->alternate_protocols();
4539 EXPECT_FALSE(
4540 alternate_protocols.HasAlternateProtocolFor(http_host_port_pair));
4541
4542 EXPECT_EQ(OK, callback.WaitForResult());
4543
4544 const HttpResponseInfo* response = trans->GetResponseInfo();
4545 ASSERT_TRUE(response != NULL);
4546 ASSERT_TRUE(response->headers != NULL);
4547 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
4548
4549 std::string response_data;
4550 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
4551 EXPECT_EQ("hello world", response_data);
4552
4553 ASSERT_TRUE(alternate_protocols.HasAlternateProtocolFor(http_host_port_pair));
4554 const HttpAlternateProtocols::PortProtocolPair alternate =
4555 alternate_protocols.GetAlternateProtocolFor(http_host_port_pair);
4556 HttpAlternateProtocols::PortProtocolPair expected_alternate;
4557 expected_alternate.port = 443;
[email protected]31e2c69e2010-04-15 18:06:064558 expected_alternate.protocol = HttpAlternateProtocols::NPN_SPDY_1;
[email protected]564b4912010-03-09 16:30:424559 EXPECT_TRUE(expected_alternate.Equals(alternate));
[email protected]a2cb8122010-03-10 17:22:424560
[email protected]31e2c69e2010-04-15 18:06:064561 HttpNetworkTransaction::SetUseAlternateProtocols(false);
[email protected]a2cb8122010-03-10 17:22:424562 HttpNetworkTransaction::SetNextProtos("");
[email protected]564b4912010-03-09 16:30:424563}
4564
4565TEST_F(HttpNetworkTransactionTest, MarkBrokenAlternateProtocol) {
[email protected]31e2c69e2010-04-15 18:06:064566 HttpNetworkTransaction::SetUseAlternateProtocols(true);
[email protected]564b4912010-03-09 16:30:424567 SessionDependencies session_deps;
4568
4569 HttpRequestInfo request;
4570 request.method = "GET";
4571 request.url = GURL("http://www.google.com/");
4572 request.load_flags = 0;
4573
4574 MockConnect mock_connect(true, ERR_CONNECTION_REFUSED);
4575 StaticSocketDataProvider first_data;
4576 first_data.set_connect_data(mock_connect);
4577 session_deps.socket_factory.AddSocketDataProvider(&first_data);
4578
4579 MockRead data_reads[] = {
4580 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
4581 MockRead("hello world"),
4582 MockRead(true, OK),
4583 };
4584 StaticSocketDataProvider second_data(
4585 data_reads, arraysize(data_reads), NULL, 0);
4586 session_deps.socket_factory.AddSocketDataProvider(&second_data);
4587
4588 // TODO(willchan): Delete this extra data provider. It's necessary due to a
4589 // ClientSocketPoolBaseHelper bug that starts up too many ConnectJobs:
4590 // http://crbug.com/37454.
4591 session_deps.socket_factory.AddSocketDataProvider(&second_data);
4592
4593 TestCompletionCallback callback;
4594
4595 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
4596
4597 HostPortPair http_host_port_pair;
4598 http_host_port_pair.host = "www.google.com";
4599 http_host_port_pair.port = 80;
4600 HttpAlternateProtocols* alternate_protocols =
4601 session->mutable_alternate_protocols();
4602 alternate_protocols->SetAlternateProtocolFor(
4603 http_host_port_pair, 1234 /* port is ignored by MockConnect anyway */,
[email protected]31e2c69e2010-04-15 18:06:064604 HttpAlternateProtocols::NPN_SPDY_1);
[email protected]564b4912010-03-09 16:30:424605
4606 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
4607
4608 int rv = trans->Start(&request, &callback, NULL);
4609 EXPECT_EQ(ERR_IO_PENDING, rv);
4610 EXPECT_EQ(OK, callback.WaitForResult());
4611
4612 const HttpResponseInfo* response = trans->GetResponseInfo();
4613 ASSERT_TRUE(response != NULL);
4614 ASSERT_TRUE(response->headers != NULL);
4615 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
4616
4617 std::string response_data;
4618 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
4619 EXPECT_EQ("hello world", response_data);
4620
4621 ASSERT_TRUE(
4622 alternate_protocols->HasAlternateProtocolFor(http_host_port_pair));
4623 const HttpAlternateProtocols::PortProtocolPair alternate =
4624 alternate_protocols->GetAlternateProtocolFor(http_host_port_pair);
4625 EXPECT_EQ(HttpAlternateProtocols::BROKEN, alternate.protocol);
[email protected]31e2c69e2010-04-15 18:06:064626 HttpNetworkTransaction::SetUseAlternateProtocols(false);
[email protected]564b4912010-03-09 16:30:424627}
4628
4629// TODO(willchan): Redo this test to use TLS/NPN=>SPDY. Currently, the code
4630// says that it does SPDY, but it just does the TLS handshake, but the NPN
4631// response does not indicate SPDY, so we just do standard HTTPS over the port.
4632// We should add code such that we don't fallback to HTTPS, but fallback to HTTP
4633// on the original port.
[email protected]a2cb8122010-03-10 17:22:424634// TEST_F(HttpNetworkTransactionTest, UseAlternateProtocol) {
4635// SessionDependencies session_deps;
[email protected]9e743cd2010-03-16 07:03:534636//
[email protected]a2cb8122010-03-10 17:22:424637// HttpRequestInfo request;
4638// request.method = "GET";
4639// request.url = GURL("http://www.google.com/");
4640// request.load_flags = 0;
[email protected]9e743cd2010-03-16 07:03:534641//
[email protected]a2cb8122010-03-10 17:22:424642// MockRead data_reads[] = {
4643// MockRead("HTTP/1.1 200 OK\r\n\r\n"),
4644// MockRead("hello world"),
4645// MockRead(true, OK),
4646// };
4647// StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
4648// session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]9e743cd2010-03-16 07:03:534649//
[email protected]a2cb8122010-03-10 17:22:424650// SSLSocketDataProvider ssl(true, OK);
4651// session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
[email protected]9e743cd2010-03-16 07:03:534652//
[email protected]a2cb8122010-03-10 17:22:424653// TestCompletionCallback callback;
[email protected]9e743cd2010-03-16 07:03:534654//
[email protected]a2cb8122010-03-10 17:22:424655// scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]9e743cd2010-03-16 07:03:534656//
[email protected]a2cb8122010-03-10 17:22:424657// HostPortPair http_host_port_pair;
4658// http_host_port_pair.host = "www.google.com";
4659// http_host_port_pair.port = 80;
4660// HttpAlternateProtocols* alternate_protocols =
4661// session->mutable_alternate_protocols();
4662// alternate_protocols->SetAlternateProtocolFor(
4663// http_host_port_pair, 1234 /* port is ignored */,
[email protected]31e2c69e2010-04-15 18:06:064664// HttpAlternateProtocols::NPN_SPDY_1);
[email protected]9e743cd2010-03-16 07:03:534665//
[email protected]a2cb8122010-03-10 17:22:424666// scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]9e743cd2010-03-16 07:03:534667//
[email protected]a2cb8122010-03-10 17:22:424668// int rv = trans->Start(&request, &callback, NULL);
4669// EXPECT_EQ(ERR_IO_PENDING, rv);
4670// EXPECT_EQ(OK, callback.WaitForResult());
[email protected]9e743cd2010-03-16 07:03:534671//
[email protected]a2cb8122010-03-10 17:22:424672// const HttpResponseInfo* response = trans->GetResponseInfo();
4673// ASSERT_TRUE(response != NULL);
4674// ASSERT_TRUE(response->headers != NULL);
4675// EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
[email protected]9e743cd2010-03-16 07:03:534676//
[email protected]a2cb8122010-03-10 17:22:424677// std::string response_data;
4678// ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
4679// EXPECT_EQ("hello world", response_data);
4680// }
4681
4682TEST_F(HttpNetworkTransactionTest, FailNpnSpdyAndFallback) {
[email protected]31e2c69e2010-04-15 18:06:064683 HttpNetworkTransaction::SetUseAlternateProtocols(true);
[email protected]2ff8b312010-04-26 22:20:544684 HttpNetworkTransaction::SetNextProtos(
4685 "\x08http/1.1\x07http1.1\x06spdy/1\x04spdy");
[email protected]564b4912010-03-09 16:30:424686 SessionDependencies session_deps;
4687
4688 HttpRequestInfo request;
4689 request.method = "GET";
4690 request.url = GURL("http://www.google.com/");
4691 request.load_flags = 0;
4692
[email protected]a2cb8122010-03-10 17:22:424693 StaticSocketDataProvider first_tcp_connect;
4694 session_deps.socket_factory.AddSocketDataProvider(&first_tcp_connect);
4695
4696 SSLSocketDataProvider ssl(true, OK);
4697 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
4698
[email protected]564b4912010-03-09 16:30:424699 MockRead data_reads[] = {
4700 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
4701 MockRead("hello world"),
4702 MockRead(true, OK),
4703 };
[email protected]a2cb8122010-03-10 17:22:424704 StaticSocketDataProvider fallback_data(
4705 data_reads, arraysize(data_reads), NULL, 0);
4706 session_deps.socket_factory.AddSocketDataProvider(&fallback_data);
[email protected]564b4912010-03-09 16:30:424707
4708 TestCompletionCallback callback;
4709
4710 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
4711
4712 HostPortPair http_host_port_pair;
4713 http_host_port_pair.host = "www.google.com";
4714 http_host_port_pair.port = 80;
4715 HttpAlternateProtocols* alternate_protocols =
4716 session->mutable_alternate_protocols();
4717 alternate_protocols->SetAlternateProtocolFor(
4718 http_host_port_pair, 1234 /* port is ignored */,
[email protected]31e2c69e2010-04-15 18:06:064719 HttpAlternateProtocols::NPN_SPDY_1);
[email protected]564b4912010-03-09 16:30:424720
4721 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
4722
4723 int rv = trans->Start(&request, &callback, NULL);
4724 EXPECT_EQ(ERR_IO_PENDING, rv);
4725 EXPECT_EQ(OK, callback.WaitForResult());
4726
4727 const HttpResponseInfo* response = trans->GetResponseInfo();
4728 ASSERT_TRUE(response != NULL);
4729 ASSERT_TRUE(response->headers != NULL);
4730 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
4731
4732 std::string response_data;
4733 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
4734 EXPECT_EQ("hello world", response_data);
[email protected]2ff8b312010-04-26 22:20:544735 HttpNetworkTransaction::SetNextProtos("");
4736 HttpNetworkTransaction::SetUseAlternateProtocols(false);
4737}
4738
4739TEST_F(HttpNetworkTransactionTest, UseAlternateProtocolForNpnSpdy) {
4740 HttpNetworkTransaction::SetUseAlternateProtocols(true);
4741 HttpNetworkTransaction::SetNextProtos(
4742 "\x08http/1.1\x07http1.1\x06spdy/1\x04spdy");
4743 SessionDependencies session_deps;
4744
4745 HttpRequestInfo request;
4746 request.method = "GET";
4747 request.url = GURL("http://www.google.com/");
4748 request.load_flags = 0;
4749
4750 MockRead data_reads[] = {
4751 MockRead("HTTP/1.1 200 OK\r\n"),
4752 MockRead("Alternate-Protocol: 443:npn-spdy/1\r\n\r\n"),
4753 MockRead("hello world"),
4754 MockRead(true, OK),
4755 };
4756
4757 StaticSocketDataProvider first_transaction(
4758 data_reads, arraysize(data_reads), NULL, 0);
4759 session_deps.socket_factory.AddSocketDataProvider(&first_transaction);
4760
4761 SSLSocketDataProvider ssl(true, OK);
4762 ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
4763 ssl.next_proto = "spdy/1";
4764 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
4765
4766 MockWrite spdy_writes[] = {
4767 MockWrite(true, reinterpret_cast<const char*>(kGetSyn),
4768 arraysize(kGetSyn)),
4769 };
4770
4771 MockRead spdy_reads[] = {
4772 MockRead(true, reinterpret_cast<const char*>(kGetSynReply),
4773 arraysize(kGetSynReply)),
4774 MockRead(true, reinterpret_cast<const char*>(kGetBodyFrame),
4775 arraysize(kGetBodyFrame)),
4776 MockRead(true, 0, 0),
4777 };
4778
4779 scoped_refptr<DelayedSocketData> spdy_data(
4780 new DelayedSocketData(
4781 1, // wait for one write to finish before reading.
4782 spdy_reads, arraysize(spdy_reads),
4783 spdy_writes, arraysize(spdy_writes)));
4784 session_deps.socket_factory.AddSocketDataProvider(spdy_data);
4785
4786 TestCompletionCallback callback;
4787
4788 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
4789 scoped_ptr<HttpNetworkTransaction> trans(new HttpNetworkTransaction(session));
4790
4791 int rv = trans->Start(&request, &callback, NULL);
4792 EXPECT_EQ(ERR_IO_PENDING, rv);
4793 EXPECT_EQ(OK, callback.WaitForResult());
4794
4795 const HttpResponseInfo* response = trans->GetResponseInfo();
4796 ASSERT_TRUE(response != NULL);
4797 ASSERT_TRUE(response->headers != NULL);
4798 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
4799
4800 std::string response_data;
4801 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
4802 EXPECT_EQ("hello world", response_data);
4803
4804 trans.reset(new HttpNetworkTransaction(session));
4805
4806 rv = trans->Start(&request, &callback, NULL);
4807 EXPECT_EQ(ERR_IO_PENDING, rv);
4808 EXPECT_EQ(OK, callback.WaitForResult());
4809
4810 response = trans->GetResponseInfo();
4811 ASSERT_TRUE(response != NULL);
4812 ASSERT_TRUE(response->headers != NULL);
4813 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
4814
4815 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
4816 EXPECT_EQ("hello!", response_data);
4817
4818 HttpNetworkTransaction::SetNextProtos("");
4819 HttpNetworkTransaction::SetUseAlternateProtocols(false);
4820}
4821
4822TEST_F(HttpNetworkTransactionTest,
4823 UseAlternateProtocolForNpnSpdyWithExistingSpdySession) {
4824 HttpNetworkTransaction::SetUseAlternateProtocols(true);
4825 HttpNetworkTransaction::SetNextProtos(
4826 "\x08http/1.1\x07http1.1\x06spdy/1\x04spdy");
4827 SessionDependencies session_deps;
4828
4829 HttpRequestInfo request;
4830 request.method = "GET";
4831 request.url = GURL("http://www.google.com/");
4832 request.load_flags = 0;
4833
4834 MockRead data_reads[] = {
4835 MockRead("HTTP/1.1 200 OK\r\n"),
4836 MockRead("Alternate-Protocol: 443:npn-spdy/1\r\n\r\n"),
4837 MockRead("hello world"),
4838 MockRead(true, OK),
4839 };
4840
4841 StaticSocketDataProvider first_transaction(
4842 data_reads, arraysize(data_reads), NULL, 0);
4843 session_deps.socket_factory.AddSocketDataProvider(&first_transaction);
4844
4845 SSLSocketDataProvider ssl(true, OK);
4846 ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
4847 ssl.next_proto = "spdy/1";
4848 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
4849
4850 MockWrite spdy_writes[] = {
4851 MockWrite(true, reinterpret_cast<const char*>(kGetSyn),
4852 arraysize(kGetSyn)),
4853 };
4854
4855 MockRead spdy_reads[] = {
4856 MockRead(true, reinterpret_cast<const char*>(kGetSynReply),
4857 arraysize(kGetSynReply)),
4858 MockRead(true, reinterpret_cast<const char*>(kGetBodyFrame),
4859 arraysize(kGetBodyFrame)),
4860 MockRead(true, 0, 0),
4861 };
4862
4863 scoped_refptr<DelayedSocketData> spdy_data(
4864 new DelayedSocketData(
4865 1, // wait for one write to finish before reading.
4866 spdy_reads, arraysize(spdy_reads),
4867 spdy_writes, arraysize(spdy_writes)));
4868 session_deps.socket_factory.AddSocketDataProvider(spdy_data);
4869
4870 TestCompletionCallback callback;
4871
4872 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
4873
4874 scoped_ptr<HttpNetworkTransaction> trans(new HttpNetworkTransaction(session));
4875
4876 int rv = trans->Start(&request, &callback, NULL);
4877 EXPECT_EQ(ERR_IO_PENDING, rv);
4878 EXPECT_EQ(OK, callback.WaitForResult());
4879
4880 const HttpResponseInfo* response = trans->GetResponseInfo();
4881 ASSERT_TRUE(response != NULL);
4882 ASSERT_TRUE(response->headers != NULL);
4883 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
4884
4885 std::string response_data;
4886 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
4887 EXPECT_EQ("hello world", response_data);
4888
4889 // Set up an initial SpdySession in the pool to reuse.
4890 scoped_refptr<SpdySession> spdy_session =
4891 session->spdy_session_pool()->Get(HostPortPair("www.google.com", 443),
4892 session);
4893 TCPSocketParams tcp_params("www.google.com", 443, MEDIUM, GURL(), false);
4894 spdy_session->Connect(
4895 "www.google.com:443", tcp_params, MEDIUM, BoundNetLog());
4896
4897 trans.reset(new HttpNetworkTransaction(session));
4898
4899 rv = trans->Start(&request, &callback, NULL);
4900 EXPECT_EQ(ERR_IO_PENDING, rv);
4901 EXPECT_EQ(OK, callback.WaitForResult());
4902
4903 response = trans->GetResponseInfo();
4904 ASSERT_TRUE(response != NULL);
4905 ASSERT_TRUE(response->headers != NULL);
4906 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
4907
4908 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
4909 EXPECT_EQ("hello!", response_data);
4910
4911 HttpNetworkTransaction::SetNextProtos("");
[email protected]31e2c69e2010-04-15 18:06:064912 HttpNetworkTransaction::SetUseAlternateProtocols(false);
[email protected]564b4912010-03-09 16:30:424913}
4914
[email protected]e5ae96a2010-04-14 20:12:454915// MockAuthHandlerCanonical is used by the ResolveCanonicalName
4916// HttpNetworkTransaction unit test below. Callers set up expectations for
4917// whether the canonical name needs to be resolved.
4918class MockAuthHandlerCanonical : public HttpAuthHandler {
4919 public:
4920 enum Resolve {
4921 RESOLVE_INIT,
4922 RESOLVE_SKIP,
4923 RESOLVE_SYNC,
4924 RESOLVE_ASYNC,
4925 RESOLVE_TESTED,
4926 };
4927
4928 MockAuthHandlerCanonical() : resolve_(RESOLVE_INIT), user_callback_(NULL) {}
4929 virtual ~MockAuthHandlerCanonical() {}
4930
4931 void SetResolveExpectation(Resolve resolve) {
4932 EXPECT_EQ(RESOLVE_INIT, resolve_);
4933 resolve_ = resolve;
4934 }
4935
4936 void ResetResolveExpectation() {
4937 EXPECT_EQ(RESOLVE_TESTED, resolve_);
4938 resolve_ = RESOLVE_INIT;
4939 }
4940
4941 virtual bool NeedsCanonicalName() {
4942 switch (resolve_) {
4943 case RESOLVE_SYNC:
4944 case RESOLVE_ASYNC:
4945 return true;
4946 case RESOLVE_SKIP:
4947 resolve_ = RESOLVE_TESTED;
4948 return false;
4949 default:
4950 NOTREACHED();
4951 return false;
4952 }
4953 }
4954
4955 virtual int ResolveCanonicalName(HostResolver* host_resolver,
4956 CompletionCallback* callback,
4957 const BoundNetLog& net_log) {
4958 EXPECT_NE(RESOLVE_TESTED, resolve_);
4959 int rv = OK;
4960 switch (resolve_) {
4961 case RESOLVE_SYNC:
4962 resolve_ = RESOLVE_TESTED;
4963 break;
4964 case RESOLVE_ASYNC:
4965 EXPECT_TRUE(user_callback_ == NULL);
4966 rv = ERR_IO_PENDING;
4967 user_callback_ = callback;
4968 MessageLoop::current()->PostTask(
4969 FROM_HERE,
4970 NewRunnableMethod(
4971 this, &MockAuthHandlerCanonical::OnResolveCanonicalName));
4972 break;
4973 default:
4974 NOTREACHED();
4975 break;
4976 }
4977 return rv;
4978 }
4979
4980 void OnResolveCanonicalName() {
4981 EXPECT_EQ(RESOLVE_ASYNC, resolve_);
4982 EXPECT_TRUE(user_callback_ != NULL);
4983 resolve_ = RESOLVE_TESTED;
4984 CompletionCallback* callback = user_callback_;
4985 user_callback_ = NULL;
4986 callback->Run(OK);
4987 }
4988
4989 virtual bool Init(HttpAuth::ChallengeTokenizer* challenge) {
4990 scheme_ = "mock";
4991 score_ = 1;
4992 properties_ = 0;
4993 return true;
4994 }
4995
4996 virtual int GenerateAuthToken(const std::wstring& username,
4997 const std::wstring& password,
4998 const HttpRequestInfo* request,
4999 const ProxyInfo* proxy,
5000 std::string* auth_token) {
5001 auth_token->assign("Mock AUTH myserver.example.com");
5002 return OK;
5003 }
5004
5005 virtual int GenerateDefaultAuthToken(const HttpRequestInfo* request,
5006 const ProxyInfo* proxy,
5007 std::string* auth_token) {
5008 auth_token->assign("Mock DEFAULT_AUTH myserver.example.com");
5009 return OK;
5010 }
5011
5012 // The Factory class simply returns the same handler each time
5013 // CreateAuthHandler is called.
5014 class Factory : public HttpAuthHandlerFactory {
5015 public:
5016 Factory() {}
5017 virtual ~Factory() {}
5018
5019 void set_mock_handler(MockAuthHandlerCanonical* mock_handler) {
5020 mock_handler_ = mock_handler;
5021 }
5022 MockAuthHandlerCanonical* mock_handler() const {
5023 return mock_handler_.get();
5024 }
5025
5026 virtual int CreateAuthHandler(HttpAuth::ChallengeTokenizer* challenge,
5027 HttpAuth::Target target,
5028 const GURL& origin,
5029 scoped_refptr<HttpAuthHandler>* handler) {
5030 *handler = mock_handler_;
5031 return OK;
5032 }
5033
5034 private:
5035 scoped_refptr<MockAuthHandlerCanonical> mock_handler_;
5036 };
5037
5038 private:
5039 Resolve resolve_;
5040 CompletionCallback* user_callback_;
5041};
5042
5043// Tests that ResolveCanonicalName is handled correctly by the
5044// HttpNetworkTransaction.
5045TEST_F(HttpNetworkTransactionTest, ResolveCanonicalName) {
5046 SessionDependencies session_deps;
5047 scoped_refptr<MockAuthHandlerCanonical> auth_handler(
5048 new MockAuthHandlerCanonical());
5049 auth_handler->Init(NULL);
5050 MockAuthHandlerCanonical::Factory* auth_factory(
5051 new MockAuthHandlerCanonical::Factory());
5052 auth_factory->set_mock_handler(auth_handler);
5053 session_deps.http_auth_handler_factory.reset(auth_factory);
5054
5055 for (int i = 0; i < 2; ++i) {
5056 scoped_ptr<HttpTransaction> trans(
5057 new HttpNetworkTransaction(CreateSession(&session_deps)));
5058
5059 // Set up expectations for this pass of the test. Many of the EXPECT calls
5060 // are contained inside the MockAuthHandlerCanonical codebase in response to
5061 // the expectations.
5062 MockAuthHandlerCanonical::Resolve resolve = (i == 0) ?
5063 MockAuthHandlerCanonical::RESOLVE_SYNC :
5064 MockAuthHandlerCanonical::RESOLVE_ASYNC;
5065 auth_handler->SetResolveExpectation(resolve);
5066 HttpRequestInfo request;
5067 request.method = "GET";
5068 request.url = GURL("http://myserver/");
5069 request.load_flags = 0;
5070
5071 MockWrite data_writes1[] = {
5072 MockWrite("GET / HTTP/1.1\r\n"
5073 "Host: myserver\r\n"
5074 "Connection: keep-alive\r\n\r\n"),
5075 };
5076
5077 MockRead data_reads1[] = {
5078 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
5079 MockRead("WWW-Authenticate: Mock myserver.example.com\r\n"),
5080 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
5081 MockRead("Content-Length: 14\r\n\r\n"),
5082 MockRead("Unauthorized\r\n"),
5083 };
5084
5085 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
5086 data_writes1, arraysize(data_writes1));
5087 session_deps.socket_factory.AddSocketDataProvider(&data1);
5088
5089 TestCompletionCallback callback1;
5090
5091 int rv = trans->Start(&request, &callback1, NULL);
5092 EXPECT_EQ(ERR_IO_PENDING, rv);
5093
5094 rv = callback1.WaitForResult();
5095 EXPECT_EQ(OK, rv);
5096
5097 const HttpResponseInfo* response = trans->GetResponseInfo();
5098 EXPECT_FALSE(response == NULL);
5099
5100 // The password prompt is set after the canonical name is resolved.
5101 // If it isn't present or is incorrect, it indicates that the scheme
5102 // did not complete correctly.
5103 EXPECT_FALSE(response->auth_challenge.get() == NULL);
5104
5105 EXPECT_EQ(L"myserver:80", response->auth_challenge->host_and_port);
5106 EXPECT_EQ(L"", response->auth_challenge->realm);
5107 EXPECT_EQ(L"mock", response->auth_challenge->scheme);
5108 auth_handler->ResetResolveExpectation();
5109 }
5110}
5111
[email protected]aeaca1f2010-04-20 22:05:215112class TLSDecompressionFailureSocketDataProvider : public SocketDataProvider {
5113 public:
5114 TLSDecompressionFailureSocketDataProvider(bool fail_all)
5115 : fail_all_(fail_all) {
5116 }
5117
5118 virtual MockRead GetNextRead() {
5119 if (fail_all_)
5120 return MockRead(false /* async */, ERR_SSL_DECOMPRESSION_FAILURE_ALERT);
5121
5122 return MockRead(false /* async */,
5123 "HTTP/1.1 200 OK\r\nContent-Length: 3\r\n\r\nok.\r\n");
5124 }
5125
5126 virtual MockWriteResult OnWrite(const std::string& data) {
5127 return MockWriteResult(false /* async */, data.size());
5128 }
5129
5130 void Reset() {
5131 }
5132
5133 private:
5134 const bool fail_all_;
5135};
5136
5137// Test that we restart a connection when we see a decompression failure from
5138// the peer during the handshake. (In the real world we'll restart with SSLv3
5139// and we won't offer DEFLATE in that case.)
5140TEST_F(HttpNetworkTransactionTest, RestartAfterTLSDecompressionFailure) {
5141 HttpRequestInfo request;
5142 request.method = "GET";
5143 request.url = GURL("https://tlsdecompressionfailure.example.com/");
5144 request.load_flags = 0;
5145
5146 SessionDependencies session_deps;
5147 TLSDecompressionFailureSocketDataProvider socket_data_provider1(
5148 false /* fail all reads */);
5149 TLSDecompressionFailureSocketDataProvider socket_data_provider2(false);
5150 SSLSocketDataProvider ssl_socket_data_provider1(
5151 false, ERR_SSL_DECOMPRESSION_FAILURE_ALERT);
5152 SSLSocketDataProvider ssl_socket_data_provider2(false, OK);
5153 session_deps.socket_factory.AddSocketDataProvider(&socket_data_provider1);
5154 session_deps.socket_factory.AddSocketDataProvider(&socket_data_provider2);
5155 session_deps.socket_factory.AddSSLSocketDataProvider(
5156 &ssl_socket_data_provider1);
5157 session_deps.socket_factory.AddSSLSocketDataProvider(
5158 &ssl_socket_data_provider2);
5159
5160 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
5161 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
5162 TestCompletionCallback callback;
5163
5164 int rv = trans->Start(&request, &callback, NULL);
5165 EXPECT_EQ(ERR_IO_PENDING, rv);
5166 EXPECT_EQ(OK, callback.WaitForResult());
5167
5168 const HttpResponseInfo* response = trans->GetResponseInfo();
5169 ASSERT_TRUE(response != NULL);
5170 ASSERT_TRUE(response->headers != NULL);
5171 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
5172
5173 std::string response_data;
5174 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
5175 EXPECT_EQ("ok.", response_data);
5176}
5177
5178// Test that we restart a connection if we get a decompression failure from the
5179// peer while reading the first bytes from the connection. This occurs when the
5180// peer cannot handle DEFLATE but we're using False Start, so we don't notice
5181// in the handshake.
5182TEST_F(HttpNetworkTransactionTest,
5183 RestartAfterTLSDecompressionFailureWithFalseStart) {
5184 HttpRequestInfo request;
5185 request.method = "GET";
5186 request.url = GURL("https://tlsdecompressionfailure2.example.com/");
5187 request.load_flags = 0;
5188
5189 SessionDependencies session_deps;
5190 TLSDecompressionFailureSocketDataProvider socket_data_provider1(
5191 true /* fail all reads */);
5192 TLSDecompressionFailureSocketDataProvider socket_data_provider2(false);
5193 SSLSocketDataProvider ssl_socket_data_provider1(false, OK);
5194 SSLSocketDataProvider ssl_socket_data_provider2(false, OK);
5195 session_deps.socket_factory.AddSocketDataProvider(&socket_data_provider1);
5196 session_deps.socket_factory.AddSocketDataProvider(&socket_data_provider2);
5197 session_deps.socket_factory.AddSSLSocketDataProvider(
5198 &ssl_socket_data_provider1);
5199 session_deps.socket_factory.AddSSLSocketDataProvider(
5200 &ssl_socket_data_provider2);
5201
5202 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
5203 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
5204 TestCompletionCallback callback;
5205
5206 int rv = trans->Start(&request, &callback, NULL);
5207 EXPECT_EQ(ERR_IO_PENDING, rv);
5208 EXPECT_EQ(OK, callback.WaitForResult());
5209
5210 const HttpResponseInfo* response = trans->GetResponseInfo();
5211 ASSERT_TRUE(response != NULL);
5212 ASSERT_TRUE(response->headers != NULL);
5213 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
5214
5215 std::string response_data;
5216 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
5217 EXPECT_EQ("ok.", response_data);
5218}
5219
[email protected]89ceba9a2009-03-21 03:46:065220} // namespace net