blob: fd66d8dea84804189441c49c5e8ca5d20dd95fc3 [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]2d731a32010-04-29 01:04:065#include "net/http/http_network_transaction.h"
6
[email protected]77848d12008-11-14 00:00:227#include <math.h> // ceil
[email protected]95d88ffe2010-02-04 21:25:338#include <vector>
[email protected]77848d12008-11-14 00:00:229
[email protected]2d731a32010-04-29 01:04:0610#include "base/basictypes.h"
[email protected]68bf9152008-09-25 19:47:3011#include "base/compiler_specific.h"
[email protected]95d88ffe2010-02-04 21:25:3312#include "base/file_path.h"
13#include "base/file_util.h"
[email protected]6624b4622010-03-29 19:58:3614#include "base/scoped_ptr.h"
[email protected]be1ce6a72010-08-03 14:35:2215#include "base/utf_string_conversions.h"
[email protected]277d5942010-08-11 21:02:3516#include "net/base/auth.h"
[email protected]169d0012010-05-10 23:20:1217#include "net/base/capturing_net_log.h"
[email protected]bacff652009-03-31 17:50:3318#include "net/base/completion_callback.h"
[email protected]b59ff372009-07-15 22:04:3219#include "net/base/mock_host_resolver.h"
[email protected]169d0012010-05-10 23:20:1220#include "net/base/net_log.h"
21#include "net/base/net_log_unittest.h"
[email protected]ac790b42009-12-02 04:31:3122#include "net/base/request_priority.h"
[email protected]db36938c2009-08-19 21:48:4223#include "net/base/ssl_config_service_defaults.h"
[email protected]bacff652009-03-31 17:50:3324#include "net/base/ssl_info.h"
initial.commit586acc5fe2008-07-26 22:42:5225#include "net/base/test_completion_callback.h"
26#include "net/base/upload_data.h"
[email protected]3c32c5f2010-05-18 15:18:1227#include "net/http/http_auth_handler_digest.h"
[email protected]3fd9dae2010-06-21 11:39:0028#include "net/http/http_auth_handler_mock.h"
[email protected]385a4672009-03-11 22:21:2929#include "net/http/http_auth_handler_ntlm.h"
[email protected]0877e3d2009-10-17 22:29:5730#include "net/http/http_basic_stream.h"
[email protected]3deb9a52010-11-11 00:24:4031#include "net/http/http_net_log_params.h"
initial.commit586acc5fe2008-07-26 22:42:5232#include "net/http/http_network_session.h"
[email protected]87bfa3f2010-09-30 14:54:5633#include "net/http/http_network_session_peer.h"
[email protected]0877e3d2009-10-17 22:29:5734#include "net/http/http_stream.h"
[email protected]8e6441ca2010-08-19 05:56:3835#include "net/http/http_stream_factory.h"
initial.commit586acc5fe2008-07-26 22:42:5236#include "net/http/http_transaction_unittest.h"
[email protected]51fff29d2008-12-19 22:17:5337#include "net/proxy/proxy_config_service_fixed.h"
[email protected]631f1322010-04-30 17:59:1138#include "net/proxy/proxy_resolver.h"
39#include "net/proxy/proxy_service.h"
[email protected]f7984fc62009-06-22 23:26:4440#include "net/socket/client_socket_factory.h"
41#include "net/socket/socket_test_util.h"
42#include "net/socket/ssl_client_socket.h"
[email protected]2ff8b312010-04-26 22:20:5443#include "net/spdy/spdy_framer.h"
44#include "net/spdy/spdy_session.h"
45#include "net/spdy/spdy_session_pool.h"
46#include "net/spdy/spdy_test_util.h"
initial.commit586acc5fe2008-07-26 22:42:5247#include "testing/gtest/include/gtest/gtest.h"
[email protected]23887f04f2008-12-02 19:20:1548#include "testing/platform_test.h"
initial.commit586acc5fe2008-07-26 22:42:5249
50//-----------------------------------------------------------------------------
51
[email protected]13c8a092010-07-29 06:15:4452namespace {
53
54const string16 kBar(ASCIIToUTF16("bar"));
55const string16 kBar2(ASCIIToUTF16("bar2"));
56const string16 kBar3(ASCIIToUTF16("bar3"));
57const string16 kBaz(ASCIIToUTF16("baz"));
58const string16 kFirst(ASCIIToUTF16("first"));
59const string16 kFoo(ASCIIToUTF16("foo"));
60const string16 kFoo2(ASCIIToUTF16("foo2"));
61const string16 kFoo3(ASCIIToUTF16("foo3"));
62const string16 kFou(ASCIIToUTF16("fou"));
63const string16 kSecond(ASCIIToUTF16("second"));
64const string16 kTestingNTLM(ASCIIToUTF16("testing-ntlm"));
65const string16 kWrongPassword(ASCIIToUTF16("wrongpassword"));
66
67} // namespace
68
[email protected]89ceba9a2009-03-21 03:46:0669namespace net {
70
[email protected]e44de5d2009-06-05 20:12:4571// Helper to manage the lifetimes of the dependencies for a
72// HttpNetworkTransaction.
[email protected]ac039522010-06-15 16:39:4473struct SessionDependencies {
[email protected]228ff742009-06-05 01:19:5974 // Default set of dependencies -- "null" proxy service.
[email protected]db36938c2009-08-19 21:48:4275 SessionDependencies()
76 : host_resolver(new MockHostResolver),
[email protected]ebeefff32010-09-15 05:10:0277 proxy_service(ProxyService::CreateDirect()),
[email protected]d1eda932009-11-04 01:03:1078 ssl_config_service(new SSLConfigServiceDefaults),
[email protected]f660e4b2010-09-29 14:20:0879 http_auth_handler_factory(
[email protected]73c45322010-10-01 23:57:5480 HttpAuthHandlerFactory::CreateDefault(host_resolver.get())),
[email protected]a7ea8832010-07-12 17:54:5481 net_log(NULL) {}
[email protected]228ff742009-06-05 01:19:5982
83 // Custom proxy service dependency.
[email protected]e44de5d2009-06-05 20:12:4584 explicit SessionDependencies(ProxyService* proxy_service)
[email protected]db36938c2009-08-19 21:48:4285 : host_resolver(new MockHostResolver),
86 proxy_service(proxy_service),
[email protected]d1eda932009-11-04 01:03:1087 ssl_config_service(new SSLConfigServiceDefaults),
[email protected]f660e4b2010-09-29 14:20:0888 http_auth_handler_factory(
[email protected]73c45322010-10-01 23:57:5489 HttpAuthHandlerFactory::CreateDefault(host_resolver.get())),
[email protected]a7ea8832010-07-12 17:54:5490 net_log(NULL) {}
[email protected]228ff742009-06-05 01:19:5991
[email protected]73c45322010-10-01 23:57:5492 scoped_ptr<MockHostResolverBase> host_resolver;
[email protected]80d6524d2009-08-18 03:58:0993 scoped_refptr<ProxyService> proxy_service;
[email protected]db36938c2009-08-19 21:48:4294 scoped_refptr<SSLConfigService> ssl_config_service;
[email protected]228ff742009-06-05 01:19:5995 MockClientSocketFactory socket_factory;
[email protected]fa55e192010-02-15 14:25:5096 scoped_ptr<HttpAuthHandlerFactory> http_auth_handler_factory;
[email protected]a7ea8832010-07-12 17:54:5497 NetLog* net_log;
[email protected]228ff742009-06-05 01:19:5998};
99
[email protected]228ff742009-06-05 01:19:59100HttpNetworkSession* CreateSession(SessionDependencies* session_deps) {
[email protected]73c45322010-10-01 23:57:54101 return new HttpNetworkSession(session_deps->host_resolver.get(),
[email protected]2db580532010-10-08 14:32:37102 NULL /* dnsrr_resolver */,
[email protected]7ab5bbd12010-10-19 13:33:21103 NULL /* ssl_host_info_factory */,
[email protected]80d6524d2009-08-18 03:58:09104 session_deps->proxy_service,
[email protected]db36938c2009-08-19 21:48:42105 &session_deps->socket_factory,
[email protected]d1eda932009-11-04 01:03:10106 session_deps->ssl_config_service,
[email protected]87bfa3f2010-09-30 14:54:56107 new SpdySessionPool(NULL),
[email protected]06650c52010-06-03 00:49:17108 session_deps->http_auth_handler_factory.get(),
[email protected]ac039522010-06-15 16:39:44109 NULL,
[email protected]a7ea8832010-07-12 17:54:54110 session_deps->net_log);
[email protected]e8d536192008-10-17 22:21:14111}
112
[email protected]89836e22008-09-25 20:33:42113class HttpNetworkTransactionTest : public PlatformTest {
initial.commit586acc5fe2008-07-26 22:42:52114 public:
[email protected]2ff8b312010-04-26 22:20:54115 virtual void SetUp() {
[email protected]0b0bf032010-09-21 18:08:50116 NetworkChangeNotifier::NotifyObserversOfIPAddressChangeForTests();
117 MessageLoop::current()->RunAllPending();
[email protected]2ff8b312010-04-26 22:20:54118 spdy::SpdyFramer::set_enable_compression_default(false);
119 }
120
[email protected]0e75a732008-10-16 20:36:09121 virtual void TearDown() {
[email protected]0b0bf032010-09-21 18:08:50122 NetworkChangeNotifier::NotifyObserversOfIPAddressChangeForTests();
123 MessageLoop::current()->RunAllPending();
[email protected]2ff8b312010-04-26 22:20:54124 spdy::SpdyFramer::set_enable_compression_default(true);
[email protected]0e75a732008-10-16 20:36:09125 // Empty the current queue.
126 MessageLoop::current()->RunAllPending();
127 PlatformTest::TearDown();
[email protected]0b0bf032010-09-21 18:08:50128 NetworkChangeNotifier::NotifyObserversOfIPAddressChangeForTests();
129 MessageLoop::current()->RunAllPending();
[email protected]0e75a732008-10-16 20:36:09130 }
131
[email protected]3d2a59b2008-09-26 19:44:25132 protected:
133 void KeepAliveConnectionResendRequestTest(const MockRead& read_failure);
initial.commit586acc5fe2008-07-26 22:42:52134
[email protected]ff007e162009-05-23 09:13:15135 struct SimpleGetHelperResult {
136 int rv;
137 std::string status_line;
138 std::string response_data;
139 };
initial.commit586acc5fe2008-07-26 22:42:52140
[email protected]31a2bfe2010-02-09 08:03:39141 SimpleGetHelperResult SimpleGetHelper(MockRead data_reads[],
142 size_t reads_count) {
[email protected]ff007e162009-05-23 09:13:15143 SimpleGetHelperResult out;
initial.commit586acc5fe2008-07-26 22:42:52144
[email protected]228ff742009-06-05 01:19:59145 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:40146 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:43147 new HttpNetworkTransaction(CreateSession(&session_deps)));
initial.commit586acc5fe2008-07-26 22:42:52148
[email protected]ff007e162009-05-23 09:13:15149 HttpRequestInfo request;
150 request.method = "GET";
151 request.url = GURL("http://www.google.com/");
152 request.load_flags = 0;
initial.commit586acc5fe2008-07-26 22:42:52153
[email protected]31a2bfe2010-02-09 08:03:39154 StaticSocketDataProvider data(data_reads, reads_count, NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:59155 session_deps.socket_factory.AddSocketDataProvider(&data);
initial.commit586acc5fe2008-07-26 22:42:52156
[email protected]ff007e162009-05-23 09:13:15157 TestCompletionCallback callback;
initial.commit586acc5fe2008-07-26 22:42:52158
[email protected]169d0012010-05-10 23:20:12159 CapturingBoundNetLog log(CapturingNetLog::kUnbounded);
[email protected]3deb9a52010-11-11 00:24:40160 EXPECT_TRUE(log.bound().IsLoggingAllEvents());
[email protected]169d0012010-05-10 23:20:12161 int rv = trans->Start(&request, &callback, log.bound());
[email protected]ff007e162009-05-23 09:13:15162 EXPECT_EQ(ERR_IO_PENDING, rv);
initial.commit586acc5fe2008-07-26 22:42:52163
[email protected]ff007e162009-05-23 09:13:15164 out.rv = callback.WaitForResult();
165 if (out.rv != OK)
166 return out;
167
168 const HttpResponseInfo* response = trans->GetResponseInfo();
169 EXPECT_TRUE(response != NULL);
170
171 EXPECT_TRUE(response->headers != NULL);
172 out.status_line = response->headers->GetStatusLine();
173
174 rv = ReadTransaction(trans.get(), &out.response_data);
175 EXPECT_EQ(OK, rv);
[email protected]dbb83db2010-05-11 18:13:39176 size_t pos = ExpectLogContainsSomewhere(
[email protected]169d0012010-05-10 23:20:12177 log.entries(), 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_REQUEST_HEADERS,
178 NetLog::PHASE_NONE);
[email protected]dbb83db2010-05-11 18:13:39179 ExpectLogContainsSomewhere(
180 log.entries(), pos,
181 NetLog::TYPE_HTTP_TRANSACTION_READ_RESPONSE_HEADERS,
182 NetLog::PHASE_NONE);
[email protected]ff007e162009-05-23 09:13:15183
[email protected]3deb9a52010-11-11 00:24:40184 CapturingNetLog::Entry entry = log.entries()[pos];
185 NetLogHttpRequestParameter* request_params =
186 static_cast<NetLogHttpRequestParameter*>(entry.extra_parameters.get());
187 EXPECT_EQ("GET / HTTP/1.1\r\n", request_params->GetLine());
188 EXPECT_EQ("Host: www.google.com\r\n"
189 "Connection: keep-alive\r\n\r\n",
190 request_params->GetHeaders().ToString());
191
[email protected]aecfbf22008-10-16 02:02:47192 return out;
[email protected]ff007e162009-05-23 09:13:15193 }
initial.commit586acc5fe2008-07-26 22:42:52194
[email protected]ff007e162009-05-23 09:13:15195 void ConnectStatusHelperWithExpectedStatus(const MockRead& status,
196 int expected_status);
initial.commit586acc5fe2008-07-26 22:42:52197
[email protected]ff007e162009-05-23 09:13:15198 void ConnectStatusHelper(const MockRead& status);
[email protected]ff007e162009-05-23 09:13:15199};
[email protected]231d5a32008-09-13 00:45:27200
[email protected]15a5ccf82008-10-23 19:57:43201// Fill |str| with a long header list that consumes >= |size| bytes.
202void FillLargeHeadersString(std::string* str, int size) {
[email protected]4ddaf2502008-10-23 18:26:19203 const char* row =
204 "SomeHeaderName: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\r\n";
205 const int sizeof_row = strlen(row);
206 const int num_rows = static_cast<int>(
207 ceil(static_cast<float>(size) / sizeof_row));
208 const int sizeof_data = num_rows * sizeof_row;
209 DCHECK(sizeof_data >= size);
[email protected]15a5ccf82008-10-23 19:57:43210 str->reserve(sizeof_data);
[email protected]372d34a2008-11-05 21:30:51211
[email protected]4ddaf2502008-10-23 18:26:19212 for (int i = 0; i < num_rows; ++i)
[email protected]15a5ccf82008-10-23 19:57:43213 str->append(row, sizeof_row);
[email protected]4ddaf2502008-10-23 18:26:19214}
215
[email protected]385a4672009-03-11 22:21:29216// Alternative functions that eliminate randomness and dependency on the local
217// host name so that the generated NTLM messages are reproducible.
[email protected]fe2bc6a2009-03-23 16:52:20218void MockGenerateRandom1(uint8* output, size_t n) {
[email protected]385a4672009-03-11 22:21:29219 static const uint8 bytes[] = {
220 0x55, 0x29, 0x66, 0x26, 0x6b, 0x9c, 0x73, 0x54
221 };
222 static size_t current_byte = 0;
223 for (size_t i = 0; i < n; ++i) {
224 output[i] = bytes[current_byte++];
225 current_byte %= arraysize(bytes);
226 }
227}
228
[email protected]fe2bc6a2009-03-23 16:52:20229void MockGenerateRandom2(uint8* output, size_t n) {
[email protected]385a4672009-03-11 22:21:29230 static const uint8 bytes[] = {
231 0x96, 0x79, 0x85, 0xe7, 0x49, 0x93, 0x70, 0xa1,
232 0x4e, 0xe7, 0x87, 0x45, 0x31, 0x5b, 0xd3, 0x1f
233 };
234 static size_t current_byte = 0;
235 for (size_t i = 0; i < n; ++i) {
236 output[i] = bytes[current_byte++];
237 current_byte %= arraysize(bytes);
238 }
239}
240
[email protected]fe2bc6a2009-03-23 16:52:20241std::string MockGetHostName() {
242 return "WTC-WIN7";
[email protected]385a4672009-03-11 22:21:29243}
244
[email protected]e60e47a2010-07-14 03:37:18245template<typename ParentPool>
246class CaptureGroupNameSocketPool : public ParentPool {
[email protected]04e5be32009-06-26 20:00:31247 public:
[email protected]e60e47a2010-07-14 03:37:18248 explicit CaptureGroupNameSocketPool(HttpNetworkSession* session);
249
[email protected]d80a4322009-08-14 07:07:49250 const std::string last_group_name_received() const {
251 return last_group_name_;
252 }
253
[email protected]684970b2009-08-14 04:54:46254 virtual int RequestSocket(const std::string& group_name,
[email protected]d80a4322009-08-14 07:07:49255 const void* socket_params,
[email protected]ac790b42009-12-02 04:31:31256 RequestPriority priority,
[email protected]04e5be32009-06-26 20:00:31257 ClientSocketHandle* handle,
[email protected]684970b2009-08-14 04:54:46258 CompletionCallback* callback,
[email protected]9e743cd2010-03-16 07:03:53259 const BoundNetLog& net_log) {
[email protected]04e5be32009-06-26 20:00:31260 last_group_name_ = group_name;
261 return ERR_IO_PENDING;
262 }
[email protected]04e5be32009-06-26 20:00:31263 virtual void CancelRequest(const std::string& group_name,
[email protected]05ea9ff2010-07-15 19:08:21264 ClientSocketHandle* handle) {}
[email protected]04e5be32009-06-26 20:00:31265 virtual void ReleaseSocket(const std::string& group_name,
266 ClientSocket* socket) {}
267 virtual void CloseIdleSockets() {}
[email protected]04e5be32009-06-26 20:00:31268 virtual int IdleSocketCount() const {
269 return 0;
270 }
271 virtual int IdleSocketCountInGroup(const std::string& group_name) const {
272 return 0;
273 }
274 virtual LoadState GetLoadState(const std::string& group_name,
275 const ClientSocketHandle* handle) const {
276 return LOAD_STATE_IDLE;
277 }
[email protected]a796bcec2010-03-22 17:17:26278 virtual base::TimeDelta ConnectionTimeout() const {
279 return base::TimeDelta();
280 }
[email protected]d80a4322009-08-14 07:07:49281
282 private:
[email protected]04e5be32009-06-26 20:00:31283 std::string last_group_name_;
284};
285
[email protected]2d731a32010-04-29 01:04:06286typedef CaptureGroupNameSocketPool<TCPClientSocketPool>
[email protected]2227c692010-05-04 15:36:11287CaptureGroupNameTCPSocketPool;
[email protected]e772db3f2010-07-12 18:11:13288typedef CaptureGroupNameSocketPool<HttpProxyClientSocketPool>
289CaptureGroupNameHttpProxySocketPool;
[email protected]2d731a32010-04-29 01:04:06290typedef CaptureGroupNameSocketPool<SOCKSClientSocketPool>
[email protected]2227c692010-05-04 15:36:11291CaptureGroupNameSOCKSSocketPool;
[email protected]e60e47a2010-07-14 03:37:18292typedef CaptureGroupNameSocketPool<SSLClientSocketPool>
293CaptureGroupNameSSLSocketPool;
294
295template<typename ParentPool>
296CaptureGroupNameSocketPool<ParentPool>::CaptureGroupNameSocketPool(
297 HttpNetworkSession* session)
298 : ParentPool(0, 0, NULL, session->host_resolver(), NULL, NULL) {}
299
300template<>
[email protected]2df19bb2010-08-25 20:13:46301CaptureGroupNameHttpProxySocketPool::CaptureGroupNameSocketPool(
302 HttpNetworkSession* session)
303 : HttpProxyClientSocketPool(0, 0, NULL, session->host_resolver(), NULL,
304 NULL, NULL) {}
305
306template<>
[email protected]e60e47a2010-07-14 03:37:18307CaptureGroupNameSSLSocketPool::CaptureGroupNameSocketPool(
308 HttpNetworkSession* session)
309 : SSLClientSocketPool(0, 0, NULL, session->host_resolver(), NULL, NULL,
[email protected]7ab5bbd12010-10-19 13:33:21310 NULL, NULL, NULL, NULL, NULL, NULL) {}
[email protected]2227c692010-05-04 15:36:11311
[email protected]231d5a32008-09-13 00:45:27312//-----------------------------------------------------------------------------
313
[email protected]dae22c52010-07-30 02:16:35314// This is the expected list of advertised protocols from the browser's NPN
315// list.
316static const char kExpectedNPNString[] = "\x08http/1.1\x06spdy/2";
317
318// This is the expected return from a current server advertising SPDY.
319static const char kAlternateProtocolHttpHeader[] =
320 "Alternate-Protocol: 443:npn-spdy/2\r\n\r\n";
321
[email protected]231d5a32008-09-13 00:45:27322TEST_F(HttpNetworkTransactionTest, Basic) {
[email protected]228ff742009-06-05 01:19:59323 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:40324 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:43325 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]231d5a32008-09-13 00:45:27326}
327
328TEST_F(HttpNetworkTransactionTest, SimpleGET) {
329 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35330 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
331 MockRead("hello world"),
[email protected]1c773ea12009-04-28 19:58:42332 MockRead(false, OK),
[email protected]231d5a32008-09-13 00:45:27333 };
[email protected]31a2bfe2010-02-09 08:03:39334 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
335 arraysize(data_reads));
[email protected]1c773ea12009-04-28 19:58:42336 EXPECT_EQ(OK, out.rv);
[email protected]231d5a32008-09-13 00:45:27337 EXPECT_EQ("HTTP/1.0 200 OK", out.status_line);
338 EXPECT_EQ("hello world", out.response_data);
339}
340
341// Response with no status line.
342TEST_F(HttpNetworkTransactionTest, SimpleGETNoHeaders) {
343 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35344 MockRead("hello world"),
[email protected]1c773ea12009-04-28 19:58:42345 MockRead(false, OK),
[email protected]231d5a32008-09-13 00:45:27346 };
[email protected]31a2bfe2010-02-09 08:03:39347 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
348 arraysize(data_reads));
[email protected]1c773ea12009-04-28 19:58:42349 EXPECT_EQ(OK, out.rv);
[email protected]231d5a32008-09-13 00:45:27350 EXPECT_EQ("HTTP/0.9 200 OK", out.status_line);
351 EXPECT_EQ("hello world", out.response_data);
352}
353
354// Allow up to 4 bytes of junk to precede status line.
355TEST_F(HttpNetworkTransactionTest, StatusLineJunk2Bytes) {
356 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35357 MockRead("xxxHTTP/1.0 404 Not Found\nServer: blah\n\nDATA"),
[email protected]1c773ea12009-04-28 19:58:42358 MockRead(false, OK),
[email protected]231d5a32008-09-13 00:45:27359 };
[email protected]31a2bfe2010-02-09 08:03:39360 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
361 arraysize(data_reads));
[email protected]1c773ea12009-04-28 19:58:42362 EXPECT_EQ(OK, out.rv);
[email protected]231d5a32008-09-13 00:45:27363 EXPECT_EQ("HTTP/1.0 404 Not Found", out.status_line);
364 EXPECT_EQ("DATA", out.response_data);
365}
366
367// Allow up to 4 bytes of junk to precede status line.
368TEST_F(HttpNetworkTransactionTest, StatusLineJunk4Bytes) {
369 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35370 MockRead("\n\nQJHTTP/1.0 404 Not Found\nServer: blah\n\nDATA"),
[email protected]1c773ea12009-04-28 19:58:42371 MockRead(false, OK),
[email protected]231d5a32008-09-13 00:45:27372 };
[email protected]31a2bfe2010-02-09 08:03:39373 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
374 arraysize(data_reads));
[email protected]1c773ea12009-04-28 19:58:42375 EXPECT_EQ(OK, out.rv);
[email protected]231d5a32008-09-13 00:45:27376 EXPECT_EQ("HTTP/1.0 404 Not Found", out.status_line);
377 EXPECT_EQ("DATA", out.response_data);
378}
379
380// Beyond 4 bytes of slop and it should fail to find a status line.
381TEST_F(HttpNetworkTransactionTest, StatusLineJunk5Bytes) {
382 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35383 MockRead("xxxxxHTTP/1.1 404 Not Found\nServer: blah"),
[email protected]1c773ea12009-04-28 19:58:42384 MockRead(false, OK),
[email protected]231d5a32008-09-13 00:45:27385 };
[email protected]31a2bfe2010-02-09 08:03:39386 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
387 arraysize(data_reads));
[email protected]1c773ea12009-04-28 19:58:42388 EXPECT_EQ(OK, out.rv);
[email protected]3d2a59b2008-09-26 19:44:25389 EXPECT_EQ("HTTP/0.9 200 OK", out.status_line);
390 EXPECT_EQ("xxxxxHTTP/1.1 404 Not Found\nServer: blah", out.response_data);
[email protected]231d5a32008-09-13 00:45:27391}
392
393// Same as StatusLineJunk4Bytes, except the read chunks are smaller.
394TEST_F(HttpNetworkTransactionTest, StatusLineJunk4Bytes_Slow) {
395 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35396 MockRead("\n"),
397 MockRead("\n"),
398 MockRead("Q"),
399 MockRead("J"),
400 MockRead("HTTP/1.0 404 Not Found\nServer: blah\n\nDATA"),
[email protected]1c773ea12009-04-28 19:58:42401 MockRead(false, OK),
[email protected]231d5a32008-09-13 00:45:27402 };
[email protected]31a2bfe2010-02-09 08:03:39403 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
404 arraysize(data_reads));
[email protected]1c773ea12009-04-28 19:58:42405 EXPECT_EQ(OK, out.rv);
[email protected]231d5a32008-09-13 00:45:27406 EXPECT_EQ("HTTP/1.0 404 Not Found", out.status_line);
407 EXPECT_EQ("DATA", out.response_data);
408}
409
410// Close the connection before enough bytes to have a status line.
411TEST_F(HttpNetworkTransactionTest, StatusLinePartial) {
412 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35413 MockRead("HTT"),
[email protected]1c773ea12009-04-28 19:58:42414 MockRead(false, OK),
[email protected]231d5a32008-09-13 00:45:27415 };
[email protected]31a2bfe2010-02-09 08:03:39416 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
417 arraysize(data_reads));
[email protected]1c773ea12009-04-28 19:58:42418 EXPECT_EQ(OK, out.rv);
[email protected]231d5a32008-09-13 00:45:27419 EXPECT_EQ("HTTP/0.9 200 OK", out.status_line);
420 EXPECT_EQ("HTT", out.response_data);
initial.commit586acc5fe2008-07-26 22:42:52421}
422
[email protected]f9d44aa2008-09-23 23:57:17423// Simulate a 204 response, lacking a Content-Length header, sent over a
424// persistent connection. The response should still terminate since a 204
425// cannot have a response body.
426TEST_F(HttpNetworkTransactionTest, StopsReading204) {
427 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35428 MockRead("HTTP/1.1 204 No Content\r\n\r\n"),
429 MockRead("junk"), // Should not be read!!
[email protected]1c773ea12009-04-28 19:58:42430 MockRead(false, OK),
[email protected]f9d44aa2008-09-23 23:57:17431 };
[email protected]31a2bfe2010-02-09 08:03:39432 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
433 arraysize(data_reads));
[email protected]1c773ea12009-04-28 19:58:42434 EXPECT_EQ(OK, out.rv);
[email protected]f9d44aa2008-09-23 23:57:17435 EXPECT_EQ("HTTP/1.1 204 No Content", out.status_line);
436 EXPECT_EQ("", out.response_data);
437}
438
[email protected]0877e3d2009-10-17 22:29:57439// A simple request using chunked encoding with some extra data after.
440// (Like might be seen in a pipelined response.)
441TEST_F(HttpNetworkTransactionTest, ChunkedEncoding) {
442 MockRead data_reads[] = {
443 MockRead("HTTP/1.1 200 OK\r\nTransfer-Encoding: chunked\r\n\r\n"),
444 MockRead("5\r\nHello\r\n"),
445 MockRead("1\r\n"),
446 MockRead(" \r\n"),
447 MockRead("5\r\nworld\r\n"),
448 MockRead("0\r\n\r\nHTTP/1.1 200 OK\r\n"),
449 MockRead(false, OK),
450 };
[email protected]31a2bfe2010-02-09 08:03:39451 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
452 arraysize(data_reads));
[email protected]0877e3d2009-10-17 22:29:57453 EXPECT_EQ(OK, out.rv);
454 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
455 EXPECT_EQ("Hello world", out.response_data);
456}
457
[email protected]9fe44f52010-09-23 18:36:00458// Next tests deal with http://crbug.com/56344.
459
460TEST_F(HttpNetworkTransactionTest,
461 MultipleContentLengthHeadersNoTransferEncoding) {
462 MockRead data_reads[] = {
463 MockRead("HTTP/1.1 200 OK\r\n"),
464 MockRead("Content-Length: 10\r\n"),
465 MockRead("Content-Length: 5\r\n\r\n"),
466 };
467 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
468 arraysize(data_reads));
469 EXPECT_EQ(ERR_RESPONSE_HEADERS_MULTIPLE_CONTENT_LENGTH, out.rv);
470}
471
472TEST_F(HttpNetworkTransactionTest,
[email protected]44b52042010-10-29 22:48:04473 DuplicateContentLengthHeadersNoTransferEncoding) {
474 MockRead data_reads[] = {
475 MockRead("HTTP/1.1 200 OK\r\n"),
476 MockRead("Content-Length: 5\r\n"),
477 MockRead("Content-Length: 5\r\n\r\n"),
478 MockRead("Hello"),
479 };
480 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
481 arraysize(data_reads));
482 EXPECT_EQ(OK, out.rv);
483 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
484 EXPECT_EQ("Hello", out.response_data);
485}
486
487TEST_F(HttpNetworkTransactionTest,
488 ComplexContentLengthHeadersNoTransferEncoding) {
489 // More than 2 dupes.
490 {
491 MockRead data_reads[] = {
492 MockRead("HTTP/1.1 200 OK\r\n"),
493 MockRead("Content-Length: 5\r\n"),
494 MockRead("Content-Length: 5\r\n"),
495 MockRead("Content-Length: 5\r\n\r\n"),
496 MockRead("Hello"),
497 };
498 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
499 arraysize(data_reads));
500 EXPECT_EQ(OK, out.rv);
501 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
502 EXPECT_EQ("Hello", out.response_data);
503 }
504 // HTTP/1.0
505 {
506 MockRead data_reads[] = {
507 MockRead("HTTP/1.0 200 OK\r\n"),
508 MockRead("Content-Length: 5\r\n"),
509 MockRead("Content-Length: 5\r\n"),
510 MockRead("Content-Length: 5\r\n\r\n"),
511 MockRead("Hello"),
512 };
513 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
514 arraysize(data_reads));
515 EXPECT_EQ(OK, out.rv);
516 EXPECT_EQ("HTTP/1.0 200 OK", out.status_line);
517 EXPECT_EQ("Hello", out.response_data);
518 }
519 // 2 dupes and one mismatched.
520 {
521 MockRead data_reads[] = {
522 MockRead("HTTP/1.1 200 OK\r\n"),
523 MockRead("Content-Length: 10\r\n"),
524 MockRead("Content-Length: 10\r\n"),
525 MockRead("Content-Length: 5\r\n\r\n"),
526 };
527 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
528 arraysize(data_reads));
529 EXPECT_EQ(ERR_RESPONSE_HEADERS_MULTIPLE_CONTENT_LENGTH, out.rv);
530 }
531}
532
533TEST_F(HttpNetworkTransactionTest,
[email protected]9fe44f52010-09-23 18:36:00534 MultipleContentLengthHeadersTransferEncoding) {
535 MockRead data_reads[] = {
536 MockRead("HTTP/1.1 200 OK\r\n"),
537 MockRead("Content-Length: 666\r\n"),
538 MockRead("Content-Length: 1337\r\n"),
539 MockRead("Transfer-Encoding: chunked\r\n\r\n"),
540 MockRead("5\r\nHello\r\n"),
541 MockRead("1\r\n"),
542 MockRead(" \r\n"),
543 MockRead("5\r\nworld\r\n"),
544 MockRead("0\r\n\r\nHTTP/1.1 200 OK\r\n"),
545 MockRead(false, OK),
546 };
547 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
548 arraysize(data_reads));
549 EXPECT_EQ(OK, out.rv);
550 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
551 EXPECT_EQ("Hello world", out.response_data);
552}
553
[email protected]ef0faf2e72009-03-05 23:27:23554// Do a request using the HEAD method. Verify that we don't try to read the
555// message body (since HEAD has none).
556TEST_F(HttpNetworkTransactionTest, Head) {
[email protected]228ff742009-06-05 01:19:59557 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:40558 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:43559 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]ef0faf2e72009-03-05 23:27:23560
[email protected]1c773ea12009-04-28 19:58:42561 HttpRequestInfo request;
[email protected]ef0faf2e72009-03-05 23:27:23562 request.method = "HEAD";
563 request.url = GURL("http://www.google.com/");
564 request.load_flags = 0;
565
566 MockWrite data_writes1[] = {
567 MockWrite("HEAD / HTTP/1.1\r\n"
568 "Host: www.google.com\r\n"
569 "Connection: keep-alive\r\n"
570 "Content-Length: 0\r\n\r\n"),
571 };
572 MockRead data_reads1[] = {
573 MockRead("HTTP/1.1 404 Not Found\r\n"),
574 MockRead("Server: Blah\r\n"),
575 MockRead("Content-Length: 1234\r\n\r\n"),
576
577 // No response body because the test stops reading here.
[email protected]1c773ea12009-04-28 19:58:42578 MockRead(false, ERR_UNEXPECTED), // Should not be reached.
[email protected]ef0faf2e72009-03-05 23:27:23579 };
580
[email protected]31a2bfe2010-02-09 08:03:39581 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
582 data_writes1, arraysize(data_writes1));
[email protected]5ecc992a42009-11-11 01:41:59583 session_deps.socket_factory.AddSocketDataProvider(&data1);
[email protected]ef0faf2e72009-03-05 23:27:23584
585 TestCompletionCallback callback1;
586
[email protected]5a1d7ca2010-04-28 20:12:27587 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:42588 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]ef0faf2e72009-03-05 23:27:23589
590 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42591 EXPECT_EQ(OK, rv);
[email protected]ef0faf2e72009-03-05 23:27:23592
[email protected]1c773ea12009-04-28 19:58:42593 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]ef0faf2e72009-03-05 23:27:23594 EXPECT_FALSE(response == NULL);
595
596 // Check that the headers got parsed.
597 EXPECT_TRUE(response->headers != NULL);
598 EXPECT_EQ(1234, response->headers->GetContentLength());
599 EXPECT_EQ("HTTP/1.1 404 Not Found", response->headers->GetStatusLine());
600
601 std::string server_header;
602 void* iter = NULL;
603 bool has_server_header = response->headers->EnumerateHeader(
604 &iter, "Server", &server_header);
605 EXPECT_TRUE(has_server_header);
606 EXPECT_EQ("Blah", server_header);
607
608 // Reading should give EOF right away, since there is no message body
609 // (despite non-zero content-length).
610 std::string response_data;
611 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:42612 EXPECT_EQ(OK, rv);
[email protected]ef0faf2e72009-03-05 23:27:23613 EXPECT_EQ("", response_data);
614}
615
initial.commit586acc5fe2008-07-26 22:42:52616TEST_F(HttpNetworkTransactionTest, ReuseConnection) {
[email protected]228ff742009-06-05 01:19:59617 SessionDependencies session_deps;
[email protected]ad8e04a2010-11-01 04:16:27618 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
initial.commit586acc5fe2008-07-26 22:42:52619
620 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35621 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
622 MockRead("hello"),
623 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
624 MockRead("world"),
[email protected]1c773ea12009-04-28 19:58:42625 MockRead(false, OK),
initial.commit586acc5fe2008-07-26 22:42:52626 };
[email protected]31a2bfe2010-02-09 08:03:39627 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:59628 session_deps.socket_factory.AddSocketDataProvider(&data);
initial.commit586acc5fe2008-07-26 22:42:52629
[email protected]0b0bf032010-09-21 18:08:50630 const char* const kExpectedResponseData[] = {
initial.commit586acc5fe2008-07-26 22:42:52631 "hello", "world"
632 };
633
634 for (int i = 0; i < 2; ++i) {
[email protected]5695b8c2009-09-30 21:36:43635 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
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.google.com/");
640 request.load_flags = 0;
641
642 TestCompletionCallback callback;
643
[email protected]5a1d7ca2010-04-28 20:12:27644 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:42645 EXPECT_EQ(ERR_IO_PENDING, rv);
initial.commit586acc5fe2008-07-26 22:42:52646
647 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42648 EXPECT_EQ(OK, rv);
initial.commit586acc5fe2008-07-26 22:42:52649
[email protected]1c773ea12009-04-28 19:58:42650 const HttpResponseInfo* response = trans->GetResponseInfo();
initial.commit586acc5fe2008-07-26 22:42:52651 EXPECT_TRUE(response != NULL);
652
653 EXPECT_TRUE(response->headers != NULL);
[email protected]3d2a59b2008-09-26 19:44:25654 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
initial.commit586acc5fe2008-07-26 22:42:52655
656 std::string response_data;
[email protected]af4876d2008-10-21 23:10:57657 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:42658 EXPECT_EQ(OK, rv);
[email protected]3d2a59b2008-09-26 19:44:25659 EXPECT_EQ(kExpectedResponseData[i], response_data);
initial.commit586acc5fe2008-07-26 22:42:52660 }
661}
662
663TEST_F(HttpNetworkTransactionTest, Ignores100) {
[email protected]228ff742009-06-05 01:19:59664 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:40665 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:43666 new HttpNetworkTransaction(CreateSession(&session_deps)));
initial.commit586acc5fe2008-07-26 22:42:52667
[email protected]1c773ea12009-04-28 19:58:42668 HttpRequestInfo request;
initial.commit586acc5fe2008-07-26 22:42:52669 request.method = "POST";
670 request.url = GURL("http://www.foo.com/");
[email protected]1c773ea12009-04-28 19:58:42671 request.upload_data = new UploadData;
initial.commit586acc5fe2008-07-26 22:42:52672 request.upload_data->AppendBytes("foo", 3);
673 request.load_flags = 0;
674
675 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35676 MockRead("HTTP/1.0 100 Continue\r\n\r\n"),
677 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
678 MockRead("hello world"),
[email protected]1c773ea12009-04-28 19:58:42679 MockRead(false, OK),
initial.commit586acc5fe2008-07-26 22:42:52680 };
[email protected]31a2bfe2010-02-09 08:03:39681 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:59682 session_deps.socket_factory.AddSocketDataProvider(&data);
initial.commit586acc5fe2008-07-26 22:42:52683
684 TestCompletionCallback callback;
685
[email protected]5a1d7ca2010-04-28 20:12:27686 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:42687 EXPECT_EQ(ERR_IO_PENDING, rv);
initial.commit586acc5fe2008-07-26 22:42:52688
689 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42690 EXPECT_EQ(OK, rv);
initial.commit586acc5fe2008-07-26 22:42:52691
[email protected]1c773ea12009-04-28 19:58:42692 const HttpResponseInfo* response = trans->GetResponseInfo();
initial.commit586acc5fe2008-07-26 22:42:52693 EXPECT_TRUE(response != NULL);
694
695 EXPECT_TRUE(response->headers != NULL);
[email protected]3d2a59b2008-09-26 19:44:25696 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
initial.commit586acc5fe2008-07-26 22:42:52697
698 std::string response_data;
[email protected]af4876d2008-10-21 23:10:57699 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:42700 EXPECT_EQ(OK, rv);
[email protected]3d2a59b2008-09-26 19:44:25701 EXPECT_EQ("hello world", response_data);
initial.commit586acc5fe2008-07-26 22:42:52702}
703
[email protected]3a2d3662009-03-27 03:49:14704// This test is almost the same as Ignores100 above, but the response contains
705// a 102 instead of a 100. Also, instead of HTTP/1.0 the response is
[email protected]0877e3d2009-10-17 22:29:57706// HTTP/1.1 and the two status headers are read in one read.
[email protected]3a2d3662009-03-27 03:49:14707TEST_F(HttpNetworkTransactionTest, Ignores1xx) {
[email protected]228ff742009-06-05 01:19:59708 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:40709 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:43710 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]3a2d3662009-03-27 03:49:14711
[email protected]1c773ea12009-04-28 19:58:42712 HttpRequestInfo request;
[email protected]3a2d3662009-03-27 03:49:14713 request.method = "GET";
714 request.url = GURL("http://www.foo.com/");
715 request.load_flags = 0;
716
717 MockRead data_reads[] = {
[email protected]0877e3d2009-10-17 22:29:57718 MockRead("HTTP/1.1 102 Unspecified status code\r\n\r\n"
719 "HTTP/1.1 200 OK\r\n\r\n"),
[email protected]3a2d3662009-03-27 03:49:14720 MockRead("hello world"),
[email protected]1c773ea12009-04-28 19:58:42721 MockRead(false, OK),
[email protected]3a2d3662009-03-27 03:49:14722 };
[email protected]31a2bfe2010-02-09 08:03:39723 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:59724 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]3a2d3662009-03-27 03:49:14725
726 TestCompletionCallback callback;
727
[email protected]5a1d7ca2010-04-28 20:12:27728 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:42729 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]3a2d3662009-03-27 03:49:14730
731 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42732 EXPECT_EQ(OK, rv);
[email protected]3a2d3662009-03-27 03:49:14733
[email protected]1c773ea12009-04-28 19:58:42734 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]3a2d3662009-03-27 03:49:14735 EXPECT_TRUE(response != NULL);
736
737 EXPECT_TRUE(response->headers != NULL);
738 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
739
740 std::string response_data;
741 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:42742 EXPECT_EQ(OK, rv);
[email protected]3a2d3662009-03-27 03:49:14743 EXPECT_EQ("hello world", response_data);
744}
745
[email protected]ee9410e72010-01-07 01:42:38746TEST_F(HttpNetworkTransactionTest, Incomplete100ThenEOF) {
747 SessionDependencies session_deps;
748 scoped_ptr<HttpTransaction> trans(
749 new HttpNetworkTransaction(CreateSession(&session_deps)));
750
751 HttpRequestInfo request;
752 request.method = "POST";
753 request.url = GURL("http://www.foo.com/");
754 request.load_flags = 0;
755
756 MockRead data_reads[] = {
757 MockRead(false, "HTTP/1.0 100 Continue\r\n"),
758 MockRead(true, 0),
759 };
[email protected]31a2bfe2010-02-09 08:03:39760 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]ee9410e72010-01-07 01:42:38761 session_deps.socket_factory.AddSocketDataProvider(&data);
762
763 TestCompletionCallback callback;
764
[email protected]5a1d7ca2010-04-28 20:12:27765 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]ee9410e72010-01-07 01:42:38766 EXPECT_EQ(ERR_IO_PENDING, rv);
767
768 rv = callback.WaitForResult();
769 EXPECT_EQ(OK, rv);
770
771 std::string response_data;
772 rv = ReadTransaction(trans.get(), &response_data);
773 EXPECT_EQ(OK, rv);
774 EXPECT_EQ("", response_data);
775}
776
777TEST_F(HttpNetworkTransactionTest, EmptyResponse) {
778 SessionDependencies session_deps;
779 scoped_ptr<HttpTransaction> trans(
780 new HttpNetworkTransaction(CreateSession(&session_deps)));
781
782 HttpRequestInfo request;
783 request.method = "POST";
784 request.url = GURL("http://www.foo.com/");
785 request.load_flags = 0;
786
787 MockRead data_reads[] = {
788 MockRead(true, 0),
789 };
[email protected]31a2bfe2010-02-09 08:03:39790 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]ee9410e72010-01-07 01:42:38791 session_deps.socket_factory.AddSocketDataProvider(&data);
792
793 TestCompletionCallback callback;
794
[email protected]5a1d7ca2010-04-28 20:12:27795 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]ee9410e72010-01-07 01:42:38796 EXPECT_EQ(ERR_IO_PENDING, rv);
797
798 rv = callback.WaitForResult();
799 EXPECT_EQ(ERR_EMPTY_RESPONSE, rv);
800}
801
[email protected]3d2a59b2008-09-26 19:44:25802// read_failure specifies a read failure that should cause the network
803// transaction to resend the request.
804void HttpNetworkTransactionTest::KeepAliveConnectionResendRequestTest(
805 const MockRead& read_failure) {
[email protected]228ff742009-06-05 01:19:59806 SessionDependencies session_deps;
[email protected]ad8e04a2010-11-01 04:16:27807 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
initial.commit586acc5fe2008-07-26 22:42:52808
[email protected]1c773ea12009-04-28 19:58:42809 HttpRequestInfo request;
initial.commit586acc5fe2008-07-26 22:42:52810 request.method = "GET";
811 request.url = GURL("http://www.foo.com/");
812 request.load_flags = 0;
813
814 MockRead data1_reads[] = {
[email protected]217e6022008-09-29 18:18:35815 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
816 MockRead("hello"),
[email protected]3d2a59b2008-09-26 19:44:25817 read_failure, // Now, we reuse the connection and fail the first read.
initial.commit586acc5fe2008-07-26 22:42:52818 };
[email protected]31a2bfe2010-02-09 08:03:39819 StaticSocketDataProvider data1(data1_reads, arraysize(data1_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:59820 session_deps.socket_factory.AddSocketDataProvider(&data1);
initial.commit586acc5fe2008-07-26 22:42:52821
822 MockRead data2_reads[] = {
[email protected]217e6022008-09-29 18:18:35823 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
824 MockRead("world"),
[email protected]1c773ea12009-04-28 19:58:42825 MockRead(true, OK),
initial.commit586acc5fe2008-07-26 22:42:52826 };
[email protected]31a2bfe2010-02-09 08:03:39827 StaticSocketDataProvider data2(data2_reads, arraysize(data2_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:59828 session_deps.socket_factory.AddSocketDataProvider(&data2);
initial.commit586acc5fe2008-07-26 22:42:52829
830 const char* kExpectedResponseData[] = {
831 "hello", "world"
832 };
833
834 for (int i = 0; i < 2; ++i) {
835 TestCompletionCallback callback;
836
[email protected]5695b8c2009-09-30 21:36:43837 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
initial.commit586acc5fe2008-07-26 22:42:52838
[email protected]5a1d7ca2010-04-28 20:12:27839 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:42840 EXPECT_EQ(ERR_IO_PENDING, rv);
initial.commit586acc5fe2008-07-26 22:42:52841
842 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42843 EXPECT_EQ(OK, rv);
initial.commit586acc5fe2008-07-26 22:42:52844
[email protected]1c773ea12009-04-28 19:58:42845 const HttpResponseInfo* response = trans->GetResponseInfo();
initial.commit586acc5fe2008-07-26 22:42:52846 EXPECT_TRUE(response != NULL);
847
848 EXPECT_TRUE(response->headers != NULL);
[email protected]3d2a59b2008-09-26 19:44:25849 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
initial.commit586acc5fe2008-07-26 22:42:52850
851 std::string response_data;
[email protected]af4876d2008-10-21 23:10:57852 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:42853 EXPECT_EQ(OK, rv);
[email protected]3d2a59b2008-09-26 19:44:25854 EXPECT_EQ(kExpectedResponseData[i], response_data);
initial.commit586acc5fe2008-07-26 22:42:52855 }
856}
[email protected]3d2a59b2008-09-26 19:44:25857
858TEST_F(HttpNetworkTransactionTest, KeepAliveConnectionReset) {
[email protected]1c773ea12009-04-28 19:58:42859 MockRead read_failure(true, ERR_CONNECTION_RESET);
[email protected]3d2a59b2008-09-26 19:44:25860 KeepAliveConnectionResendRequestTest(read_failure);
861}
862
863TEST_F(HttpNetworkTransactionTest, KeepAliveConnectionEOF) {
[email protected]1c773ea12009-04-28 19:58:42864 MockRead read_failure(false, OK); // EOF
[email protected]3d2a59b2008-09-26 19:44:25865 KeepAliveConnectionResendRequestTest(read_failure);
866}
867
868TEST_F(HttpNetworkTransactionTest, NonKeepAliveConnectionReset) {
[email protected]228ff742009-06-05 01:19:59869 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:40870 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:43871 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]3d2a59b2008-09-26 19:44:25872
[email protected]1c773ea12009-04-28 19:58:42873 HttpRequestInfo request;
[email protected]3d2a59b2008-09-26 19:44:25874 request.method = "GET";
875 request.url = GURL("http://www.google.com/");
876 request.load_flags = 0;
877
878 MockRead data_reads[] = {
[email protected]1c773ea12009-04-28 19:58:42879 MockRead(true, ERR_CONNECTION_RESET),
[email protected]217e6022008-09-29 18:18:35880 MockRead("HTTP/1.0 200 OK\r\n\r\n"), // Should not be used
881 MockRead("hello world"),
[email protected]1c773ea12009-04-28 19:58:42882 MockRead(false, OK),
[email protected]3d2a59b2008-09-26 19:44:25883 };
[email protected]31a2bfe2010-02-09 08:03:39884 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:59885 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]3d2a59b2008-09-26 19:44:25886
887 TestCompletionCallback callback;
888
[email protected]5a1d7ca2010-04-28 20:12:27889 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:42890 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]3d2a59b2008-09-26 19:44:25891
892 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42893 EXPECT_EQ(ERR_CONNECTION_RESET, rv);
[email protected]3d2a59b2008-09-26 19:44:25894
[email protected]1c773ea12009-04-28 19:58:42895 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]3d2a59b2008-09-26 19:44:25896 EXPECT_TRUE(response == NULL);
[email protected]3d2a59b2008-09-26 19:44:25897}
898
899// What do various browsers do when the server closes a non-keepalive
900// connection without sending any response header or body?
901//
902// IE7: error page
903// Safari 3.1.2 (Windows): error page
904// Firefox 3.0.1: blank page
905// Opera 9.52: after five attempts, blank page
[email protected]1c773ea12009-04-28 19:58:42906// Us with WinHTTP: error page (ERR_INVALID_RESPONSE)
907// Us: error page (EMPTY_RESPONSE)
[email protected]3d2a59b2008-09-26 19:44:25908TEST_F(HttpNetworkTransactionTest, NonKeepAliveConnectionEOF) {
909 MockRead data_reads[] = {
[email protected]1c773ea12009-04-28 19:58:42910 MockRead(false, OK), // EOF
[email protected]217e6022008-09-29 18:18:35911 MockRead("HTTP/1.0 200 OK\r\n\r\n"), // Should not be used
912 MockRead("hello world"),
[email protected]1c773ea12009-04-28 19:58:42913 MockRead(false, OK),
[email protected]3d2a59b2008-09-26 19:44:25914 };
[email protected]31a2bfe2010-02-09 08:03:39915 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
916 arraysize(data_reads));
[email protected]1c773ea12009-04-28 19:58:42917 EXPECT_EQ(ERR_EMPTY_RESPONSE, out.rv);
[email protected]3d2a59b2008-09-26 19:44:25918}
[email protected]038e9a32008-10-08 22:40:16919
[email protected]0b0bf032010-09-21 18:08:50920// Test that we correctly reuse a keep-alive connection after not explicitly
921// reading the body.
922TEST_F(HttpNetworkTransactionTest, KeepAliveAfterUnreadBody) {
[email protected]fc31d6a42010-06-24 18:05:13923 SessionDependencies session_deps;
[email protected]ad8e04a2010-11-01 04:16:27924 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]fc31d6a42010-06-24 18:05:13925
926 HttpRequestInfo request;
927 request.method = "GET";
928 request.url = GURL("http://www.foo.com/");
929 request.load_flags = 0;
930
[email protected]0b0bf032010-09-21 18:08:50931 // Note that because all these reads happen in the same
932 // StaticSocketDataProvider, it shows that the same socket is being reused for
933 // all transactions.
[email protected]fc31d6a42010-06-24 18:05:13934 MockRead data1_reads[] = {
[email protected]0b0bf032010-09-21 18:08:50935 MockRead("HTTP/1.1 204 No Content\r\n\r\n"),
936 MockRead("HTTP/1.1 205 Reset Content\r\n\r\n"),
[email protected]fc31d6a42010-06-24 18:05:13937 MockRead("HTTP/1.1 304 Not Modified\r\n\r\n"),
[email protected]0b0bf032010-09-21 18:08:50938 MockRead("HTTP/1.1 302 Found\r\n"
939 "Content-Length: 0\r\n\r\n"),
940 MockRead("HTTP/1.1 302 Found\r\n"
941 "Content-Length: 5\r\n\r\n"
942 "hello"),
943 MockRead("HTTP/1.1 301 Moved Permanently\r\n"
944 "Content-Length: 0\r\n\r\n"),
945 MockRead("HTTP/1.1 301 Moved Permanently\r\n"
946 "Content-Length: 5\r\n\r\n"
947 "hello"),
[email protected]fc31d6a42010-06-24 18:05:13948 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
949 MockRead("hello"),
950 };
951 StaticSocketDataProvider data1(data1_reads, arraysize(data1_reads), NULL, 0);
952 session_deps.socket_factory.AddSocketDataProvider(&data1);
953
954 MockRead data2_reads[] = {
955 MockRead(false, ERR_UNEXPECTED), // Should not be reached.
956 };
957 StaticSocketDataProvider data2(data2_reads, arraysize(data2_reads), NULL, 0);
958 session_deps.socket_factory.AddSocketDataProvider(&data2);
959
[email protected]0b0bf032010-09-21 18:08:50960 const int kNumUnreadBodies = arraysize(data1_reads) - 2;
961 std::string response_lines[kNumUnreadBodies];
962
963 for (size_t i = 0; i < arraysize(data1_reads) - 2; ++i) {
[email protected]fc31d6a42010-06-24 18:05:13964 TestCompletionCallback callback;
965
966 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
967
968 int rv = trans->Start(&request, &callback, BoundNetLog());
969 EXPECT_EQ(ERR_IO_PENDING, rv);
970
971 rv = callback.WaitForResult();
972 EXPECT_EQ(OK, rv);
973
974 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]0b0bf032010-09-21 18:08:50975 ASSERT_TRUE(response != NULL);
[email protected]fc31d6a42010-06-24 18:05:13976
[email protected]0b0bf032010-09-21 18:08:50977 ASSERT_TRUE(response->headers != NULL);
978 response_lines[i] = response->headers->GetStatusLine();
979
980 // We intentionally don't read the response bodies.
[email protected]fc31d6a42010-06-24 18:05:13981 }
[email protected]0b0bf032010-09-21 18:08:50982
983 const char* const kStatusLines[] = {
984 "HTTP/1.1 204 No Content",
985 "HTTP/1.1 205 Reset Content",
986 "HTTP/1.1 304 Not Modified",
987 "HTTP/1.1 302 Found",
988 "HTTP/1.1 302 Found",
989 "HTTP/1.1 301 Moved Permanently",
990 "HTTP/1.1 301 Moved Permanently",
991 };
992
993 COMPILE_ASSERT(kNumUnreadBodies == arraysize(kStatusLines),
994 forgot_to_update_kStatusLines);
995
996 for (int i = 0; i < kNumUnreadBodies; ++i)
997 EXPECT_EQ(kStatusLines[i], response_lines[i]);
998
999 TestCompletionCallback callback;
1000 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
1001 int rv = trans->Start(&request, &callback, BoundNetLog());
1002 EXPECT_EQ(ERR_IO_PENDING, rv);
1003 rv = callback.WaitForResult();
1004 EXPECT_EQ(OK, rv);
1005 const HttpResponseInfo* response = trans->GetResponseInfo();
1006 ASSERT_TRUE(response != NULL);
1007 ASSERT_TRUE(response->headers != NULL);
1008 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
1009 std::string response_data;
1010 rv = ReadTransaction(trans.get(), &response_data);
1011 EXPECT_EQ(OK, rv);
1012 EXPECT_EQ("hello", response_data);
[email protected]fc31d6a42010-06-24 18:05:131013}
1014
[email protected]038e9a32008-10-08 22:40:161015// Test the request-challenge-retry sequence for basic auth.
1016// (basic auth is the easiest to mock, because it has no randomness).
1017TEST_F(HttpNetworkTransactionTest, BasicAuth) {
[email protected]228ff742009-06-05 01:19:591018 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:401019 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:431020 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]038e9a32008-10-08 22:40:161021
[email protected]1c773ea12009-04-28 19:58:421022 HttpRequestInfo request;
[email protected]038e9a32008-10-08 22:40:161023 request.method = "GET";
1024 request.url = GURL("http://www.google.com/");
1025 request.load_flags = 0;
1026
[email protected]f9ee6b52008-11-08 06:46:231027 MockWrite data_writes1[] = {
1028 MockWrite("GET / HTTP/1.1\r\n"
1029 "Host: www.google.com\r\n"
1030 "Connection: keep-alive\r\n\r\n"),
1031 };
1032
[email protected]038e9a32008-10-08 22:40:161033 MockRead data_reads1[] = {
1034 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
1035 // Give a couple authenticate options (only the middle one is actually
1036 // supported).
[email protected]22927ad2009-09-21 19:56:191037 MockRead("WWW-Authenticate: Basic invalid\r\n"), // Malformed.
[email protected]038e9a32008-10-08 22:40:161038 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1039 MockRead("WWW-Authenticate: UNSUPPORTED realm=\"FOO\"\r\n"),
1040 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1041 // Large content-length -- won't matter, as connection will be reset.
1042 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:421043 MockRead(false, ERR_FAILED),
[email protected]038e9a32008-10-08 22:40:161044 };
1045
1046 // After calling trans->RestartWithAuth(), this is the request we should
1047 // be issuing -- the final header line contains the credentials.
1048 MockWrite data_writes2[] = {
1049 MockWrite("GET / HTTP/1.1\r\n"
1050 "Host: www.google.com\r\n"
1051 "Connection: keep-alive\r\n"
1052 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
1053 };
1054
1055 // Lastly, the server responds with the actual content.
1056 MockRead data_reads2[] = {
1057 MockRead("HTTP/1.0 200 OK\r\n"),
1058 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1059 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:421060 MockRead(false, OK),
[email protected]038e9a32008-10-08 22:40:161061 };
1062
[email protected]31a2bfe2010-02-09 08:03:391063 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
1064 data_writes1, arraysize(data_writes1));
1065 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
1066 data_writes2, arraysize(data_writes2));
[email protected]5ecc992a42009-11-11 01:41:591067 session_deps.socket_factory.AddSocketDataProvider(&data1);
1068 session_deps.socket_factory.AddSocketDataProvider(&data2);
[email protected]038e9a32008-10-08 22:40:161069
1070 TestCompletionCallback callback1;
1071
[email protected]5a1d7ca2010-04-28 20:12:271072 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:421073 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]038e9a32008-10-08 22:40:161074
1075 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421076 EXPECT_EQ(OK, rv);
[email protected]038e9a32008-10-08 22:40:161077
[email protected]1c773ea12009-04-28 19:58:421078 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]038e9a32008-10-08 22:40:161079 EXPECT_FALSE(response == NULL);
1080
1081 // The password prompt info should have been set in response->auth_challenge.
1082 EXPECT_FALSE(response->auth_challenge.get() == NULL);
1083
[email protected]71e4573a2009-05-21 22:03:001084 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
[email protected]038e9a32008-10-08 22:40:161085 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
1086 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
1087
1088 TestCompletionCallback callback2;
1089
[email protected]13c8a092010-07-29 06:15:441090 rv = trans->RestartWithAuth(kFoo, kBar, &callback2);
[email protected]1c773ea12009-04-28 19:58:421091 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]038e9a32008-10-08 22:40:161092
1093 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421094 EXPECT_EQ(OK, rv);
[email protected]038e9a32008-10-08 22:40:161095
1096 response = trans->GetResponseInfo();
1097 EXPECT_FALSE(response == NULL);
1098 EXPECT_TRUE(response->auth_challenge.get() == NULL);
1099 EXPECT_EQ(100, response->headers->GetContentLength());
[email protected]038e9a32008-10-08 22:40:161100}
1101
[email protected]861fcd52009-08-26 02:33:461102TEST_F(HttpNetworkTransactionTest, DoNotSendAuth) {
1103 SessionDependencies session_deps;
1104 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:431105 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]861fcd52009-08-26 02:33:461106
1107 HttpRequestInfo request;
1108 request.method = "GET";
1109 request.url = GURL("http://www.google.com/");
1110 request.load_flags = net::LOAD_DO_NOT_SEND_AUTH_DATA;
1111
1112 MockWrite data_writes[] = {
1113 MockWrite("GET / HTTP/1.1\r\n"
1114 "Host: www.google.com\r\n"
1115 "Connection: keep-alive\r\n\r\n"),
1116 };
1117
1118 MockRead data_reads[] = {
1119 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
1120 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1121 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1122 // Large content-length -- won't matter, as connection will be reset.
1123 MockRead("Content-Length: 10000\r\n\r\n"),
1124 MockRead(false, ERR_FAILED),
1125 };
1126
[email protected]31a2bfe2010-02-09 08:03:391127 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
1128 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:591129 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]861fcd52009-08-26 02:33:461130 TestCompletionCallback callback;
1131
[email protected]5a1d7ca2010-04-28 20:12:271132 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]861fcd52009-08-26 02:33:461133 EXPECT_EQ(ERR_IO_PENDING, rv);
1134
1135 rv = callback.WaitForResult();
1136 EXPECT_EQ(0, rv);
1137
1138 const HttpResponseInfo* response = trans->GetResponseInfo();
1139 ASSERT_FALSE(response == NULL);
1140 EXPECT_TRUE(response->auth_challenge.get() == NULL);
1141}
1142
[email protected]2d2697f92009-02-18 21:00:321143// Test the request-challenge-retry sequence for basic auth, over a keep-alive
1144// connection.
1145TEST_F(HttpNetworkTransactionTest, BasicAuthKeepAlive) {
[email protected]228ff742009-06-05 01:19:591146 SessionDependencies session_deps;
[email protected]0b0bf032010-09-21 18:08:501147 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]2d2697f92009-02-18 21:00:321148
[email protected]1c773ea12009-04-28 19:58:421149 HttpRequestInfo request;
[email protected]2d2697f92009-02-18 21:00:321150 request.method = "GET";
1151 request.url = GURL("http://www.google.com/");
1152 request.load_flags = 0;
1153
1154 MockWrite data_writes1[] = {
1155 MockWrite("GET / HTTP/1.1\r\n"
1156 "Host: www.google.com\r\n"
1157 "Connection: keep-alive\r\n\r\n"),
1158
1159 // After calling trans->RestartWithAuth(), this is the request we should
1160 // be issuing -- the final header line contains the credentials.
1161 MockWrite("GET / HTTP/1.1\r\n"
1162 "Host: www.google.com\r\n"
1163 "Connection: keep-alive\r\n"
1164 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
1165 };
1166
1167 MockRead data_reads1[] = {
1168 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
1169 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1170 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1171 MockRead("Content-Length: 14\r\n\r\n"),
1172 MockRead("Unauthorized\r\n"),
1173
1174 // Lastly, the server responds with the actual content.
1175 MockRead("HTTP/1.1 200 OK\r\n"),
1176 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
[email protected]0b0bf032010-09-21 18:08:501177 MockRead("Content-Length: 5\r\n\r\n"),
1178 MockRead("Hello"),
[email protected]2d2697f92009-02-18 21:00:321179 };
1180
[email protected]31a2bfe2010-02-09 08:03:391181 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
1182 data_writes1, arraysize(data_writes1));
[email protected]5ecc992a42009-11-11 01:41:591183 session_deps.socket_factory.AddSocketDataProvider(&data1);
[email protected]2d2697f92009-02-18 21:00:321184
1185 TestCompletionCallback callback1;
1186
[email protected]0b0bf032010-09-21 18:08:501187 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]5a1d7ca2010-04-28 20:12:271188 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:421189 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:321190
1191 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421192 EXPECT_EQ(OK, rv);
[email protected]2d2697f92009-02-18 21:00:321193
[email protected]1c773ea12009-04-28 19:58:421194 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]2d2697f92009-02-18 21:00:321195 EXPECT_FALSE(response == NULL);
1196
1197 // The password prompt info should have been set in response->auth_challenge.
1198 EXPECT_FALSE(response->auth_challenge.get() == NULL);
1199
[email protected]71e4573a2009-05-21 22:03:001200 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
[email protected]2d2697f92009-02-18 21:00:321201 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
1202 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
1203
1204 TestCompletionCallback callback2;
1205
[email protected]13c8a092010-07-29 06:15:441206 rv = trans->RestartWithAuth(kFoo, kBar, &callback2);
[email protected]1c773ea12009-04-28 19:58:421207 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:321208
1209 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421210 EXPECT_EQ(OK, rv);
[email protected]2d2697f92009-02-18 21:00:321211
1212 response = trans->GetResponseInfo();
1213 EXPECT_FALSE(response == NULL);
1214 EXPECT_TRUE(response->auth_challenge.get() == NULL);
[email protected]0b0bf032010-09-21 18:08:501215 EXPECT_EQ(5, response->headers->GetContentLength());
[email protected]2d2697f92009-02-18 21:00:321216}
1217
1218// Test the request-challenge-retry sequence for basic auth, over a keep-alive
1219// connection and with no response body to drain.
1220TEST_F(HttpNetworkTransactionTest, BasicAuthKeepAliveNoBody) {
[email protected]228ff742009-06-05 01:19:591221 SessionDependencies session_deps;
[email protected]0b0bf032010-09-21 18:08:501222 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]2d2697f92009-02-18 21:00:321223
[email protected]1c773ea12009-04-28 19:58:421224 HttpRequestInfo request;
[email protected]2d2697f92009-02-18 21:00:321225 request.method = "GET";
1226 request.url = GURL("http://www.google.com/");
1227 request.load_flags = 0;
1228
1229 MockWrite data_writes1[] = {
1230 MockWrite("GET / HTTP/1.1\r\n"
1231 "Host: www.google.com\r\n"
1232 "Connection: keep-alive\r\n\r\n"),
1233
1234 // After calling trans->RestartWithAuth(), this is the request we should
1235 // be issuing -- the final header line contains the credentials.
1236 MockWrite("GET / HTTP/1.1\r\n"
1237 "Host: www.google.com\r\n"
1238 "Connection: keep-alive\r\n"
1239 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
1240 };
1241
[email protected]2d2697f92009-02-18 21:00:321242 MockRead data_reads1[] = {
1243 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
1244 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
[email protected]11203f012009-11-12 23:02:311245 MockRead("Content-Length: 0\r\n\r\n"), // No response body.
[email protected]2d2697f92009-02-18 21:00:321246
1247 // Lastly, the server responds with the actual content.
1248 MockRead("HTTP/1.1 200 OK\r\n"),
1249 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
[email protected]0b0bf032010-09-21 18:08:501250 MockRead("Content-Length: 5\r\n\r\n"),
1251 MockRead("hello"),
[email protected]2d2697f92009-02-18 21:00:321252 };
1253
[email protected]31a2bfe2010-02-09 08:03:391254 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
1255 data_writes1, arraysize(data_writes1));
[email protected]5ecc992a42009-11-11 01:41:591256 session_deps.socket_factory.AddSocketDataProvider(&data1);
[email protected]2d2697f92009-02-18 21:00:321257
1258 TestCompletionCallback callback1;
1259
[email protected]0b0bf032010-09-21 18:08:501260 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]5a1d7ca2010-04-28 20:12:271261 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:421262 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:321263
1264 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421265 EXPECT_EQ(OK, rv);
[email protected]2d2697f92009-02-18 21:00:321266
[email protected]1c773ea12009-04-28 19:58:421267 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]2d2697f92009-02-18 21:00:321268 EXPECT_FALSE(response == NULL);
1269
1270 // The password prompt info should have been set in response->auth_challenge.
1271 EXPECT_FALSE(response->auth_challenge.get() == NULL);
1272
[email protected]71e4573a2009-05-21 22:03:001273 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
[email protected]2d2697f92009-02-18 21:00:321274 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
1275 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
1276
1277 TestCompletionCallback callback2;
1278
[email protected]13c8a092010-07-29 06:15:441279 rv = trans->RestartWithAuth(kFoo, kBar, &callback2);
[email protected]1c773ea12009-04-28 19:58:421280 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:321281
1282 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421283 EXPECT_EQ(OK, rv);
[email protected]2d2697f92009-02-18 21:00:321284
1285 response = trans->GetResponseInfo();
1286 EXPECT_FALSE(response == NULL);
1287 EXPECT_TRUE(response->auth_challenge.get() == NULL);
[email protected]0b0bf032010-09-21 18:08:501288 EXPECT_EQ(5, response->headers->GetContentLength());
[email protected]2d2697f92009-02-18 21:00:321289}
1290
1291// Test the request-challenge-retry sequence for basic auth, over a keep-alive
1292// connection and with a large response body to drain.
1293TEST_F(HttpNetworkTransactionTest, BasicAuthKeepAliveLargeBody) {
[email protected]228ff742009-06-05 01:19:591294 SessionDependencies session_deps;
[email protected]0b0bf032010-09-21 18:08:501295 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]2d2697f92009-02-18 21:00:321296
[email protected]1c773ea12009-04-28 19:58:421297 HttpRequestInfo request;
[email protected]2d2697f92009-02-18 21:00:321298 request.method = "GET";
1299 request.url = GURL("http://www.google.com/");
1300 request.load_flags = 0;
1301
1302 MockWrite data_writes1[] = {
1303 MockWrite("GET / HTTP/1.1\r\n"
1304 "Host: www.google.com\r\n"
1305 "Connection: keep-alive\r\n\r\n"),
1306
1307 // After calling trans->RestartWithAuth(), this is the request we should
1308 // be issuing -- the final header line contains the credentials.
1309 MockWrite("GET / HTTP/1.1\r\n"
1310 "Host: www.google.com\r\n"
1311 "Connection: keep-alive\r\n"
1312 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
1313 };
1314
1315 // Respond with 5 kb of response body.
1316 std::string large_body_string("Unauthorized");
1317 large_body_string.append(5 * 1024, ' ');
1318 large_body_string.append("\r\n");
1319
1320 MockRead data_reads1[] = {
1321 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
1322 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1323 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1324 // 5134 = 12 + 5 * 1024 + 2
1325 MockRead("Content-Length: 5134\r\n\r\n"),
1326 MockRead(true, large_body_string.data(), large_body_string.size()),
1327
1328 // Lastly, the server responds with the actual content.
1329 MockRead("HTTP/1.1 200 OK\r\n"),
1330 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
[email protected]0b0bf032010-09-21 18:08:501331 MockRead("Content-Length: 5\r\n\r\n"),
1332 MockRead("hello"),
[email protected]2d2697f92009-02-18 21:00:321333 };
1334
[email protected]31a2bfe2010-02-09 08:03:391335 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
1336 data_writes1, arraysize(data_writes1));
[email protected]5ecc992a42009-11-11 01:41:591337 session_deps.socket_factory.AddSocketDataProvider(&data1);
[email protected]2d2697f92009-02-18 21:00:321338
1339 TestCompletionCallback callback1;
1340
[email protected]0b0bf032010-09-21 18:08:501341 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]5a1d7ca2010-04-28 20:12:271342 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:421343 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:321344
1345 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421346 EXPECT_EQ(OK, rv);
[email protected]2d2697f92009-02-18 21:00:321347
[email protected]1c773ea12009-04-28 19:58:421348 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]2d2697f92009-02-18 21:00:321349 EXPECT_FALSE(response == NULL);
1350
1351 // The password prompt info should have been set in response->auth_challenge.
1352 EXPECT_FALSE(response->auth_challenge.get() == NULL);
1353
[email protected]71e4573a2009-05-21 22:03:001354 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
[email protected]2d2697f92009-02-18 21:00:321355 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
1356 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
1357
1358 TestCompletionCallback callback2;
1359
[email protected]13c8a092010-07-29 06:15:441360 rv = trans->RestartWithAuth(kFoo, kBar, &callback2);
[email protected]1c773ea12009-04-28 19:58:421361 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:321362
1363 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421364 EXPECT_EQ(OK, rv);
[email protected]2d2697f92009-02-18 21:00:321365
1366 response = trans->GetResponseInfo();
1367 EXPECT_FALSE(response == NULL);
1368 EXPECT_TRUE(response->auth_challenge.get() == NULL);
[email protected]0b0bf032010-09-21 18:08:501369 EXPECT_EQ(5, response->headers->GetContentLength());
[email protected]2d2697f92009-02-18 21:00:321370}
1371
1372// Test the request-challenge-retry sequence for basic auth, over a keep-alive
[email protected]11203f012009-11-12 23:02:311373// connection, but the server gets impatient and closes the connection.
1374TEST_F(HttpNetworkTransactionTest, BasicAuthKeepAliveImpatientServer) {
1375 SessionDependencies session_deps;
[email protected]0b0bf032010-09-21 18:08:501376 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]11203f012009-11-12 23:02:311377
1378 HttpRequestInfo request;
1379 request.method = "GET";
1380 request.url = GURL("http://www.google.com/");
1381 request.load_flags = 0;
1382
1383 MockWrite data_writes1[] = {
1384 MockWrite("GET / HTTP/1.1\r\n"
1385 "Host: www.google.com\r\n"
1386 "Connection: keep-alive\r\n\r\n"),
1387 // This simulates the seemingly successful write to a closed connection
1388 // if the bug is not fixed.
1389 MockWrite("GET / HTTP/1.1\r\n"
1390 "Host: www.google.com\r\n"
1391 "Connection: keep-alive\r\n"
1392 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
1393 };
1394
1395 MockRead data_reads1[] = {
1396 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
1397 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1398 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1399 MockRead("Content-Length: 14\r\n\r\n"),
1400 // Tell MockTCPClientSocket to simulate the server closing the connection.
1401 MockRead(false, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
1402 MockRead("Unauthorized\r\n"),
1403 MockRead(false, OK), // The server closes the connection.
1404 };
1405
1406 // After calling trans->RestartWithAuth(), this is the request we should
1407 // be issuing -- the final header line contains the credentials.
1408 MockWrite data_writes2[] = {
1409 MockWrite("GET / HTTP/1.1\r\n"
1410 "Host: www.google.com\r\n"
1411 "Connection: keep-alive\r\n"
1412 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
1413 };
1414
1415 // Lastly, the server responds with the actual content.
1416 MockRead data_reads2[] = {
1417 MockRead("HTTP/1.1 200 OK\r\n"),
1418 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
[email protected]0b0bf032010-09-21 18:08:501419 MockRead("Content-Length: 5\r\n\r\n"),
1420 MockRead("hello"),
[email protected]11203f012009-11-12 23:02:311421 };
1422
[email protected]31a2bfe2010-02-09 08:03:391423 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
1424 data_writes1, arraysize(data_writes1));
1425 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
1426 data_writes2, arraysize(data_writes2));
[email protected]11203f012009-11-12 23:02:311427 session_deps.socket_factory.AddSocketDataProvider(&data1);
1428 session_deps.socket_factory.AddSocketDataProvider(&data2);
1429
1430 TestCompletionCallback callback1;
1431
[email protected]0b0bf032010-09-21 18:08:501432 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]5a1d7ca2010-04-28 20:12:271433 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]11203f012009-11-12 23:02:311434 EXPECT_EQ(ERR_IO_PENDING, rv);
1435
1436 rv = callback1.WaitForResult();
1437 EXPECT_EQ(OK, rv);
1438
1439 const HttpResponseInfo* response = trans->GetResponseInfo();
1440 EXPECT_FALSE(response == NULL);
1441
1442 // The password prompt info should have been set in response->auth_challenge.
1443 EXPECT_FALSE(response->auth_challenge.get() == NULL);
1444
1445 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
1446 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
1447 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
1448
1449 TestCompletionCallback callback2;
1450
[email protected]13c8a092010-07-29 06:15:441451 rv = trans->RestartWithAuth(kFoo, kBar, &callback2);
[email protected]11203f012009-11-12 23:02:311452 EXPECT_EQ(ERR_IO_PENDING, rv);
1453
1454 rv = callback2.WaitForResult();
1455 EXPECT_EQ(OK, rv);
1456
1457 response = trans->GetResponseInfo();
1458 ASSERT_FALSE(response == NULL);
1459 EXPECT_TRUE(response->auth_challenge.get() == NULL);
[email protected]0b0bf032010-09-21 18:08:501460 EXPECT_EQ(5, response->headers->GetContentLength());
[email protected]11203f012009-11-12 23:02:311461}
1462
[email protected]394816e92010-08-03 07:38:591463// Test the request-challenge-retry sequence for basic auth, over a connection
1464// that requires a restart when setting up an SSL tunnel.
1465TEST_F(HttpNetworkTransactionTest, BasicAuthProxyNoKeepAlive) {
1466 // Configure against proxy server "myproxy:70".
[email protected]81cdfcd2010-10-16 00:49:001467 SessionDependencies session_deps(ProxyService::CreateFixed("myproxy:70"));
[email protected]394816e92010-08-03 07:38:591468 CapturingBoundNetLog log(CapturingNetLog::kUnbounded);
1469 session_deps.net_log = log.bound().net_log();
1470 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
1471
[email protected]394816e92010-08-03 07:38:591472 HttpRequestInfo request;
1473 request.method = "GET";
1474 request.url = GURL("https://www.google.com/");
1475 // when the no authentication data flag is set.
1476 request.load_flags = net::LOAD_DO_NOT_SEND_AUTH_DATA;
1477
1478 // Since we have proxy, should try to establish tunnel.
1479 MockWrite data_writes1[] = {
1480 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
1481 "Host: www.google.com\r\n"
1482 "Proxy-Connection: keep-alive\r\n\r\n"),
1483
1484 // After calling trans->RestartWithAuth(), this is the request we should
1485 // be issuing -- the final header line contains the credentials.
1486 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
1487 "Host: www.google.com\r\n"
1488 "Proxy-Connection: keep-alive\r\n"
1489 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
1490
1491 MockWrite("GET / HTTP/1.1\r\n"
1492 "Host: www.google.com\r\n"
1493 "Connection: keep-alive\r\n\r\n"),
1494 };
1495
1496 // The proxy responds to the connect with a 407, using a persistent
1497 // connection.
1498 MockRead data_reads1[] = {
1499 // No credentials.
1500 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
1501 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1502 MockRead("Proxy-Connection: close\r\n\r\n"),
1503
1504 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
1505
1506 MockRead("HTTP/1.1 200 OK\r\n"),
1507 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
[email protected]0b0bf032010-09-21 18:08:501508 MockRead("Content-Length: 5\r\n\r\n"),
1509 MockRead(false, "hello"),
[email protected]394816e92010-08-03 07:38:591510 };
1511
1512 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
1513 data_writes1, arraysize(data_writes1));
1514 session_deps.socket_factory.AddSocketDataProvider(&data1);
1515 SSLSocketDataProvider ssl(true, OK);
1516 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
1517
1518 TestCompletionCallback callback1;
1519
[email protected]0b0bf032010-09-21 18:08:501520 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
1521
[email protected]394816e92010-08-03 07:38:591522 int rv = trans->Start(&request, &callback1, log.bound());
1523 EXPECT_EQ(ERR_IO_PENDING, rv);
1524
1525 rv = callback1.WaitForResult();
1526 EXPECT_EQ(OK, rv);
1527 size_t pos = ExpectLogContainsSomewhere(
1528 log.entries(), 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
1529 NetLog::PHASE_NONE);
1530 ExpectLogContainsSomewhere(
1531 log.entries(), pos,
1532 NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
1533 NetLog::PHASE_NONE);
1534
1535 const HttpResponseInfo* response = trans->GetResponseInfo();
1536 ASSERT_FALSE(response == NULL);
1537
1538 EXPECT_EQ(407, response->headers->response_code());
1539 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
1540
1541 // The password prompt info should have been set in response->auth_challenge.
1542 ASSERT_FALSE(response->auth_challenge.get() == NULL);
1543
1544 EXPECT_EQ(L"myproxy:70", response->auth_challenge->host_and_port);
1545 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
1546 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
1547
1548 TestCompletionCallback callback2;
1549
1550 rv = trans->RestartWithAuth(kFoo, kBar, &callback2);
1551 EXPECT_EQ(ERR_IO_PENDING, rv);
1552
1553 rv = callback2.WaitForResult();
1554 EXPECT_EQ(OK, rv);
1555
1556 response = trans->GetResponseInfo();
1557 ASSERT_FALSE(response == NULL);
1558
1559 EXPECT_TRUE(response->headers->IsKeepAlive());
1560 EXPECT_EQ(200, response->headers->response_code());
[email protected]0b0bf032010-09-21 18:08:501561 EXPECT_EQ(5, response->headers->GetContentLength());
[email protected]394816e92010-08-03 07:38:591562 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
1563
1564 // The password prompt info should not be set.
1565 EXPECT_TRUE(response->auth_challenge.get() == NULL);
[email protected]0b0bf032010-09-21 18:08:501566
1567 trans.reset();
1568 session->FlushSocketPools();
[email protected]394816e92010-08-03 07:38:591569}
1570
[email protected]11203f012009-11-12 23:02:311571// Test the request-challenge-retry sequence for basic auth, over a keep-alive
[email protected]2d2697f92009-02-18 21:00:321572// proxy connection, when setting up an SSL tunnel.
1573TEST_F(HttpNetworkTransactionTest, BasicAuthProxyKeepAlive) {
1574 // Configure against proxy server "myproxy:70".
[email protected]81cdfcd2010-10-16 00:49:001575 SessionDependencies session_deps(ProxyService::CreateFixed("myproxy:70"));
[email protected]a7ea8832010-07-12 17:54:541576 CapturingBoundNetLog log(CapturingNetLog::kUnbounded);
1577 session_deps.net_log = log.bound().net_log();
[email protected]228ff742009-06-05 01:19:591578 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]2d2697f92009-02-18 21:00:321579
[email protected]5695b8c2009-09-30 21:36:431580 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]2d2697f92009-02-18 21:00:321581
[email protected]1c773ea12009-04-28 19:58:421582 HttpRequestInfo request;
[email protected]2d2697f92009-02-18 21:00:321583 request.method = "GET";
1584 request.url = GURL("https://www.google.com/");
[email protected]861fcd52009-08-26 02:33:461585 // Ensure that proxy authentication is attempted even
1586 // when the no authentication data flag is set.
1587 request.load_flags = net::LOAD_DO_NOT_SEND_AUTH_DATA;
[email protected]2d2697f92009-02-18 21:00:321588
1589 // Since we have proxy, should try to establish tunnel.
1590 MockWrite data_writes1[] = {
1591 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
[email protected]e44de5d2009-06-05 20:12:451592 "Host: www.google.com\r\n"
1593 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]2d2697f92009-02-18 21:00:321594
1595 // After calling trans->RestartWithAuth(), this is the request we should
1596 // be issuing -- the final header line contains the credentials.
1597 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
1598 "Host: www.google.com\r\n"
[email protected]e44de5d2009-06-05 20:12:451599 "Proxy-Connection: keep-alive\r\n"
[email protected]2d2697f92009-02-18 21:00:321600 "Proxy-Authorization: Basic Zm9vOmJheg==\r\n\r\n"),
1601 };
1602
1603 // The proxy responds to the connect with a 407, using a persistent
1604 // connection.
1605 MockRead data_reads1[] = {
1606 // No credentials.
1607 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
1608 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1609 MockRead("Content-Length: 10\r\n\r\n"),
1610 MockRead("0123456789"),
1611
1612 // Wrong credentials (wrong password).
1613 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
1614 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1615 MockRead("Content-Length: 10\r\n\r\n"),
1616 // No response body because the test stops reading here.
[email protected]1c773ea12009-04-28 19:58:421617 MockRead(false, ERR_UNEXPECTED), // Should not be reached.
[email protected]2d2697f92009-02-18 21:00:321618 };
1619
[email protected]31a2bfe2010-02-09 08:03:391620 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
1621 data_writes1, arraysize(data_writes1));
[email protected]5ecc992a42009-11-11 01:41:591622 session_deps.socket_factory.AddSocketDataProvider(&data1);
[email protected]2d2697f92009-02-18 21:00:321623
1624 TestCompletionCallback callback1;
1625
[email protected]dbb83db2010-05-11 18:13:391626 int rv = trans->Start(&request, &callback1, log.bound());
[email protected]1c773ea12009-04-28 19:58:421627 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:321628
1629 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421630 EXPECT_EQ(OK, rv);
[email protected]dbb83db2010-05-11 18:13:391631 size_t pos = ExpectLogContainsSomewhere(
1632 log.entries(), 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
1633 NetLog::PHASE_NONE);
1634 ExpectLogContainsSomewhere(
1635 log.entries(), pos,
1636 NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
1637 NetLog::PHASE_NONE);
[email protected]2d2697f92009-02-18 21:00:321638
[email protected]1c773ea12009-04-28 19:58:421639 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]2d2697f92009-02-18 21:00:321640 EXPECT_FALSE(response == NULL);
1641
1642 EXPECT_TRUE(response->headers->IsKeepAlive());
1643 EXPECT_EQ(407, response->headers->response_code());
1644 EXPECT_EQ(10, response->headers->GetContentLength());
[email protected]1c773ea12009-04-28 19:58:421645 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
[email protected]2d2697f92009-02-18 21:00:321646
1647 // The password prompt info should have been set in response->auth_challenge.
1648 EXPECT_FALSE(response->auth_challenge.get() == NULL);
1649
[email protected]71e4573a2009-05-21 22:03:001650 EXPECT_EQ(L"myproxy:70", response->auth_challenge->host_and_port);
[email protected]2d2697f92009-02-18 21:00:321651 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
1652 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
1653
1654 TestCompletionCallback callback2;
1655
1656 // Wrong password (should be "bar").
[email protected]13c8a092010-07-29 06:15:441657 rv = trans->RestartWithAuth(kFoo, kBaz, &callback2);
[email protected]1c773ea12009-04-28 19:58:421658 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:321659
1660 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421661 EXPECT_EQ(OK, rv);
[email protected]2d2697f92009-02-18 21:00:321662
1663 response = trans->GetResponseInfo();
1664 EXPECT_FALSE(response == NULL);
1665
1666 EXPECT_TRUE(response->headers->IsKeepAlive());
1667 EXPECT_EQ(407, response->headers->response_code());
1668 EXPECT_EQ(10, response->headers->GetContentLength());
[email protected]1c773ea12009-04-28 19:58:421669 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
[email protected]2d2697f92009-02-18 21:00:321670
1671 // The password prompt info should have been set in response->auth_challenge.
1672 EXPECT_FALSE(response->auth_challenge.get() == NULL);
1673
[email protected]71e4573a2009-05-21 22:03:001674 EXPECT_EQ(L"myproxy:70", response->auth_challenge->host_and_port);
[email protected]2d2697f92009-02-18 21:00:321675 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
1676 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
[email protected]e772db3f2010-07-12 18:11:131677
[email protected]e60e47a2010-07-14 03:37:181678 // Flush the idle socket before the NetLog and HttpNetworkTransaction go
1679 // out of scope.
1680 session->FlushSocketPools();
[email protected]2d2697f92009-02-18 21:00:321681}
1682
[email protected]a8e9b162009-03-12 00:06:441683// Test that we don't read the response body when we fail to establish a tunnel,
1684// even if the user cancels the proxy's auth attempt.
1685TEST_F(HttpNetworkTransactionTest, BasicAuthProxyCancelTunnel) {
1686 // Configure against proxy server "myproxy:70".
[email protected]81cdfcd2010-10-16 00:49:001687 SessionDependencies session_deps(ProxyService::CreateFixed("myproxy:70"));
[email protected]a8e9b162009-03-12 00:06:441688
[email protected]e44de5d2009-06-05 20:12:451689 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]a8e9b162009-03-12 00:06:441690
[email protected]5695b8c2009-09-30 21:36:431691 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]a8e9b162009-03-12 00:06:441692
[email protected]1c773ea12009-04-28 19:58:421693 HttpRequestInfo request;
[email protected]a8e9b162009-03-12 00:06:441694 request.method = "GET";
1695 request.url = GURL("https://www.google.com/");
1696 request.load_flags = 0;
1697
1698 // Since we have proxy, should try to establish tunnel.
1699 MockWrite data_writes[] = {
1700 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
[email protected]e44de5d2009-06-05 20:12:451701 "Host: www.google.com\r\n"
1702 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]a8e9b162009-03-12 00:06:441703 };
1704
1705 // The proxy responds to the connect with a 407.
1706 MockRead data_reads[] = {
1707 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
1708 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1709 MockRead("Content-Length: 10\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:421710 MockRead(false, ERR_UNEXPECTED), // Should not be reached.
[email protected]a8e9b162009-03-12 00:06:441711 };
1712
[email protected]31a2bfe2010-02-09 08:03:391713 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
1714 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:591715 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]a8e9b162009-03-12 00:06:441716
1717 TestCompletionCallback callback;
1718
[email protected]5a1d7ca2010-04-28 20:12:271719 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:421720 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]a8e9b162009-03-12 00:06:441721
1722 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421723 EXPECT_EQ(OK, rv);
[email protected]a8e9b162009-03-12 00:06:441724
[email protected]1c773ea12009-04-28 19:58:421725 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]a8e9b162009-03-12 00:06:441726 EXPECT_FALSE(response == NULL);
1727
1728 EXPECT_TRUE(response->headers->IsKeepAlive());
1729 EXPECT_EQ(407, response->headers->response_code());
1730 EXPECT_EQ(10, response->headers->GetContentLength());
[email protected]1c773ea12009-04-28 19:58:421731 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
[email protected]a8e9b162009-03-12 00:06:441732
1733 std::string response_data;
1734 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:421735 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED, rv);
[email protected]e60e47a2010-07-14 03:37:181736
1737 // Flush the idle socket before the HttpNetworkTransaction goes out of scope.
1738 session->FlushSocketPools();
[email protected]a8e9b162009-03-12 00:06:441739}
1740
[email protected]8fdbcd22010-05-05 02:54:521741// Test when a server (non-proxy) returns a 407 (proxy-authenticate).
1742// The request should fail with ERR_UNEXPECTED_PROXY_AUTH.
1743TEST_F(HttpNetworkTransactionTest, UnexpectedProxyAuth) {
1744 // We are using a DIRECT connection (i.e. no proxy) for this session.
1745 SessionDependencies session_deps;
1746 scoped_ptr<HttpTransaction> trans(
1747 new HttpNetworkTransaction(CreateSession(&session_deps)));
1748
1749 HttpRequestInfo request;
1750 request.method = "GET";
1751 request.url = GURL("http://www.google.com/");
1752 request.load_flags = 0;
1753
1754 MockWrite data_writes1[] = {
1755 MockWrite("GET / HTTP/1.1\r\n"
1756 "Host: www.google.com\r\n"
1757 "Connection: keep-alive\r\n\r\n"),
1758 };
1759
1760 MockRead data_reads1[] = {
1761 MockRead("HTTP/1.0 407 Proxy Auth required\r\n"),
1762 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1763 // Large content-length -- won't matter, as connection will be reset.
1764 MockRead("Content-Length: 10000\r\n\r\n"),
1765 MockRead(false, ERR_FAILED),
1766 };
1767
1768 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
1769 data_writes1, arraysize(data_writes1));
1770 session_deps.socket_factory.AddSocketDataProvider(&data1);
1771
1772 TestCompletionCallback callback;
1773
1774 int rv = trans->Start(&request, &callback, BoundNetLog());
1775 EXPECT_EQ(ERR_IO_PENDING, rv);
1776
1777 rv = callback.WaitForResult();
1778 EXPECT_EQ(ERR_UNEXPECTED_PROXY_AUTH, rv);
1779}
1780
[email protected]7a67a8152010-11-05 18:31:101781// Tests when an HTTPS server (non-proxy) returns a 407 (proxy-authentication)
1782// through a non-authenticating proxy. The request should fail with
1783// ERR_UNEXPECTED_PROXY_AUTH.
1784// Note that it is impossible to detect if an HTTP server returns a 407 through
1785// a non-authenticating proxy - there is nothing to indicate whether the
1786// response came from the proxy or the server, so it is treated as if the proxy
1787// issued the challenge.
1788TEST_F(HttpNetworkTransactionTest, HttpsServerRequestsProxyAuthThroughProxy) {
1789 SessionDependencies session_deps(ProxyService::CreateFixed("myproxy:70"));
1790 CapturingBoundNetLog log(CapturingNetLog::kUnbounded);
1791 session_deps.net_log = log.bound().net_log();
1792 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
1793
1794 HttpRequestInfo request;
1795 request.method = "GET";
1796 request.url = GURL("https://www.google.com/");
1797
1798 // Since we have proxy, should try to establish tunnel.
1799 MockWrite data_writes1[] = {
1800 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
1801 "Host: www.google.com\r\n"
1802 "Proxy-Connection: keep-alive\r\n\r\n"),
1803
1804 MockWrite("GET / HTTP/1.1\r\n"
1805 "Host: www.google.com\r\n"
1806 "Connection: keep-alive\r\n\r\n"),
1807 };
1808
1809 MockRead data_reads1[] = {
1810 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
1811
1812 MockRead("HTTP/1.1 407 Unauthorized\r\n"),
1813 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1814 MockRead("\r\n"),
1815 MockRead(false, OK),
1816 };
1817
1818 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
1819 data_writes1, arraysize(data_writes1));
1820 session_deps.socket_factory.AddSocketDataProvider(&data1);
1821 SSLSocketDataProvider ssl(true, OK);
1822 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
1823
1824 TestCompletionCallback callback1;
1825
1826 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
1827
1828 int rv = trans->Start(&request, &callback1, log.bound());
1829 EXPECT_EQ(ERR_IO_PENDING, rv);
1830
1831 rv = callback1.WaitForResult();
1832 EXPECT_EQ(ERR_UNEXPECTED_PROXY_AUTH, rv);
1833 size_t pos = ExpectLogContainsSomewhere(
1834 log.entries(), 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
1835 NetLog::PHASE_NONE);
1836 ExpectLogContainsSomewhere(
1837 log.entries(), pos,
1838 NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
1839 NetLog::PHASE_NONE);
1840}
[email protected]2df19bb2010-08-25 20:13:461841
1842// Test a simple get through an HTTPS Proxy.
1843TEST_F(HttpNetworkTransactionTest, HttpsProxyGet) {
1844 // Configure against https proxy server "proxy:70".
[email protected]81cdfcd2010-10-16 00:49:001845 SessionDependencies session_deps(ProxyService::CreateFixed("https://proxy:70"));
[email protected]2df19bb2010-08-25 20:13:461846 CapturingBoundNetLog log(CapturingNetLog::kUnbounded);
1847 session_deps.net_log = log.bound().net_log();
1848 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
1849
[email protected]2df19bb2010-08-25 20:13:461850 HttpRequestInfo request;
1851 request.method = "GET";
1852 request.url = GURL("http://www.google.com/");
1853
1854 // Since we have proxy, should use full url
1855 MockWrite data_writes1[] = {
1856 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
1857 "Host: www.google.com\r\n"
1858 "Proxy-Connection: keep-alive\r\n\r\n"),
1859 };
1860
1861 MockRead data_reads1[] = {
1862 MockRead("HTTP/1.1 200 OK\r\n"),
1863 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1864 MockRead("Content-Length: 100\r\n\r\n"),
1865 MockRead(false, OK),
1866 };
1867
1868 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
1869 data_writes1, arraysize(data_writes1));
1870 session_deps.socket_factory.AddSocketDataProvider(&data1);
1871 SSLSocketDataProvider ssl(true, OK);
1872 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
1873
1874 TestCompletionCallback callback1;
1875
[email protected]0b0bf032010-09-21 18:08:501876 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
1877
[email protected]2df19bb2010-08-25 20:13:461878 int rv = trans->Start(&request, &callback1, log.bound());
1879 EXPECT_EQ(ERR_IO_PENDING, rv);
1880
1881 rv = callback1.WaitForResult();
1882 EXPECT_EQ(OK, rv);
1883
1884 const HttpResponseInfo* response = trans->GetResponseInfo();
1885 ASSERT_FALSE(response == NULL);
1886
1887 EXPECT_TRUE(response->headers->IsKeepAlive());
1888 EXPECT_EQ(200, response->headers->response_code());
1889 EXPECT_EQ(100, response->headers->GetContentLength());
1890 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
1891
1892 // The password prompt info should not be set.
1893 EXPECT_TRUE(response->auth_challenge.get() == NULL);
1894}
1895
[email protected]7642b5ae2010-09-01 20:55:171896// Test a SPDY get through an HTTPS Proxy.
1897TEST_F(HttpNetworkTransactionTest, HttpsProxySpdyGet) {
1898 // Configure against https proxy server "proxy:70".
[email protected]81cdfcd2010-10-16 00:49:001899 SessionDependencies session_deps(ProxyService::CreateFixed("https://proxy:70"));
[email protected]7642b5ae2010-09-01 20:55:171900 CapturingBoundNetLog log(CapturingNetLog::kUnbounded);
1901 session_deps.net_log = log.bound().net_log();
1902 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
1903
[email protected]7642b5ae2010-09-01 20:55:171904 HttpRequestInfo request;
1905 request.method = "GET";
1906 request.url = GURL("http://www.google.com/");
1907 request.load_flags = 0;
1908
1909 // fetch http://www.google.com/ via SPDY
1910 scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST,
1911 false));
1912 MockWrite spdy_writes[] = { CreateMockWrite(*req) };
1913
1914 scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1));
1915 scoped_ptr<spdy::SpdyFrame> data(ConstructSpdyBodyFrame(1, true));
1916 MockRead spdy_reads[] = {
1917 CreateMockRead(*resp),
1918 CreateMockRead(*data),
1919 MockRead(true, 0, 0),
1920 };
1921
1922 scoped_refptr<DelayedSocketData> spdy_data(
1923 new DelayedSocketData(
1924 1, // wait for one write to finish before reading.
1925 spdy_reads, arraysize(spdy_reads),
1926 spdy_writes, arraysize(spdy_writes)));
1927 session_deps.socket_factory.AddSocketDataProvider(spdy_data);
1928
1929 SSLSocketDataProvider ssl(true, OK);
1930 ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
1931 ssl.next_proto = "spdy/2";
1932 ssl.was_npn_negotiated = true;
1933 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
1934
1935 TestCompletionCallback callback1;
1936
[email protected]0b0bf032010-09-21 18:08:501937 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
1938
[email protected]7642b5ae2010-09-01 20:55:171939 int rv = trans->Start(&request, &callback1, log.bound());
1940 EXPECT_EQ(ERR_IO_PENDING, rv);
1941
1942 rv = callback1.WaitForResult();
1943 EXPECT_EQ(OK, rv);
1944
1945 const HttpResponseInfo* response = trans->GetResponseInfo();
1946 ASSERT_TRUE(response != NULL);
1947 ASSERT_TRUE(response->headers != NULL);
1948 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
1949
1950 std::string response_data;
1951 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
1952 EXPECT_EQ(net::kUploadData, response_data);
1953}
1954
[email protected]dc7bd1c52010-11-12 00:01:131955// Test a SPDY get through an HTTPS Proxy.
1956TEST_F(HttpNetworkTransactionTest, HttpsProxySpdyGetWithProxyAuth) {
1957 // Configure against https proxy server "proxy:70".
1958 SessionDependencies session_deps(
1959 ProxyService::CreateFixed("https://proxy:70"));
1960 CapturingBoundNetLog log(CapturingNetLog::kUnbounded);
1961 session_deps.net_log = log.bound().net_log();
1962 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
1963
1964 HttpRequestInfo request;
1965 request.method = "GET";
1966 request.url = GURL("http://www.google.com/");
1967 request.load_flags = 0;
1968
1969 // The first request will be a bare GET, the second request will be a
1970 // GET with a Proxy-Authorization header.
1971 scoped_ptr<spdy::SpdyFrame> req_get(
1972 ConstructSpdyGet(NULL, 0, false, 1, LOWEST, false));
1973 const char* const kExtraAuthorizationHeaders[] = {
1974 "proxy-authorization",
1975 "Basic Zm9vOmJhcg==",
1976 };
1977 scoped_ptr<spdy::SpdyFrame> req_get_authorization(
1978 ConstructSpdyGet(
1979 kExtraAuthorizationHeaders, arraysize(kExtraAuthorizationHeaders)/2,
1980 false, 3, LOWEST, false));
1981 MockWrite spdy_writes[] = {
1982 CreateMockWrite(*req_get, 1),
1983 CreateMockWrite(*req_get_authorization, 4),
1984 };
1985
1986 // The first response is a 407 proxy authentication challenge, and the second
1987 // response will be a 200 response since the second request includes a valid
1988 // Authorization header.
1989 const char* const kExtraAuthenticationHeaders[] = {
1990 "Proxy-Authenticate",
1991 "Basic realm=\"MyRealm1\""
1992 };
1993 scoped_ptr<spdy::SpdyFrame> resp_authentication(
1994 ConstructSpdySynReplyError(
1995 "407 Proxy Authentication Required",
1996 kExtraAuthenticationHeaders, arraysize(kExtraAuthenticationHeaders)/2,
1997 1));
1998 scoped_ptr<spdy::SpdyFrame> body_authentication(
1999 ConstructSpdyBodyFrame(1, true));
2000 scoped_ptr<spdy::SpdyFrame> resp_data(ConstructSpdyGetSynReply(NULL, 0, 3));
2001 scoped_ptr<spdy::SpdyFrame> body_data(ConstructSpdyBodyFrame(3, true));
2002 MockRead spdy_reads[] = {
2003 CreateMockRead(*resp_authentication, 2),
2004 CreateMockRead(*body_authentication, 3),
2005 CreateMockRead(*resp_data, 5),
2006 CreateMockRead(*body_data, 6),
2007 MockRead(true, 0, 7),
2008 };
2009
2010 scoped_refptr<OrderedSocketData> data(
2011 new OrderedSocketData(spdy_reads, arraysize(spdy_reads),
2012 spdy_writes, arraysize(spdy_writes)));
2013 session_deps.socket_factory.AddSocketDataProvider(data);
2014
2015 SSLSocketDataProvider ssl(true, OK);
2016 ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
2017 ssl.next_proto = "spdy/2";
2018 ssl.was_npn_negotiated = true;
2019 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
2020
2021 TestCompletionCallback callback1;
2022
2023 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
2024
2025 int rv = trans->Start(&request, &callback1, log.bound());
2026 EXPECT_EQ(ERR_IO_PENDING, rv);
2027
2028 rv = callback1.WaitForResult();
2029 EXPECT_EQ(OK, rv);
2030
2031 const HttpResponseInfo* const response = trans->GetResponseInfo();
2032
2033 ASSERT_TRUE(response != NULL);
2034 ASSERT_TRUE(response->headers != NULL);
2035 EXPECT_EQ(407, response->headers->response_code());
2036 EXPECT_TRUE(response->was_fetched_via_spdy);
2037
2038 // The password prompt info should have been set in response->auth_challenge.
2039 ASSERT_TRUE(response->auth_challenge.get() != NULL);
2040 EXPECT_TRUE(response->auth_challenge->is_proxy);
2041 EXPECT_EQ(L"proxy:70", response->auth_challenge->host_and_port);
2042 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
2043 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
2044
2045 TestCompletionCallback callback2;
2046
2047 rv = trans->RestartWithAuth(kFoo, kBar, &callback2);
2048 EXPECT_EQ(ERR_IO_PENDING, rv);
2049
2050 rv = callback2.WaitForResult();
2051 EXPECT_EQ(OK, rv);
2052
2053 const HttpResponseInfo* const response_restart = trans->GetResponseInfo();
2054
2055 ASSERT_TRUE(response_restart != NULL);
2056 ASSERT_TRUE(response_restart->headers != NULL);
2057 EXPECT_EQ(200, response_restart->headers->response_code());
2058 // The password prompt info should not be set.
2059 EXPECT_TRUE(response_restart->auth_challenge.get() == NULL);
2060}
2061
[email protected]d9da5fe2010-10-13 22:37:162062// Test a SPDY CONNECT through an HTTPS Proxy to an HTTPS (non-SPDY) Server.
2063TEST_F(HttpNetworkTransactionTest, HttpsProxySpdyConnectHttps) {
2064 // Configure against https proxy server "proxy:70".
[email protected]81cdfcd2010-10-16 00:49:002065 SessionDependencies session_deps(ProxyService::CreateFixed("https://proxy:70"));
[email protected]d9da5fe2010-10-13 22:37:162066 CapturingBoundNetLog log(CapturingNetLog::kUnbounded);
2067 session_deps.net_log = log.bound().net_log();
2068 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
2069
2070 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
2071
2072 HttpRequestInfo request;
2073 request.method = "GET";
2074 request.url = GURL("https://www.google.com/");
2075 request.load_flags = 0;
2076
2077 // CONNECT to www.google.com:443 via SPDY
2078 scoped_ptr<spdy::SpdyFrame> connect(ConstructSpdyConnect(NULL, 0, 1));
2079 // fetch https://www.google.com/ via HTTP
2080
2081 const char get[] = "GET / HTTP/1.1\r\n"
2082 "Host: www.google.com\r\n"
2083 "Connection: keep-alive\r\n\r\n";
2084 scoped_ptr<spdy::SpdyFrame> wrapped_get(
2085 ConstructSpdyBodyFrame(1, get, strlen(get), false));
2086 MockWrite spdy_writes[] = {
2087 CreateMockWrite(*connect, 1),
2088 CreateMockWrite(*wrapped_get, 3)
2089 };
2090
2091 scoped_ptr<spdy::SpdyFrame> conn_resp(ConstructSpdyGetSynReply(NULL, 0, 1));
2092 const char resp[] = "HTTP/1.1 200 OK\r\n"
2093 "Content-Length: 10\r\n\r\n";
2094
2095 scoped_ptr<spdy::SpdyFrame> wrapped_get_resp(
2096 ConstructSpdyBodyFrame(1, resp, strlen(resp), false));
2097 scoped_ptr<spdy::SpdyFrame> wrapped_body(
2098 ConstructSpdyBodyFrame(1, "1234567890", 10, false));
2099 MockRead spdy_reads[] = {
2100 CreateMockRead(*conn_resp, 2, true),
2101 CreateMockRead(*wrapped_get_resp, 4, true),
2102 CreateMockRead(*wrapped_body, 5, true),
2103 CreateMockRead(*wrapped_body, 6, true),
2104 MockRead(true, 0, 7),
2105 };
2106
2107 scoped_refptr<OrderedSocketData> spdy_data(
2108 new OrderedSocketData(
2109 spdy_reads, arraysize(spdy_reads),
2110 spdy_writes, arraysize(spdy_writes)));
2111 session_deps.socket_factory.AddSocketDataProvider(spdy_data);
2112
2113 SSLSocketDataProvider ssl(true, OK);
2114 ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
2115 ssl.next_proto = "spdy/2";
2116 ssl.was_npn_negotiated = true;
2117 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
2118 SSLSocketDataProvider ssl2(true, OK);
2119 ssl2.was_npn_negotiated = false;
2120 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl2);
2121
2122 TestCompletionCallback callback1;
2123
2124 int rv = trans->Start(&request, &callback1, log.bound());
2125 EXPECT_EQ(ERR_IO_PENDING, rv);
2126
2127 rv = callback1.WaitForResult();
2128 EXPECT_EQ(OK, rv);
2129
2130 const HttpResponseInfo* response = trans->GetResponseInfo();
2131 ASSERT_TRUE(response != NULL);
2132 ASSERT_TRUE(response->headers != NULL);
2133 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
2134
2135 std::string response_data;
2136 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
2137 EXPECT_EQ("1234567890", response_data);
2138}
2139
2140// Test a SPDY CONNECT through an HTTPS Proxy to a SPDY server.
2141TEST_F(HttpNetworkTransactionTest, HttpsProxySpdyConnectSpdy) {
2142 // Configure against https proxy server "proxy:70".
[email protected]81cdfcd2010-10-16 00:49:002143 SessionDependencies session_deps(ProxyService::CreateFixed("https://proxy:70"));
[email protected]d9da5fe2010-10-13 22:37:162144 CapturingBoundNetLog log(CapturingNetLog::kUnbounded);
2145 session_deps.net_log = log.bound().net_log();
2146 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
2147
2148 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
2149
2150 HttpRequestInfo request;
2151 request.method = "GET";
2152 request.url = GURL("https://www.google.com/");
2153 request.load_flags = 0;
2154
2155 // CONNECT to www.google.com:443 via SPDY
2156 scoped_ptr<spdy::SpdyFrame> connect(ConstructSpdyConnect(NULL, 0, 1));
2157 // fetch https://www.google.com/ via SPDY
2158 const char* const kMyUrl = "https://www.google.com/";
2159 scoped_ptr<spdy::SpdyFrame> get(ConstructSpdyGet(kMyUrl, false, 1, LOWEST));
2160 scoped_ptr<spdy::SpdyFrame> wrapped_get(ConstructWrappedSpdyFrame(get, 1));
2161 MockWrite spdy_writes[] = {
2162 CreateMockWrite(*connect, 1),
2163 CreateMockWrite(*wrapped_get, 3)
2164 };
2165
2166 scoped_ptr<spdy::SpdyFrame> conn_resp(ConstructSpdyGetSynReply(NULL, 0, 1));
2167 scoped_ptr<spdy::SpdyFrame> get_resp(ConstructSpdyGetSynReply(NULL, 0, 1));
2168 scoped_ptr<spdy::SpdyFrame> wrapped_get_resp(
2169 ConstructWrappedSpdyFrame(get_resp, 1));
2170 scoped_ptr<spdy::SpdyFrame> body(ConstructSpdyBodyFrame(1, true));
2171 scoped_ptr<spdy::SpdyFrame> wrapped_body(ConstructWrappedSpdyFrame(body, 1));
2172 MockRead spdy_reads[] = {
2173 CreateMockRead(*conn_resp, 2, true),
2174 CreateMockRead(*wrapped_get_resp, 4, true),
2175 CreateMockRead(*wrapped_body, 5, true),
2176 MockRead(true, 0, 1),
2177 };
2178
2179 scoped_refptr<OrderedSocketData> spdy_data(
2180 new OrderedSocketData(
2181 spdy_reads, arraysize(spdy_reads),
2182 spdy_writes, arraysize(spdy_writes)));
2183 session_deps.socket_factory.AddSocketDataProvider(spdy_data);
2184
2185 SSLSocketDataProvider ssl(true, OK);
2186 ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
2187 ssl.next_proto = "spdy/2";
2188 ssl.was_npn_negotiated = true;
2189 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
2190 SSLSocketDataProvider ssl2(true, OK);
2191 ssl2.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
2192 ssl2.next_proto = "spdy/2";
2193 ssl2.was_npn_negotiated = true;
2194 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl2);
2195
2196 TestCompletionCallback callback1;
2197
2198 int rv = trans->Start(&request, &callback1, log.bound());
2199 EXPECT_EQ(ERR_IO_PENDING, rv);
2200
2201 rv = callback1.WaitForResult();
2202 EXPECT_EQ(OK, rv);
2203
2204 const HttpResponseInfo* response = trans->GetResponseInfo();
2205 ASSERT_TRUE(response != NULL);
2206 ASSERT_TRUE(response->headers != NULL);
2207 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
2208
2209 std::string response_data;
2210 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
2211 EXPECT_EQ(net::kUploadData, response_data);
2212}
2213
2214// Test a SPDY CONNECT failure through an HTTPS Proxy.
2215TEST_F(HttpNetworkTransactionTest, HttpsProxySpdyConnectFailure) {
2216 // Configure against https proxy server "proxy:70".
[email protected]81cdfcd2010-10-16 00:49:002217 SessionDependencies session_deps(ProxyService::CreateFixed("https://proxy:70"));
[email protected]d9da5fe2010-10-13 22:37:162218 CapturingBoundNetLog log(CapturingNetLog::kUnbounded);
2219 session_deps.net_log = log.bound().net_log();
2220 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
2221
2222 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
2223
2224 HttpRequestInfo request;
2225 request.method = "GET";
2226 request.url = GURL("https://www.google.com/");
2227 request.load_flags = 0;
2228
2229 // CONNECT to www.google.com:443 via SPDY
2230 scoped_ptr<spdy::SpdyFrame> connect(ConstructSpdyConnect(NULL, 0, 1));
2231 scoped_ptr<spdy::SpdyFrame> get(ConstructSpdyRstStream(1, spdy::CANCEL));
2232
2233 MockWrite spdy_writes[] = {
2234 CreateMockWrite(*connect, 1),
2235 CreateMockWrite(*get, 3),
2236 };
2237
2238 scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdySynReplyError(1));
2239 scoped_ptr<spdy::SpdyFrame> data(ConstructSpdyBodyFrame(1, true));
2240 MockRead spdy_reads[] = {
2241 CreateMockRead(*resp, 2, true),
2242 MockRead(true, 0, 4),
2243 };
2244
2245 scoped_refptr<OrderedSocketData> spdy_data(
2246 new OrderedSocketData(
2247 spdy_reads, arraysize(spdy_reads),
2248 spdy_writes, arraysize(spdy_writes)));
2249 session_deps.socket_factory.AddSocketDataProvider(spdy_data);
2250
2251 SSLSocketDataProvider ssl(true, OK);
2252 ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
2253 ssl.next_proto = "spdy/2";
2254 ssl.was_npn_negotiated = true;
2255 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
2256 SSLSocketDataProvider ssl2(true, OK);
2257 ssl2.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
2258 ssl2.next_proto = "spdy/2";
2259 ssl2.was_npn_negotiated = true;
2260 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl2);
2261
2262 TestCompletionCallback callback1;
2263
2264 int rv = trans->Start(&request, &callback1, log.bound());
2265 EXPECT_EQ(ERR_IO_PENDING, rv);
2266
2267 rv = callback1.WaitForResult();
2268 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED, rv);
2269
2270 const HttpResponseInfo* response = trans->GetResponseInfo();
2271 ASSERT_TRUE(response == NULL);
2272}
2273
[email protected]2df19bb2010-08-25 20:13:462274// Test the challenge-response-retry sequence through an HTTPS Proxy
2275TEST_F(HttpNetworkTransactionTest, HttpsProxyAuthRetry) {
2276 // Configure against https proxy server "proxy:70".
[email protected]81cdfcd2010-10-16 00:49:002277 SessionDependencies session_deps(ProxyService::CreateFixed("https://proxy:70"));
[email protected]2df19bb2010-08-25 20:13:462278 CapturingBoundNetLog log(CapturingNetLog::kUnbounded);
2279 session_deps.net_log = log.bound().net_log();
2280 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
2281
[email protected]2df19bb2010-08-25 20:13:462282 HttpRequestInfo request;
2283 request.method = "GET";
2284 request.url = GURL("http://www.google.com/");
2285 // when the no authentication data flag is set.
2286 request.load_flags = net::LOAD_DO_NOT_SEND_AUTH_DATA;
2287
2288 // Since we have proxy, should use full url
2289 MockWrite data_writes1[] = {
2290 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
2291 "Host: www.google.com\r\n"
2292 "Proxy-Connection: keep-alive\r\n\r\n"),
2293
2294 // After calling trans->RestartWithAuth(), this is the request we should
2295 // be issuing -- the final header line contains the credentials.
2296 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
2297 "Host: www.google.com\r\n"
2298 "Proxy-Connection: keep-alive\r\n"
2299 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2300 };
2301
2302 // The proxy responds to the GET with a 407, using a persistent
2303 // connection.
2304 MockRead data_reads1[] = {
2305 // No credentials.
2306 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
2307 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2308 MockRead("Proxy-Connection: keep-alive\r\n"),
2309 MockRead("Content-Length: 0\r\n\r\n"),
2310
2311 MockRead("HTTP/1.1 200 OK\r\n"),
2312 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2313 MockRead("Content-Length: 100\r\n\r\n"),
2314 MockRead(false, OK),
2315 };
2316
2317 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2318 data_writes1, arraysize(data_writes1));
2319 session_deps.socket_factory.AddSocketDataProvider(&data1);
2320 SSLSocketDataProvider ssl(true, OK);
2321 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
2322
2323 TestCompletionCallback callback1;
2324
[email protected]0b0bf032010-09-21 18:08:502325 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
2326
[email protected]2df19bb2010-08-25 20:13:462327 int rv = trans->Start(&request, &callback1, log.bound());
2328 EXPECT_EQ(ERR_IO_PENDING, rv);
2329
2330 rv = callback1.WaitForResult();
2331 EXPECT_EQ(OK, rv);
2332
2333 const HttpResponseInfo* response = trans->GetResponseInfo();
2334 ASSERT_FALSE(response == NULL);
2335
2336 EXPECT_EQ(407, response->headers->response_code());
2337 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
2338
2339 // The password prompt info should have been set in response->auth_challenge.
2340 ASSERT_FALSE(response->auth_challenge.get() == NULL);
2341
2342 EXPECT_EQ(L"proxy:70", response->auth_challenge->host_and_port);
2343 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
2344 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
2345
2346 TestCompletionCallback callback2;
2347
2348 rv = trans->RestartWithAuth(kFoo, kBar, &callback2);
2349 EXPECT_EQ(ERR_IO_PENDING, rv);
2350
2351 rv = callback2.WaitForResult();
2352 EXPECT_EQ(OK, rv);
2353
2354 response = trans->GetResponseInfo();
2355 ASSERT_FALSE(response == NULL);
2356
2357 EXPECT_TRUE(response->headers->IsKeepAlive());
2358 EXPECT_EQ(200, response->headers->response_code());
2359 EXPECT_EQ(100, response->headers->GetContentLength());
2360 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
2361
2362 // The password prompt info should not be set.
2363 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2364}
2365
[email protected]ff007e162009-05-23 09:13:152366void HttpNetworkTransactionTest::ConnectStatusHelperWithExpectedStatus(
[email protected]c744cf22009-02-27 07:28:082367 const MockRead& status, int expected_status) {
2368 // Configure against proxy server "myproxy:70".
[email protected]81cdfcd2010-10-16 00:49:002369 SessionDependencies session_deps(ProxyService::CreateFixed("myproxy:70"));
[email protected]c744cf22009-02-27 07:28:082370
[email protected]228ff742009-06-05 01:19:592371 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]c744cf22009-02-27 07:28:082372
[email protected]1c773ea12009-04-28 19:58:422373 HttpRequestInfo request;
[email protected]c744cf22009-02-27 07:28:082374 request.method = "GET";
2375 request.url = GURL("https://www.google.com/");
2376 request.load_flags = 0;
2377
2378 // Since we have proxy, should try to establish tunnel.
2379 MockWrite data_writes[] = {
2380 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
[email protected]e44de5d2009-06-05 20:12:452381 "Host: www.google.com\r\n"
2382 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]c744cf22009-02-27 07:28:082383 };
2384
2385 MockRead data_reads[] = {
2386 status,
2387 MockRead("Content-Length: 10\r\n\r\n"),
2388 // No response body because the test stops reading here.
[email protected]1c773ea12009-04-28 19:58:422389 MockRead(false, ERR_UNEXPECTED), // Should not be reached.
[email protected]c744cf22009-02-27 07:28:082390 };
2391
[email protected]31a2bfe2010-02-09 08:03:392392 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
2393 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:592394 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]c744cf22009-02-27 07:28:082395
2396 TestCompletionCallback callback;
2397
[email protected]0b0bf032010-09-21 18:08:502398 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
2399
[email protected]5a1d7ca2010-04-28 20:12:272400 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:422401 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]c744cf22009-02-27 07:28:082402
2403 rv = callback.WaitForResult();
2404 EXPECT_EQ(expected_status, rv);
2405}
2406
[email protected]ff007e162009-05-23 09:13:152407void HttpNetworkTransactionTest::ConnectStatusHelper(const MockRead& status) {
[email protected]c744cf22009-02-27 07:28:082408 ConnectStatusHelperWithExpectedStatus(
[email protected]1c773ea12009-04-28 19:58:422409 status, ERR_TUNNEL_CONNECTION_FAILED);
[email protected]c744cf22009-02-27 07:28:082410}
2411
2412TEST_F(HttpNetworkTransactionTest, ConnectStatus100) {
2413 ConnectStatusHelper(MockRead("HTTP/1.1 100 Continue\r\n"));
2414}
2415
2416TEST_F(HttpNetworkTransactionTest, ConnectStatus101) {
2417 ConnectStatusHelper(MockRead("HTTP/1.1 101 Switching Protocols\r\n"));
2418}
2419
2420TEST_F(HttpNetworkTransactionTest, ConnectStatus201) {
2421 ConnectStatusHelper(MockRead("HTTP/1.1 201 Created\r\n"));
2422}
2423
2424TEST_F(HttpNetworkTransactionTest, ConnectStatus202) {
2425 ConnectStatusHelper(MockRead("HTTP/1.1 202 Accepted\r\n"));
2426}
2427
2428TEST_F(HttpNetworkTransactionTest, ConnectStatus203) {
2429 ConnectStatusHelper(
2430 MockRead("HTTP/1.1 203 Non-Authoritative Information\r\n"));
2431}
2432
2433TEST_F(HttpNetworkTransactionTest, ConnectStatus204) {
2434 ConnectStatusHelper(MockRead("HTTP/1.1 204 No Content\r\n"));
2435}
2436
2437TEST_F(HttpNetworkTransactionTest, ConnectStatus205) {
2438 ConnectStatusHelper(MockRead("HTTP/1.1 205 Reset Content\r\n"));
2439}
2440
2441TEST_F(HttpNetworkTransactionTest, ConnectStatus206) {
2442 ConnectStatusHelper(MockRead("HTTP/1.1 206 Partial Content\r\n"));
2443}
2444
2445TEST_F(HttpNetworkTransactionTest, ConnectStatus300) {
2446 ConnectStatusHelper(MockRead("HTTP/1.1 300 Multiple Choices\r\n"));
2447}
2448
2449TEST_F(HttpNetworkTransactionTest, ConnectStatus301) {
2450 ConnectStatusHelper(MockRead("HTTP/1.1 301 Moved Permanently\r\n"));
2451}
2452
2453TEST_F(HttpNetworkTransactionTest, ConnectStatus302) {
2454 ConnectStatusHelper(MockRead("HTTP/1.1 302 Found\r\n"));
2455}
2456
2457TEST_F(HttpNetworkTransactionTest, ConnectStatus303) {
2458 ConnectStatusHelper(MockRead("HTTP/1.1 303 See Other\r\n"));
2459}
2460
2461TEST_F(HttpNetworkTransactionTest, ConnectStatus304) {
2462 ConnectStatusHelper(MockRead("HTTP/1.1 304 Not Modified\r\n"));
2463}
2464
2465TEST_F(HttpNetworkTransactionTest, ConnectStatus305) {
2466 ConnectStatusHelper(MockRead("HTTP/1.1 305 Use Proxy\r\n"));
2467}
2468
2469TEST_F(HttpNetworkTransactionTest, ConnectStatus306) {
2470 ConnectStatusHelper(MockRead("HTTP/1.1 306\r\n"));
2471}
2472
2473TEST_F(HttpNetworkTransactionTest, ConnectStatus307) {
2474 ConnectStatusHelper(MockRead("HTTP/1.1 307 Temporary Redirect\r\n"));
2475}
2476
2477TEST_F(HttpNetworkTransactionTest, ConnectStatus400) {
2478 ConnectStatusHelper(MockRead("HTTP/1.1 400 Bad Request\r\n"));
2479}
2480
2481TEST_F(HttpNetworkTransactionTest, ConnectStatus401) {
2482 ConnectStatusHelper(MockRead("HTTP/1.1 401 Unauthorized\r\n"));
2483}
2484
2485TEST_F(HttpNetworkTransactionTest, ConnectStatus402) {
2486 ConnectStatusHelper(MockRead("HTTP/1.1 402 Payment Required\r\n"));
2487}
2488
2489TEST_F(HttpNetworkTransactionTest, ConnectStatus403) {
2490 ConnectStatusHelper(MockRead("HTTP/1.1 403 Forbidden\r\n"));
2491}
2492
2493TEST_F(HttpNetworkTransactionTest, ConnectStatus404) {
2494 ConnectStatusHelper(MockRead("HTTP/1.1 404 Not Found\r\n"));
2495}
2496
2497TEST_F(HttpNetworkTransactionTest, ConnectStatus405) {
2498 ConnectStatusHelper(MockRead("HTTP/1.1 405 Method Not Allowed\r\n"));
2499}
2500
2501TEST_F(HttpNetworkTransactionTest, ConnectStatus406) {
2502 ConnectStatusHelper(MockRead("HTTP/1.1 406 Not Acceptable\r\n"));
2503}
2504
2505TEST_F(HttpNetworkTransactionTest, ConnectStatus407) {
2506 ConnectStatusHelperWithExpectedStatus(
2507 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
[email protected]a7ea8832010-07-12 17:54:542508 ERR_PROXY_AUTH_UNSUPPORTED);
[email protected]c744cf22009-02-27 07:28:082509}
2510
2511TEST_F(HttpNetworkTransactionTest, ConnectStatus408) {
2512 ConnectStatusHelper(MockRead("HTTP/1.1 408 Request Timeout\r\n"));
2513}
2514
2515TEST_F(HttpNetworkTransactionTest, ConnectStatus409) {
2516 ConnectStatusHelper(MockRead("HTTP/1.1 409 Conflict\r\n"));
2517}
2518
2519TEST_F(HttpNetworkTransactionTest, ConnectStatus410) {
2520 ConnectStatusHelper(MockRead("HTTP/1.1 410 Gone\r\n"));
2521}
2522
2523TEST_F(HttpNetworkTransactionTest, ConnectStatus411) {
2524 ConnectStatusHelper(MockRead("HTTP/1.1 411 Length Required\r\n"));
2525}
2526
2527TEST_F(HttpNetworkTransactionTest, ConnectStatus412) {
2528 ConnectStatusHelper(MockRead("HTTP/1.1 412 Precondition Failed\r\n"));
2529}
2530
2531TEST_F(HttpNetworkTransactionTest, ConnectStatus413) {
2532 ConnectStatusHelper(MockRead("HTTP/1.1 413 Request Entity Too Large\r\n"));
2533}
2534
2535TEST_F(HttpNetworkTransactionTest, ConnectStatus414) {
2536 ConnectStatusHelper(MockRead("HTTP/1.1 414 Request-URI Too Long\r\n"));
2537}
2538
2539TEST_F(HttpNetworkTransactionTest, ConnectStatus415) {
2540 ConnectStatusHelper(MockRead("HTTP/1.1 415 Unsupported Media Type\r\n"));
2541}
2542
2543TEST_F(HttpNetworkTransactionTest, ConnectStatus416) {
2544 ConnectStatusHelper(
2545 MockRead("HTTP/1.1 416 Requested Range Not Satisfiable\r\n"));
2546}
2547
2548TEST_F(HttpNetworkTransactionTest, ConnectStatus417) {
2549 ConnectStatusHelper(MockRead("HTTP/1.1 417 Expectation Failed\r\n"));
2550}
2551
2552TEST_F(HttpNetworkTransactionTest, ConnectStatus500) {
2553 ConnectStatusHelper(MockRead("HTTP/1.1 500 Internal Server Error\r\n"));
2554}
2555
2556TEST_F(HttpNetworkTransactionTest, ConnectStatus501) {
2557 ConnectStatusHelper(MockRead("HTTP/1.1 501 Not Implemented\r\n"));
2558}
2559
2560TEST_F(HttpNetworkTransactionTest, ConnectStatus502) {
2561 ConnectStatusHelper(MockRead("HTTP/1.1 502 Bad Gateway\r\n"));
2562}
2563
2564TEST_F(HttpNetworkTransactionTest, ConnectStatus503) {
2565 ConnectStatusHelper(MockRead("HTTP/1.1 503 Service Unavailable\r\n"));
2566}
2567
2568TEST_F(HttpNetworkTransactionTest, ConnectStatus504) {
2569 ConnectStatusHelper(MockRead("HTTP/1.1 504 Gateway Timeout\r\n"));
2570}
2571
2572TEST_F(HttpNetworkTransactionTest, ConnectStatus505) {
2573 ConnectStatusHelper(MockRead("HTTP/1.1 505 HTTP Version Not Supported\r\n"));
2574}
2575
[email protected]038e9a32008-10-08 22:40:162576// Test the flow when both the proxy server AND origin server require
2577// authentication. Again, this uses basic auth for both since that is
2578// the simplest to mock.
2579TEST_F(HttpNetworkTransactionTest, BasicAuthProxyThenServer) {
[email protected]81cdfcd2010-10-16 00:49:002580 SessionDependencies session_deps(ProxyService::CreateFixed("myproxy:70"));
[email protected]db8f44c2008-12-13 04:52:012581
[email protected]038e9a32008-10-08 22:40:162582 // Configure against proxy server "myproxy:70".
[email protected]1c773ea12009-04-28 19:58:422583 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(
[email protected]5695b8c2009-09-30 21:36:432584 CreateSession(&session_deps)));
[email protected]038e9a32008-10-08 22:40:162585
[email protected]1c773ea12009-04-28 19:58:422586 HttpRequestInfo request;
[email protected]038e9a32008-10-08 22:40:162587 request.method = "GET";
2588 request.url = GURL("http://www.google.com/");
2589 request.load_flags = 0;
2590
[email protected]f9ee6b52008-11-08 06:46:232591 MockWrite data_writes1[] = {
2592 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
2593 "Host: www.google.com\r\n"
2594 "Proxy-Connection: keep-alive\r\n\r\n"),
2595 };
2596
[email protected]038e9a32008-10-08 22:40:162597 MockRead data_reads1[] = {
2598 MockRead("HTTP/1.0 407 Unauthorized\r\n"),
2599 // Give a couple authenticate options (only the middle one is actually
2600 // supported).
[email protected]22927ad2009-09-21 19:56:192601 MockRead("Proxy-Authenticate: Basic invalid\r\n"), // Malformed.
[email protected]038e9a32008-10-08 22:40:162602 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2603 MockRead("Proxy-Authenticate: UNSUPPORTED realm=\"FOO\"\r\n"),
2604 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2605 // Large content-length -- won't matter, as connection will be reset.
2606 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422607 MockRead(false, ERR_FAILED),
[email protected]038e9a32008-10-08 22:40:162608 };
2609
2610 // After calling trans->RestartWithAuth() the first time, this is the
2611 // request we should be issuing -- the final header line contains the
2612 // proxy's credentials.
2613 MockWrite data_writes2[] = {
2614 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
2615 "Host: www.google.com\r\n"
2616 "Proxy-Connection: keep-alive\r\n"
2617 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2618 };
2619
2620 // Now the proxy server lets the request pass through to origin server.
2621 // The origin server responds with a 401.
2622 MockRead data_reads2[] = {
2623 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
2624 // Note: We are using the same realm-name as the proxy server. This is
2625 // completely valid, as realms are unique across hosts.
2626 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2627 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2628 MockRead("Content-Length: 2000\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422629 MockRead(false, ERR_FAILED), // Won't be reached.
[email protected]038e9a32008-10-08 22:40:162630 };
2631
2632 // After calling trans->RestartWithAuth() the second time, we should send
2633 // the credentials for both the proxy and origin server.
2634 MockWrite data_writes3[] = {
2635 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
2636 "Host: www.google.com\r\n"
2637 "Proxy-Connection: keep-alive\r\n"
2638 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n"
2639 "Authorization: Basic Zm9vMjpiYXIy\r\n\r\n"),
2640 };
2641
2642 // Lastly we get the desired content.
2643 MockRead data_reads3[] = {
2644 MockRead("HTTP/1.0 200 OK\r\n"),
2645 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2646 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422647 MockRead(false, OK),
[email protected]038e9a32008-10-08 22:40:162648 };
2649
[email protected]31a2bfe2010-02-09 08:03:392650 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2651 data_writes1, arraysize(data_writes1));
2652 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
2653 data_writes2, arraysize(data_writes2));
2654 StaticSocketDataProvider data3(data_reads3, arraysize(data_reads3),
2655 data_writes3, arraysize(data_writes3));
[email protected]5ecc992a42009-11-11 01:41:592656 session_deps.socket_factory.AddSocketDataProvider(&data1);
2657 session_deps.socket_factory.AddSocketDataProvider(&data2);
2658 session_deps.socket_factory.AddSocketDataProvider(&data3);
[email protected]038e9a32008-10-08 22:40:162659
2660 TestCompletionCallback callback1;
2661
[email protected]5a1d7ca2010-04-28 20:12:272662 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:422663 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]038e9a32008-10-08 22:40:162664
2665 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422666 EXPECT_EQ(OK, rv);
[email protected]038e9a32008-10-08 22:40:162667
[email protected]1c773ea12009-04-28 19:58:422668 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]038e9a32008-10-08 22:40:162669 EXPECT_FALSE(response == NULL);
2670
2671 // The password prompt info should have been set in response->auth_challenge.
2672 EXPECT_FALSE(response->auth_challenge.get() == NULL);
2673
[email protected]71e4573a2009-05-21 22:03:002674 EXPECT_EQ(L"myproxy:70", response->auth_challenge->host_and_port);
[email protected]038e9a32008-10-08 22:40:162675 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
2676 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
2677
2678 TestCompletionCallback callback2;
2679
[email protected]13c8a092010-07-29 06:15:442680 rv = trans->RestartWithAuth(kFoo, kBar, &callback2);
[email protected]1c773ea12009-04-28 19:58:422681 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]038e9a32008-10-08 22:40:162682
2683 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422684 EXPECT_EQ(OK, rv);
[email protected]038e9a32008-10-08 22:40:162685
2686 response = trans->GetResponseInfo();
2687 EXPECT_FALSE(response == NULL);
2688 EXPECT_FALSE(response->auth_challenge.get() == NULL);
2689
[email protected]71e4573a2009-05-21 22:03:002690 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
[email protected]038e9a32008-10-08 22:40:162691 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
2692 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
2693
2694 TestCompletionCallback callback3;
2695
[email protected]13c8a092010-07-29 06:15:442696 rv = trans->RestartWithAuth(kFoo2, kBar2, &callback3);
[email protected]1c773ea12009-04-28 19:58:422697 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]038e9a32008-10-08 22:40:162698
2699 rv = callback3.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422700 EXPECT_EQ(OK, rv);
[email protected]038e9a32008-10-08 22:40:162701
2702 response = trans->GetResponseInfo();
2703 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2704 EXPECT_EQ(100, response->headers->GetContentLength());
[email protected]038e9a32008-10-08 22:40:162705}
[email protected]4ddaf2502008-10-23 18:26:192706
[email protected]ea9dc9a2009-09-05 00:43:322707// For the NTLM implementation using SSPI, we skip the NTLM tests since we
2708// can't hook into its internals to cause it to generate predictable NTLM
2709// authorization headers.
2710#if defined(NTLM_PORTABLE)
[email protected]385a4672009-03-11 22:21:292711// The NTLM authentication unit tests were generated by capturing the HTTP
2712// requests and responses using Fiddler 2 and inspecting the generated random
2713// bytes in the debugger.
2714
2715// Enter the correct password and authenticate successfully.
2716TEST_F(HttpNetworkTransactionTest, NTLMAuth1) {
[email protected]1c773ea12009-04-28 19:58:422717 HttpAuthHandlerNTLM::ScopedProcSetter proc_setter(MockGenerateRandom1,
[email protected]2227c692010-05-04 15:36:112718 MockGetHostName);
[email protected]228ff742009-06-05 01:19:592719 SessionDependencies session_deps;
[email protected]0b0bf032010-09-21 18:08:502720 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]3f918782009-02-28 01:29:242721
[email protected]1c773ea12009-04-28 19:58:422722 HttpRequestInfo request;
[email protected]3f918782009-02-28 01:29:242723 request.method = "GET";
2724 request.url = GURL("http://172.22.68.17/kids/login.aspx");
2725 request.load_flags = 0;
2726
2727 MockWrite data_writes1[] = {
2728 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
2729 "Host: 172.22.68.17\r\n"
2730 "Connection: keep-alive\r\n\r\n"),
2731 };
2732
2733 MockRead data_reads1[] = {
2734 MockRead("HTTP/1.1 401 Access Denied\r\n"),
[email protected]aef04272010-06-28 18:03:042735 // Negotiate and NTLM are often requested together. However, we only want
2736 // to test NTLM. Since Negotiate is preferred over NTLM, we have to skip
2737 // the header that requests Negotiate for this test.
[email protected]3f918782009-02-28 01:29:242738 MockRead("WWW-Authenticate: NTLM\r\n"),
2739 MockRead("Connection: close\r\n"),
2740 MockRead("Content-Length: 42\r\n"),
[email protected]076c85082009-04-10 23:21:362741 MockRead("Content-Type: text/html\r\n\r\n"),
[email protected]3f918782009-02-28 01:29:242742 // Missing content -- won't matter, as connection will be reset.
[email protected]1c773ea12009-04-28 19:58:422743 MockRead(false, ERR_UNEXPECTED),
[email protected]3f918782009-02-28 01:29:242744 };
2745
2746 MockWrite data_writes2[] = {
[email protected]0757e7702009-03-27 04:00:222747 // After restarting with a null identity, this is the
[email protected]3f918782009-02-28 01:29:242748 // request we should be issuing -- the final header line contains a Type
2749 // 1 message.
2750 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
2751 "Host: 172.22.68.17\r\n"
2752 "Connection: keep-alive\r\n"
2753 "Authorization: NTLM "
2754 "TlRMTVNTUAABAAAAB4IIAAAAAAAAAAAAAAAAAAAAAAA=\r\n\r\n"),
2755
2756 // After calling trans->RestartWithAuth(), we should send a Type 3 message
2757 // (the credentials for the origin server). The second request continues
2758 // on the same connection.
2759 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
2760 "Host: 172.22.68.17\r\n"
2761 "Connection: keep-alive\r\n"
[email protected]385a4672009-03-11 22:21:292762 "Authorization: NTLM TlRMTVNTUAADAAAAGAAYAGgAAAAYABgAgA"
2763 "AAAAAAAABAAAAAGAAYAEAAAAAQABAAWAAAAAAAAAAAAAAABYIIAHQA"
2764 "ZQBzAHQAaQBuAGcALQBuAHQAbABtAFcAVABDAC0AVwBJAE4ANwBVKW"
2765 "Yma5xzVAAAAAAAAAAAAAAAAAAAAACH+gWcm+YsP9Tqb9zCR3WAeZZX"
2766 "ahlhx5I=\r\n\r\n"),
[email protected]3f918782009-02-28 01:29:242767 };
2768
2769 MockRead data_reads2[] = {
2770 // The origin server responds with a Type 2 message.
2771 MockRead("HTTP/1.1 401 Access Denied\r\n"),
2772 MockRead("WWW-Authenticate: NTLM "
[email protected]385a4672009-03-11 22:21:292773 "TlRMTVNTUAACAAAADAAMADgAAAAFgokCjGpMpPGlYKkAAAAAAAAAALo"
[email protected]3f918782009-02-28 01:29:242774 "AugBEAAAABQEoCgAAAA9HAE8ATwBHAEwARQACAAwARwBPAE8ARwBMAE"
2775 "UAAQAaAEEASwBFAEUAUwBBAFIAQQAtAEMATwBSAFAABAAeAGMAbwByA"
2776 "HAALgBnAG8AbwBnAGwAZQAuAGMAbwBtAAMAQABhAGsAZQBlAHMAYQBy"
2777 "AGEALQBjAG8AcgBwAC4AYQBkAC4AYwBvAHIAcAAuAGcAbwBvAGcAbAB"
2778 "lAC4AYwBvAG0ABQAeAGMAbwByAHAALgBnAG8AbwBnAGwAZQAuAGMAbw"
2779 "BtAAAAAAA=\r\n"),
2780 MockRead("Content-Length: 42\r\n"),
[email protected]076c85082009-04-10 23:21:362781 MockRead("Content-Type: text/html\r\n\r\n"),
[email protected]3f918782009-02-28 01:29:242782 MockRead("You are not authorized to view this page\r\n"),
2783
2784 // Lastly we get the desired content.
2785 MockRead("HTTP/1.1 200 OK\r\n"),
2786 MockRead("Content-Type: text/html; charset=utf-8\r\n"),
2787 MockRead("Content-Length: 13\r\n\r\n"),
2788 MockRead("Please Login\r\n"),
[email protected]1c773ea12009-04-28 19:58:422789 MockRead(false, OK),
[email protected]3f918782009-02-28 01:29:242790 };
2791
[email protected]31a2bfe2010-02-09 08:03:392792 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2793 data_writes1, arraysize(data_writes1));
2794 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
2795 data_writes2, arraysize(data_writes2));
[email protected]5ecc992a42009-11-11 01:41:592796 session_deps.socket_factory.AddSocketDataProvider(&data1);
2797 session_deps.socket_factory.AddSocketDataProvider(&data2);
[email protected]3f918782009-02-28 01:29:242798
2799 TestCompletionCallback callback1;
2800
[email protected]0b0bf032010-09-21 18:08:502801 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
2802
[email protected]5a1d7ca2010-04-28 20:12:272803 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:422804 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]3f918782009-02-28 01:29:242805
2806 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422807 EXPECT_EQ(OK, rv);
[email protected]3f918782009-02-28 01:29:242808
[email protected]0757e7702009-03-27 04:00:222809 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
2810 TestCompletionCallback callback2;
[email protected]13c8a092010-07-29 06:15:442811 rv = trans->RestartWithAuth(string16(), string16(), &callback2);
[email protected]1c773ea12009-04-28 19:58:422812 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]0757e7702009-03-27 04:00:222813 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422814 EXPECT_EQ(OK, rv);
[email protected]0757e7702009-03-27 04:00:222815 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
2816
[email protected]1c773ea12009-04-28 19:58:422817 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]aef04272010-06-28 18:03:042818 ASSERT_FALSE(response == NULL);
[email protected]3f918782009-02-28 01:29:242819
[email protected]aef04272010-06-28 18:03:042820 // The password prompt info should have been set in
2821 // response->auth_challenge.
[email protected]3f918782009-02-28 01:29:242822 EXPECT_FALSE(response->auth_challenge.get() == NULL);
2823
[email protected]71e4573a2009-05-21 22:03:002824 EXPECT_EQ(L"172.22.68.17:80", response->auth_challenge->host_and_port);
[email protected]3f918782009-02-28 01:29:242825 EXPECT_EQ(L"", response->auth_challenge->realm);
2826 EXPECT_EQ(L"ntlm", response->auth_challenge->scheme);
2827
[email protected]0757e7702009-03-27 04:00:222828 TestCompletionCallback callback3;
[email protected]3f918782009-02-28 01:29:242829
[email protected]13c8a092010-07-29 06:15:442830 rv = trans->RestartWithAuth(kTestingNTLM, kTestingNTLM, &callback3);
[email protected]1c773ea12009-04-28 19:58:422831 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]3f918782009-02-28 01:29:242832
[email protected]0757e7702009-03-27 04:00:222833 rv = callback3.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422834 EXPECT_EQ(OK, rv);
[email protected]3f918782009-02-28 01:29:242835
2836 response = trans->GetResponseInfo();
[email protected]aef04272010-06-28 18:03:042837 ASSERT_FALSE(response == NULL);
2838
[email protected]3f918782009-02-28 01:29:242839 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2840 EXPECT_EQ(13, response->headers->GetContentLength());
2841}
2842
[email protected]385a4672009-03-11 22:21:292843// Enter a wrong password, and then the correct one.
2844TEST_F(HttpNetworkTransactionTest, NTLMAuth2) {
[email protected]1c773ea12009-04-28 19:58:422845 HttpAuthHandlerNTLM::ScopedProcSetter proc_setter(MockGenerateRandom2,
[email protected]2227c692010-05-04 15:36:112846 MockGetHostName);
[email protected]228ff742009-06-05 01:19:592847 SessionDependencies session_deps;
[email protected]0b0bf032010-09-21 18:08:502848 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]385a4672009-03-11 22:21:292849
[email protected]1c773ea12009-04-28 19:58:422850 HttpRequestInfo request;
[email protected]385a4672009-03-11 22:21:292851 request.method = "GET";
2852 request.url = GURL("http://172.22.68.17/kids/login.aspx");
2853 request.load_flags = 0;
2854
2855 MockWrite data_writes1[] = {
2856 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
2857 "Host: 172.22.68.17\r\n"
2858 "Connection: keep-alive\r\n\r\n"),
2859 };
2860
2861 MockRead data_reads1[] = {
2862 MockRead("HTTP/1.1 401 Access Denied\r\n"),
[email protected]aef04272010-06-28 18:03:042863 // Negotiate and NTLM are often requested together. However, we only want
2864 // to test NTLM. Since Negotiate is preferred over NTLM, we have to skip
2865 // the header that requests Negotiate for this test.
[email protected]385a4672009-03-11 22:21:292866 MockRead("WWW-Authenticate: NTLM\r\n"),
2867 MockRead("Connection: close\r\n"),
2868 MockRead("Content-Length: 42\r\n"),
[email protected]076c85082009-04-10 23:21:362869 MockRead("Content-Type: text/html\r\n\r\n"),
[email protected]385a4672009-03-11 22:21:292870 // Missing content -- won't matter, as connection will be reset.
[email protected]1c773ea12009-04-28 19:58:422871 MockRead(false, ERR_UNEXPECTED),
[email protected]385a4672009-03-11 22:21:292872 };
2873
2874 MockWrite data_writes2[] = {
[email protected]0757e7702009-03-27 04:00:222875 // After restarting with a null identity, this is the
[email protected]385a4672009-03-11 22:21:292876 // request we should be issuing -- the final header line contains a Type
2877 // 1 message.
2878 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
2879 "Host: 172.22.68.17\r\n"
2880 "Connection: keep-alive\r\n"
2881 "Authorization: NTLM "
2882 "TlRMTVNTUAABAAAAB4IIAAAAAAAAAAAAAAAAAAAAAAA=\r\n\r\n"),
2883
2884 // After calling trans->RestartWithAuth(), we should send a Type 3 message
2885 // (the credentials for the origin server). The second request continues
2886 // on the same connection.
2887 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
2888 "Host: 172.22.68.17\r\n"
2889 "Connection: keep-alive\r\n"
2890 "Authorization: NTLM TlRMTVNTUAADAAAAGAAYAGgAAAAYABgAgA"
2891 "AAAAAAAABAAAAAGAAYAEAAAAAQABAAWAAAAAAAAAAAAAAABYIIAHQA"
2892 "ZQBzAHQAaQBuAGcALQBuAHQAbABtAFcAVABDAC0AVwBJAE4ANwCWeY"
2893 "XnSZNwoQAAAAAAAAAAAAAAAAAAAADLa34/phTTKzNTWdub+uyFleOj"
2894 "4Ww7b7E=\r\n\r\n"),
2895 };
2896
2897 MockRead data_reads2[] = {
2898 // The origin server responds with a Type 2 message.
2899 MockRead("HTTP/1.1 401 Access Denied\r\n"),
2900 MockRead("WWW-Authenticate: NTLM "
2901 "TlRMTVNTUAACAAAADAAMADgAAAAFgokCbVWUZezVGpAAAAAAAAAAALo"
2902 "AugBEAAAABQEoCgAAAA9HAE8ATwBHAEwARQACAAwARwBPAE8ARwBMAE"
2903 "UAAQAaAEEASwBFAEUAUwBBAFIAQQAtAEMATwBSAFAABAAeAGMAbwByA"
2904 "HAALgBnAG8AbwBnAGwAZQAuAGMAbwBtAAMAQABhAGsAZQBlAHMAYQBy"
2905 "AGEALQBjAG8AcgBwAC4AYQBkAC4AYwBvAHIAcAAuAGcAbwBvAGcAbAB"
2906 "lAC4AYwBvAG0ABQAeAGMAbwByAHAALgBnAG8AbwBnAGwAZQAuAGMAbw"
2907 "BtAAAAAAA=\r\n"),
2908 MockRead("Content-Length: 42\r\n"),
[email protected]076c85082009-04-10 23:21:362909 MockRead("Content-Type: text/html\r\n\r\n"),
[email protected]385a4672009-03-11 22:21:292910 MockRead("You are not authorized to view this page\r\n"),
2911
2912 // Wrong password.
2913 MockRead("HTTP/1.1 401 Access Denied\r\n"),
[email protected]385a4672009-03-11 22:21:292914 MockRead("WWW-Authenticate: NTLM\r\n"),
2915 MockRead("Connection: close\r\n"),
2916 MockRead("Content-Length: 42\r\n"),
[email protected]076c85082009-04-10 23:21:362917 MockRead("Content-Type: text/html\r\n\r\n"),
[email protected]385a4672009-03-11 22:21:292918 // Missing content -- won't matter, as connection will be reset.
[email protected]1c773ea12009-04-28 19:58:422919 MockRead(false, ERR_UNEXPECTED),
[email protected]385a4672009-03-11 22:21:292920 };
2921
2922 MockWrite data_writes3[] = {
[email protected]0757e7702009-03-27 04:00:222923 // After restarting with a null identity, this is the
[email protected]385a4672009-03-11 22:21:292924 // request we should be issuing -- the final header line contains a Type
2925 // 1 message.
2926 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
2927 "Host: 172.22.68.17\r\n"
2928 "Connection: keep-alive\r\n"
2929 "Authorization: NTLM "
2930 "TlRMTVNTUAABAAAAB4IIAAAAAAAAAAAAAAAAAAAAAAA=\r\n\r\n"),
2931
2932 // After calling trans->RestartWithAuth(), we should send a Type 3 message
2933 // (the credentials for the origin server). The second request continues
2934 // on the same connection.
2935 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
2936 "Host: 172.22.68.17\r\n"
2937 "Connection: keep-alive\r\n"
2938 "Authorization: NTLM TlRMTVNTUAADAAAAGAAYAGgAAAAYABgAgA"
2939 "AAAAAAAABAAAAAGAAYAEAAAAAQABAAWAAAAAAAAAAAAAAABYIIAHQA"
2940 "ZQBzAHQAaQBuAGcALQBuAHQAbABtAFcAVABDAC0AVwBJAE4ANwBO54"
2941 "dFMVvTHwAAAAAAAAAAAAAAAAAAAACS7sT6Uzw7L0L//WUqlIaVWpbI"
2942 "+4MUm7c=\r\n\r\n"),
2943 };
2944
2945 MockRead data_reads3[] = {
2946 // The origin server responds with a Type 2 message.
2947 MockRead("HTTP/1.1 401 Access Denied\r\n"),
2948 MockRead("WWW-Authenticate: NTLM "
2949 "TlRMTVNTUAACAAAADAAMADgAAAAFgokCL24VN8dgOR8AAAAAAAAAALo"
2950 "AugBEAAAABQEoCgAAAA9HAE8ATwBHAEwARQACAAwARwBPAE8ARwBMAE"
2951 "UAAQAaAEEASwBFAEUAUwBBAFIAQQAtAEMATwBSAFAABAAeAGMAbwByA"
2952 "HAALgBnAG8AbwBnAGwAZQAuAGMAbwBtAAMAQABhAGsAZQBlAHMAYQBy"
2953 "AGEALQBjAG8AcgBwAC4AYQBkAC4AYwBvAHIAcAAuAGcAbwBvAGcAbAB"
2954 "lAC4AYwBvAG0ABQAeAGMAbwByAHAALgBnAG8AbwBnAGwAZQAuAGMAbw"
2955 "BtAAAAAAA=\r\n"),
2956 MockRead("Content-Length: 42\r\n"),
[email protected]076c85082009-04-10 23:21:362957 MockRead("Content-Type: text/html\r\n\r\n"),
[email protected]385a4672009-03-11 22:21:292958 MockRead("You are not authorized to view this page\r\n"),
2959
2960 // Lastly we get the desired content.
2961 MockRead("HTTP/1.1 200 OK\r\n"),
2962 MockRead("Content-Type: text/html; charset=utf-8\r\n"),
2963 MockRead("Content-Length: 13\r\n\r\n"),
2964 MockRead("Please Login\r\n"),
[email protected]1c773ea12009-04-28 19:58:422965 MockRead(false, OK),
[email protected]385a4672009-03-11 22:21:292966 };
2967
[email protected]31a2bfe2010-02-09 08:03:392968 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2969 data_writes1, arraysize(data_writes1));
2970 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
2971 data_writes2, arraysize(data_writes2));
2972 StaticSocketDataProvider data3(data_reads3, arraysize(data_reads3),
2973 data_writes3, arraysize(data_writes3));
[email protected]5ecc992a42009-11-11 01:41:592974 session_deps.socket_factory.AddSocketDataProvider(&data1);
2975 session_deps.socket_factory.AddSocketDataProvider(&data2);
2976 session_deps.socket_factory.AddSocketDataProvider(&data3);
[email protected]385a4672009-03-11 22:21:292977
2978 TestCompletionCallback callback1;
2979
[email protected]0b0bf032010-09-21 18:08:502980 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
2981
[email protected]5a1d7ca2010-04-28 20:12:272982 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:422983 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]385a4672009-03-11 22:21:292984
2985 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422986 EXPECT_EQ(OK, rv);
[email protected]385a4672009-03-11 22:21:292987
[email protected]0757e7702009-03-27 04:00:222988 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
[email protected]385a4672009-03-11 22:21:292989 TestCompletionCallback callback2;
[email protected]13c8a092010-07-29 06:15:442990 rv = trans->RestartWithAuth(string16(), string16(), &callback2);
[email protected]1c773ea12009-04-28 19:58:422991 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]385a4672009-03-11 22:21:292992 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422993 EXPECT_EQ(OK, rv);
[email protected]0757e7702009-03-27 04:00:222994 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
[email protected]385a4672009-03-11 22:21:292995
[email protected]1c773ea12009-04-28 19:58:422996 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]385a4672009-03-11 22:21:292997 EXPECT_FALSE(response == NULL);
2998
2999 // The password prompt info should have been set in response->auth_challenge.
3000 EXPECT_FALSE(response->auth_challenge.get() == NULL);
3001
[email protected]71e4573a2009-05-21 22:03:003002 EXPECT_EQ(L"172.22.68.17:80", response->auth_challenge->host_and_port);
[email protected]385a4672009-03-11 22:21:293003 EXPECT_EQ(L"", response->auth_challenge->realm);
3004 EXPECT_EQ(L"ntlm", response->auth_challenge->scheme);
3005
3006 TestCompletionCallback callback3;
3007
[email protected]0757e7702009-03-27 04:00:223008 // Enter the wrong password.
[email protected]13c8a092010-07-29 06:15:443009 rv = trans->RestartWithAuth(kTestingNTLM, kWrongPassword, &callback3);
[email protected]1c773ea12009-04-28 19:58:423010 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]385a4672009-03-11 22:21:293011
3012 rv = callback3.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:423013 EXPECT_EQ(OK, rv);
[email protected]385a4672009-03-11 22:21:293014
[email protected]0757e7702009-03-27 04:00:223015 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
3016 TestCompletionCallback callback4;
[email protected]13c8a092010-07-29 06:15:443017 rv = trans->RestartWithAuth(string16(), string16(), &callback4);
[email protected]1c773ea12009-04-28 19:58:423018 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]0757e7702009-03-27 04:00:223019 rv = callback4.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:423020 EXPECT_EQ(OK, rv);
[email protected]0757e7702009-03-27 04:00:223021 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
3022
3023 response = trans->GetResponseInfo();
3024 EXPECT_FALSE(response == NULL);
3025
3026 // The password prompt info should have been set in response->auth_challenge.
3027 EXPECT_FALSE(response->auth_challenge.get() == NULL);
3028
[email protected]71e4573a2009-05-21 22:03:003029 EXPECT_EQ(L"172.22.68.17:80", response->auth_challenge->host_and_port);
[email protected]0757e7702009-03-27 04:00:223030 EXPECT_EQ(L"", response->auth_challenge->realm);
3031 EXPECT_EQ(L"ntlm", response->auth_challenge->scheme);
3032
3033 TestCompletionCallback callback5;
3034
3035 // Now enter the right password.
[email protected]13c8a092010-07-29 06:15:443036 rv = trans->RestartWithAuth(kTestingNTLM, kTestingNTLM, &callback5);
[email protected]1c773ea12009-04-28 19:58:423037 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]0757e7702009-03-27 04:00:223038
3039 rv = callback5.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:423040 EXPECT_EQ(OK, rv);
[email protected]0757e7702009-03-27 04:00:223041
[email protected]385a4672009-03-11 22:21:293042 response = trans->GetResponseInfo();
3043 EXPECT_TRUE(response->auth_challenge.get() == NULL);
3044 EXPECT_EQ(13, response->headers->GetContentLength());
3045}
[email protected]ea9dc9a2009-09-05 00:43:323046#endif // NTLM_PORTABLE
[email protected]385a4672009-03-11 22:21:293047
[email protected]4ddaf2502008-10-23 18:26:193048// Test reading a server response which has only headers, and no body.
3049// After some maximum number of bytes is consumed, the transaction should
3050// fail with ERR_RESPONSE_HEADERS_TOO_BIG.
3051TEST_F(HttpNetworkTransactionTest, LargeHeadersNoBody) {
[email protected]228ff742009-06-05 01:19:593052 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:403053 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:433054 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]4ddaf2502008-10-23 18:26:193055
[email protected]1c773ea12009-04-28 19:58:423056 HttpRequestInfo request;
[email protected]4ddaf2502008-10-23 18:26:193057 request.method = "GET";
3058 request.url = GURL("http://www.google.com/");
3059 request.load_flags = 0;
3060
[email protected]b75b7b2f2009-10-06 00:54:533061 // Respond with 300 kb of headers (we should fail after 256 kb).
[email protected]15a5ccf82008-10-23 19:57:433062 std::string large_headers_string;
[email protected]b75b7b2f2009-10-06 00:54:533063 FillLargeHeadersString(&large_headers_string, 300 * 1024);
[email protected]4ddaf2502008-10-23 18:26:193064
3065 MockRead data_reads[] = {
3066 MockRead("HTTP/1.0 200 OK\r\n"),
[email protected]15a5ccf82008-10-23 19:57:433067 MockRead(true, large_headers_string.data(), large_headers_string.size()),
[email protected]4ddaf2502008-10-23 18:26:193068 MockRead("\r\nBODY"),
[email protected]1c773ea12009-04-28 19:58:423069 MockRead(false, OK),
[email protected]4ddaf2502008-10-23 18:26:193070 };
[email protected]31a2bfe2010-02-09 08:03:393071 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:593072 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]4ddaf2502008-10-23 18:26:193073
3074 TestCompletionCallback callback;
3075
[email protected]5a1d7ca2010-04-28 20:12:273076 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:423077 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]4ddaf2502008-10-23 18:26:193078
3079 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:423080 EXPECT_EQ(ERR_RESPONSE_HEADERS_TOO_BIG, rv);
[email protected]4ddaf2502008-10-23 18:26:193081
[email protected]1c773ea12009-04-28 19:58:423082 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]4ddaf2502008-10-23 18:26:193083 EXPECT_TRUE(response == NULL);
3084}
[email protected]f4e426b2008-11-05 00:24:493085
3086// Make sure that we don't try to reuse a TCPClientSocket when failing to
3087// establish tunnel.
3088// http://code.google.com/p/chromium/issues/detail?id=3772
3089TEST_F(HttpNetworkTransactionTest, DontRecycleTCPSocketForSSLTunnel) {
3090 // Configure against proxy server "myproxy:70".
[email protected]81cdfcd2010-10-16 00:49:003091 SessionDependencies session_deps(ProxyService::CreateFixed("myproxy:70"));
[email protected]db8f44c2008-12-13 04:52:013092
[email protected]228ff742009-06-05 01:19:593093 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]f4e426b2008-11-05 00:24:493094
[email protected]5695b8c2009-09-30 21:36:433095 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]f4e426b2008-11-05 00:24:493096
[email protected]1c773ea12009-04-28 19:58:423097 HttpRequestInfo request;
[email protected]f4e426b2008-11-05 00:24:493098 request.method = "GET";
3099 request.url = GURL("https://www.google.com/");
3100 request.load_flags = 0;
3101
3102 // Since we have proxy, should try to establish tunnel.
3103 MockWrite data_writes1[] = {
3104 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
[email protected]e44de5d2009-06-05 20:12:453105 "Host: www.google.com\r\n"
3106 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]f4e426b2008-11-05 00:24:493107 };
3108
[email protected]77848d12008-11-14 00:00:223109 // The proxy responds to the connect with a 404, using a persistent
[email protected]f4e426b2008-11-05 00:24:493110 // connection. Usually a proxy would return 501 (not implemented),
3111 // or 200 (tunnel established).
3112 MockRead data_reads1[] = {
3113 MockRead("HTTP/1.1 404 Not Found\r\n"),
3114 MockRead("Content-Length: 10\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:423115 MockRead(false, ERR_UNEXPECTED), // Should not be reached.
[email protected]f4e426b2008-11-05 00:24:493116 };
3117
[email protected]31a2bfe2010-02-09 08:03:393118 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
3119 data_writes1, arraysize(data_writes1));
[email protected]5ecc992a42009-11-11 01:41:593120 session_deps.socket_factory.AddSocketDataProvider(&data1);
[email protected]f4e426b2008-11-05 00:24:493121
3122 TestCompletionCallback callback1;
3123
[email protected]5a1d7ca2010-04-28 20:12:273124 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:423125 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f4e426b2008-11-05 00:24:493126
3127 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:423128 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED, rv);
[email protected]f4e426b2008-11-05 00:24:493129
[email protected]1c773ea12009-04-28 19:58:423130 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]c744cf22009-02-27 07:28:083131 EXPECT_TRUE(response == NULL);
[email protected]f4e426b2008-11-05 00:24:493132
[email protected]b4404c02009-04-10 16:38:523133 // Empty the current queue. This is necessary because idle sockets are
3134 // added to the connection pool asynchronously with a PostTask.
3135 MessageLoop::current()->RunAllPending();
3136
[email protected]f4e426b2008-11-05 00:24:493137 // We now check to make sure the TCPClientSocket was not added back to
3138 // the pool.
[email protected]a937a06d2009-08-19 21:19:243139 EXPECT_EQ(0, session->tcp_socket_pool()->IdleSocketCount());
[email protected]f4e426b2008-11-05 00:24:493140 trans.reset();
[email protected]b4404c02009-04-10 16:38:523141 MessageLoop::current()->RunAllPending();
[email protected]f4e426b2008-11-05 00:24:493142 // Make sure that the socket didn't get recycled after calling the destructor.
[email protected]a937a06d2009-08-19 21:19:243143 EXPECT_EQ(0, session->tcp_socket_pool()->IdleSocketCount());
[email protected]f4e426b2008-11-05 00:24:493144}
[email protected]372d34a2008-11-05 21:30:513145
[email protected]1b157c02009-04-21 01:55:403146// Make sure that we recycle a socket after reading all of the response body.
3147TEST_F(HttpNetworkTransactionTest, RecycleSocket) {
[email protected]228ff742009-06-05 01:19:593148 SessionDependencies session_deps;
3149 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]1b157c02009-04-21 01:55:403150
[email protected]5695b8c2009-09-30 21:36:433151 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]1b157c02009-04-21 01:55:403152
[email protected]1c773ea12009-04-28 19:58:423153 HttpRequestInfo request;
[email protected]1b157c02009-04-21 01:55:403154 request.method = "GET";
3155 request.url = GURL("http://www.google.com/");
3156 request.load_flags = 0;
3157
3158 MockRead data_reads[] = {
3159 // A part of the response body is received with the response headers.
3160 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 11\r\n\r\nhel"),
3161 // The rest of the response body is received in two parts.
3162 MockRead("lo"),
3163 MockRead(" world"),
3164 MockRead("junk"), // Should not be read!!
[email protected]1c773ea12009-04-28 19:58:423165 MockRead(false, OK),
[email protected]1b157c02009-04-21 01:55:403166 };
3167
[email protected]31a2bfe2010-02-09 08:03:393168 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:593169 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1b157c02009-04-21 01:55:403170
3171 TestCompletionCallback callback;
3172
[email protected]5a1d7ca2010-04-28 20:12:273173 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:423174 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]1b157c02009-04-21 01:55:403175
3176 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:423177 EXPECT_EQ(OK, rv);
[email protected]1b157c02009-04-21 01:55:403178
[email protected]1c773ea12009-04-28 19:58:423179 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]1b157c02009-04-21 01:55:403180 EXPECT_TRUE(response != NULL);
3181
3182 EXPECT_TRUE(response->headers != NULL);
3183 std::string status_line = response->headers->GetStatusLine();
3184 EXPECT_EQ("HTTP/1.1 200 OK", status_line);
3185
[email protected]a937a06d2009-08-19 21:19:243186 EXPECT_EQ(0, session->tcp_socket_pool()->IdleSocketCount());
[email protected]1b157c02009-04-21 01:55:403187
3188 std::string response_data;
3189 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:423190 EXPECT_EQ(OK, rv);
[email protected]1b157c02009-04-21 01:55:403191 EXPECT_EQ("hello world", response_data);
3192
3193 // Empty the current queue. This is necessary because idle sockets are
3194 // added to the connection pool asynchronously with a PostTask.
3195 MessageLoop::current()->RunAllPending();
3196
3197 // We now check to make sure the socket was added back to the pool.
[email protected]a937a06d2009-08-19 21:19:243198 EXPECT_EQ(1, session->tcp_socket_pool()->IdleSocketCount());
[email protected]1b157c02009-04-21 01:55:403199}
3200
[email protected]76a505b2010-08-25 06:23:003201// Make sure that we recycle a SSL socket after reading all of the response
3202// body.
3203TEST_F(HttpNetworkTransactionTest, RecycleSSLSocket) {
3204 SessionDependencies session_deps;
3205 HttpRequestInfo request;
3206 request.method = "GET";
3207 request.url = GURL("https://www.google.com/");
3208 request.load_flags = 0;
3209
3210 MockWrite data_writes[] = {
3211 MockWrite("GET / HTTP/1.1\r\n"
3212 "Host: www.google.com\r\n"
3213 "Connection: keep-alive\r\n\r\n"),
3214 };
3215
3216 MockRead data_reads[] = {
3217 MockRead("HTTP/1.1 200 OK\r\n"),
3218 MockRead("Content-Length: 11\r\n\r\n"),
3219 MockRead("hello world"),
3220 MockRead(false, OK),
3221 };
3222
3223 SSLSocketDataProvider ssl(true, OK);
3224 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
3225
3226 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
3227 data_writes, arraysize(data_writes));
3228 session_deps.socket_factory.AddSocketDataProvider(&data);
3229
3230 TestCompletionCallback callback;
3231
3232 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
3233 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
3234
3235 int rv = trans->Start(&request, &callback, BoundNetLog());
3236
3237 EXPECT_EQ(ERR_IO_PENDING, rv);
3238 EXPECT_EQ(OK, callback.WaitForResult());
3239
3240 const HttpResponseInfo* response = trans->GetResponseInfo();
3241 ASSERT_TRUE(response != NULL);
3242 ASSERT_TRUE(response->headers != NULL);
3243 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
3244
3245 EXPECT_EQ(0, session->tcp_socket_pool()->IdleSocketCount());
3246
3247 std::string response_data;
3248 rv = ReadTransaction(trans.get(), &response_data);
3249 EXPECT_EQ(OK, rv);
3250 EXPECT_EQ("hello world", response_data);
3251
3252 // Empty the current queue. This is necessary because idle sockets are
3253 // added to the connection pool asynchronously with a PostTask.
3254 MessageLoop::current()->RunAllPending();
3255
3256 // We now check to make sure the socket was added back to the pool.
3257 EXPECT_EQ(1, session->ssl_socket_pool()->IdleSocketCount());
3258}
3259
3260// Grab a SSL socket, use it, and put it back into the pool. Then, reuse it
3261// from the pool and make sure that we recover okay.
3262TEST_F(HttpNetworkTransactionTest, RecycleDeadSSLSocket) {
3263 SessionDependencies session_deps;
3264 HttpRequestInfo request;
3265 request.method = "GET";
3266 request.url = GURL("https://www.google.com/");
3267 request.load_flags = 0;
3268
3269 MockWrite data_writes[] = {
3270 MockWrite("GET / HTTP/1.1\r\n"
3271 "Host: www.google.com\r\n"
3272 "Connection: keep-alive\r\n\r\n"),
3273 MockWrite("GET / HTTP/1.1\r\n"
3274 "Host: www.google.com\r\n"
3275 "Connection: keep-alive\r\n\r\n"),
3276 };
3277
3278 MockRead data_reads[] = {
3279 MockRead("HTTP/1.1 200 OK\r\n"),
3280 MockRead("Content-Length: 11\r\n\r\n"),
3281 MockRead(false, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
3282 MockRead("hello world"),
3283 MockRead(true, 0, 0) // EOF
3284 };
3285
3286 SSLSocketDataProvider ssl(true, OK);
3287 SSLSocketDataProvider ssl2(true, OK);
3288 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
3289 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl2);
3290
3291 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
3292 data_writes, arraysize(data_writes));
3293 StaticSocketDataProvider data2(data_reads, arraysize(data_reads),
3294 data_writes, arraysize(data_writes));
3295 session_deps.socket_factory.AddSocketDataProvider(&data);
3296 session_deps.socket_factory.AddSocketDataProvider(&data2);
3297
3298 TestCompletionCallback callback;
3299
3300 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
3301 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
3302
3303 int rv = trans->Start(&request, &callback, BoundNetLog());
3304
3305 EXPECT_EQ(ERR_IO_PENDING, rv);
3306 EXPECT_EQ(OK, callback.WaitForResult());
3307
3308 const HttpResponseInfo* response = trans->GetResponseInfo();
3309 ASSERT_TRUE(response != NULL);
3310 ASSERT_TRUE(response->headers != NULL);
3311 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
3312
3313 EXPECT_EQ(0, session->tcp_socket_pool()->IdleSocketCount());
3314
3315 std::string response_data;
3316 rv = ReadTransaction(trans.get(), &response_data);
3317 EXPECT_EQ(OK, rv);
3318 EXPECT_EQ("hello world", response_data);
3319
3320 // Empty the current queue. This is necessary because idle sockets are
3321 // added to the connection pool asynchronously with a PostTask.
3322 MessageLoop::current()->RunAllPending();
3323
3324 // We now check to make sure the socket was added back to the pool.
3325 EXPECT_EQ(1, session->ssl_socket_pool()->IdleSocketCount());
3326
3327 // Now start the second transaction, which should reuse the previous socket.
3328
3329 trans.reset(new HttpNetworkTransaction(session));
3330
3331 rv = trans->Start(&request, &callback, BoundNetLog());
3332
3333 EXPECT_EQ(ERR_IO_PENDING, rv);
3334 EXPECT_EQ(OK, callback.WaitForResult());
3335
3336 response = trans->GetResponseInfo();
3337 ASSERT_TRUE(response != NULL);
3338 ASSERT_TRUE(response->headers != NULL);
3339 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
3340
3341 EXPECT_EQ(0, session->tcp_socket_pool()->IdleSocketCount());
3342
3343 rv = ReadTransaction(trans.get(), &response_data);
3344 EXPECT_EQ(OK, rv);
3345 EXPECT_EQ("hello world", response_data);
3346
3347 // Empty the current queue. This is necessary because idle sockets are
3348 // added to the connection pool asynchronously with a PostTask.
3349 MessageLoop::current()->RunAllPending();
3350
3351 // We now check to make sure the socket was added back to the pool.
3352 EXPECT_EQ(1, session->ssl_socket_pool()->IdleSocketCount());
3353}
3354
[email protected]b4404c02009-04-10 16:38:523355// Make sure that we recycle a socket after a zero-length response.
3356// http://crbug.com/9880
3357TEST_F(HttpNetworkTransactionTest, RecycleSocketAfterZeroContentLength) {
[email protected]228ff742009-06-05 01:19:593358 SessionDependencies session_deps;
3359 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]b4404c02009-04-10 16:38:523360
[email protected]5695b8c2009-09-30 21:36:433361 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]b4404c02009-04-10 16:38:523362
[email protected]1c773ea12009-04-28 19:58:423363 HttpRequestInfo request;
[email protected]b4404c02009-04-10 16:38:523364 request.method = "GET";
3365 request.url = GURL("http://www.google.com/csi?v=3&s=web&action=&"
3366 "tran=undefined&ei=mAXcSeegAo-SMurloeUN&"
3367 "e=17259,18167,19592,19773,19981,20133,20173,20233&"
3368 "rt=prt.2642,ol.2649,xjs.2951");
3369 request.load_flags = 0;
3370
3371 MockRead data_reads[] = {
3372 MockRead("HTTP/1.1 204 No Content\r\n"
3373 "Content-Length: 0\r\n"
3374 "Content-Type: text/html\r\n\r\n"),
3375 MockRead("junk"), // Should not be read!!
[email protected]1c773ea12009-04-28 19:58:423376 MockRead(false, OK),
[email protected]b4404c02009-04-10 16:38:523377 };
3378
[email protected]31a2bfe2010-02-09 08:03:393379 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:593380 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]b4404c02009-04-10 16:38:523381
3382 TestCompletionCallback callback;
3383
[email protected]5a1d7ca2010-04-28 20:12:273384 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:423385 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]b4404c02009-04-10 16:38:523386
3387 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:423388 EXPECT_EQ(OK, rv);
[email protected]b4404c02009-04-10 16:38:523389
[email protected]1c773ea12009-04-28 19:58:423390 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]b4404c02009-04-10 16:38:523391 EXPECT_TRUE(response != NULL);
3392
3393 EXPECT_TRUE(response->headers != NULL);
3394 std::string status_line = response->headers->GetStatusLine();
3395 EXPECT_EQ("HTTP/1.1 204 No Content", status_line);
3396
[email protected]a937a06d2009-08-19 21:19:243397 EXPECT_EQ(0, session->tcp_socket_pool()->IdleSocketCount());
[email protected]b4404c02009-04-10 16:38:523398
3399 std::string response_data;
3400 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:423401 EXPECT_EQ(OK, rv);
[email protected]b4404c02009-04-10 16:38:523402 EXPECT_EQ("", response_data);
3403
3404 // Empty the current queue. This is necessary because idle sockets are
3405 // added to the connection pool asynchronously with a PostTask.
3406 MessageLoop::current()->RunAllPending();
3407
3408 // We now check to make sure the socket was added back to the pool.
[email protected]a937a06d2009-08-19 21:19:243409 EXPECT_EQ(1, session->tcp_socket_pool()->IdleSocketCount());
[email protected]b4404c02009-04-10 16:38:523410}
3411
[email protected]372d34a2008-11-05 21:30:513412TEST_F(HttpNetworkTransactionTest, ResendRequestOnWriteBodyError) {
[email protected]1c773ea12009-04-28 19:58:423413 HttpRequestInfo request[2];
[email protected]372d34a2008-11-05 21:30:513414 // Transaction 1: a GET request that succeeds. The socket is recycled
3415 // after use.
3416 request[0].method = "GET";
3417 request[0].url = GURL("http://www.google.com/");
3418 request[0].load_flags = 0;
3419 // Transaction 2: a POST request. Reuses the socket kept alive from
3420 // transaction 1. The first attempts fails when writing the POST data.
3421 // This causes the transaction to retry with a new socket. The second
3422 // attempt succeeds.
3423 request[1].method = "POST";
3424 request[1].url = GURL("http://www.google.com/login.cgi");
[email protected]1c773ea12009-04-28 19:58:423425 request[1].upload_data = new UploadData;
[email protected]372d34a2008-11-05 21:30:513426 request[1].upload_data->AppendBytes("foo", 3);
3427 request[1].load_flags = 0;
3428
[email protected]228ff742009-06-05 01:19:593429 SessionDependencies session_deps;
[email protected]ad8e04a2010-11-01 04:16:273430 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]372d34a2008-11-05 21:30:513431
3432 // The first socket is used for transaction 1 and the first attempt of
3433 // transaction 2.
3434
3435 // The response of transaction 1.
3436 MockRead data_reads1[] = {
3437 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 11\r\n\r\n"),
3438 MockRead("hello world"),
[email protected]1c773ea12009-04-28 19:58:423439 MockRead(false, OK),
[email protected]372d34a2008-11-05 21:30:513440 };
3441 // The mock write results of transaction 1 and the first attempt of
3442 // transaction 2.
3443 MockWrite data_writes1[] = {
3444 MockWrite(false, 64), // GET
3445 MockWrite(false, 93), // POST
[email protected]1c773ea12009-04-28 19:58:423446 MockWrite(false, ERR_CONNECTION_ABORTED), // POST data
[email protected]372d34a2008-11-05 21:30:513447 };
[email protected]31a2bfe2010-02-09 08:03:393448 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
3449 data_writes1, arraysize(data_writes1));
[email protected]372d34a2008-11-05 21:30:513450
3451 // The second socket is used for the second attempt of transaction 2.
3452
3453 // The response of transaction 2.
3454 MockRead data_reads2[] = {
3455 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 7\r\n\r\n"),
3456 MockRead("welcome"),
[email protected]1c773ea12009-04-28 19:58:423457 MockRead(false, OK),
[email protected]372d34a2008-11-05 21:30:513458 };
3459 // The mock write results of the second attempt of transaction 2.
3460 MockWrite data_writes2[] = {
3461 MockWrite(false, 93), // POST
3462 MockWrite(false, 3), // POST data
3463 };
[email protected]31a2bfe2010-02-09 08:03:393464 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
3465 data_writes2, arraysize(data_writes2));
[email protected]372d34a2008-11-05 21:30:513466
[email protected]5ecc992a42009-11-11 01:41:593467 session_deps.socket_factory.AddSocketDataProvider(&data1);
3468 session_deps.socket_factory.AddSocketDataProvider(&data2);
[email protected]372d34a2008-11-05 21:30:513469
3470 const char* kExpectedResponseData[] = {
3471 "hello world", "welcome"
3472 };
3473
3474 for (int i = 0; i < 2; ++i) {
[email protected]1c773ea12009-04-28 19:58:423475 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:433476 new HttpNetworkTransaction(session));
[email protected]372d34a2008-11-05 21:30:513477
3478 TestCompletionCallback callback;
3479
[email protected]5a1d7ca2010-04-28 20:12:273480 int rv = trans->Start(&request[i], &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:423481 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]372d34a2008-11-05 21:30:513482
3483 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:423484 EXPECT_EQ(OK, rv);
[email protected]372d34a2008-11-05 21:30:513485
[email protected]1c773ea12009-04-28 19:58:423486 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]372d34a2008-11-05 21:30:513487 EXPECT_TRUE(response != NULL);
3488
3489 EXPECT_TRUE(response->headers != NULL);
3490 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
3491
3492 std::string response_data;
3493 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:423494 EXPECT_EQ(OK, rv);
[email protected]372d34a2008-11-05 21:30:513495 EXPECT_EQ(kExpectedResponseData[i], response_data);
3496 }
3497}
[email protected]f9ee6b52008-11-08 06:46:233498
3499// Test the request-challenge-retry sequence for basic auth when there is
3500// an identity in the URL. The request should be sent as normal, but when
3501// it fails the identity from the URL is used to answer the challenge.
[email protected]ea9dc9a2009-09-05 00:43:323502TEST_F(HttpNetworkTransactionTest, AuthIdentityInURL) {
[email protected]228ff742009-06-05 01:19:593503 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:403504 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:433505 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]f9ee6b52008-11-08 06:46:233506
[email protected]1c773ea12009-04-28 19:58:423507 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:233508 request.method = "GET";
3509 // Note: the URL has a username:password in it.
[email protected]a97cca42009-08-14 01:00:293510 request.url = GURL("http://foo:b@[email protected]/");
3511
3512 // The password contains an escaped character -- for this test to pass it
3513 // will need to be unescaped by HttpNetworkTransaction.
3514 EXPECT_EQ("b%40r", request.url.password());
3515
[email protected]ea9dc9a2009-09-05 00:43:323516 request.load_flags = LOAD_NORMAL;
[email protected]f9ee6b52008-11-08 06:46:233517
3518 MockWrite data_writes1[] = {
3519 MockWrite("GET / HTTP/1.1\r\n"
3520 "Host: www.google.com\r\n"
3521 "Connection: keep-alive\r\n\r\n"),
3522 };
3523
3524 MockRead data_reads1[] = {
3525 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
3526 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
3527 MockRead("Content-Length: 10\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:423528 MockRead(false, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:233529 };
3530
3531 // After the challenge above, the transaction will be restarted using the
[email protected]ea9dc9a2009-09-05 00:43:323532 // identity from the url (foo, b@r) to answer the challenge.
[email protected]f9ee6b52008-11-08 06:46:233533 MockWrite data_writes2[] = {
3534 MockWrite("GET / HTTP/1.1\r\n"
3535 "Host: www.google.com\r\n"
3536 "Connection: keep-alive\r\n"
[email protected]a97cca42009-08-14 01:00:293537 "Authorization: Basic Zm9vOmJAcg==\r\n\r\n"),
[email protected]f9ee6b52008-11-08 06:46:233538 };
3539
3540 MockRead data_reads2[] = {
3541 MockRead("HTTP/1.0 200 OK\r\n"),
3542 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:423543 MockRead(false, OK),
[email protected]f9ee6b52008-11-08 06:46:233544 };
3545
[email protected]31a2bfe2010-02-09 08:03:393546 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
3547 data_writes1, arraysize(data_writes1));
3548 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
3549 data_writes2, arraysize(data_writes2));
[email protected]5ecc992a42009-11-11 01:41:593550 session_deps.socket_factory.AddSocketDataProvider(&data1);
3551 session_deps.socket_factory.AddSocketDataProvider(&data2);
[email protected]f9ee6b52008-11-08 06:46:233552
3553 TestCompletionCallback callback1;
3554
[email protected]5a1d7ca2010-04-28 20:12:273555 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:423556 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:233557
3558 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:423559 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:233560
[email protected]0757e7702009-03-27 04:00:223561 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
3562 TestCompletionCallback callback2;
[email protected]13c8a092010-07-29 06:15:443563 rv = trans->RestartWithAuth(string16(), string16(), &callback2);
[email protected]1c773ea12009-04-28 19:58:423564 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]0757e7702009-03-27 04:00:223565 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:423566 EXPECT_EQ(OK, rv);
[email protected]0757e7702009-03-27 04:00:223567 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
3568
[email protected]1c773ea12009-04-28 19:58:423569 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]f9ee6b52008-11-08 06:46:233570 EXPECT_FALSE(response == NULL);
3571
3572 // There is no challenge info, since the identity in URL worked.
3573 EXPECT_TRUE(response->auth_challenge.get() == NULL);
3574
3575 EXPECT_EQ(100, response->headers->GetContentLength());
3576
3577 // Empty the current queue.
3578 MessageLoop::current()->RunAllPending();
3579}
3580
[email protected]ea9dc9a2009-09-05 00:43:323581// Test the request-challenge-retry sequence for basic auth when there is
3582// an incorrect identity in the URL. The identity from the URL should be used
3583// only once.
3584TEST_F(HttpNetworkTransactionTest, WrongAuthIdentityInURL) {
3585 SessionDependencies session_deps;
3586 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:433587 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]ea9dc9a2009-09-05 00:43:323588
3589 HttpRequestInfo request;
3590 request.method = "GET";
3591 // Note: the URL has a username:password in it. The password "baz" is
3592 // wrong (should be "bar").
3593 request.url = GURL("http://foo:[email protected]/");
3594
3595 request.load_flags = LOAD_NORMAL;
3596
3597 MockWrite data_writes1[] = {
3598 MockWrite("GET / HTTP/1.1\r\n"
3599 "Host: www.google.com\r\n"
3600 "Connection: keep-alive\r\n\r\n"),
3601 };
3602
3603 MockRead data_reads1[] = {
3604 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
3605 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
3606 MockRead("Content-Length: 10\r\n\r\n"),
3607 MockRead(false, ERR_FAILED),
3608 };
3609
3610 // After the challenge above, the transaction will be restarted using the
3611 // identity from the url (foo, baz) to answer the challenge.
3612 MockWrite data_writes2[] = {
3613 MockWrite("GET / HTTP/1.1\r\n"
3614 "Host: www.google.com\r\n"
3615 "Connection: keep-alive\r\n"
3616 "Authorization: Basic Zm9vOmJheg==\r\n\r\n"),
3617 };
3618
3619 MockRead data_reads2[] = {
3620 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
3621 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
3622 MockRead("Content-Length: 10\r\n\r\n"),
3623 MockRead(false, ERR_FAILED),
3624 };
3625
3626 // After the challenge above, the transaction will be restarted using the
3627 // identity supplied by the user (foo, bar) to answer the challenge.
3628 MockWrite data_writes3[] = {
3629 MockWrite("GET / HTTP/1.1\r\n"
3630 "Host: www.google.com\r\n"
3631 "Connection: keep-alive\r\n"
3632 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
3633 };
3634
3635 MockRead data_reads3[] = {
3636 MockRead("HTTP/1.0 200 OK\r\n"),
3637 MockRead("Content-Length: 100\r\n\r\n"),
3638 MockRead(false, OK),
3639 };
3640
[email protected]31a2bfe2010-02-09 08:03:393641 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
3642 data_writes1, arraysize(data_writes1));
3643 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
3644 data_writes2, arraysize(data_writes2));
3645 StaticSocketDataProvider data3(data_reads3, arraysize(data_reads3),
3646 data_writes3, arraysize(data_writes3));
[email protected]5ecc992a42009-11-11 01:41:593647 session_deps.socket_factory.AddSocketDataProvider(&data1);
3648 session_deps.socket_factory.AddSocketDataProvider(&data2);
3649 session_deps.socket_factory.AddSocketDataProvider(&data3);
[email protected]ea9dc9a2009-09-05 00:43:323650
3651 TestCompletionCallback callback1;
3652
[email protected]5a1d7ca2010-04-28 20:12:273653 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]ea9dc9a2009-09-05 00:43:323654 EXPECT_EQ(ERR_IO_PENDING, rv);
3655
3656 rv = callback1.WaitForResult();
3657 EXPECT_EQ(OK, rv);
3658
3659 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
3660 TestCompletionCallback callback2;
[email protected]13c8a092010-07-29 06:15:443661 rv = trans->RestartWithAuth(string16(), string16(), &callback2);
[email protected]ea9dc9a2009-09-05 00:43:323662 EXPECT_EQ(ERR_IO_PENDING, rv);
3663 rv = callback2.WaitForResult();
3664 EXPECT_EQ(OK, rv);
3665 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
3666
3667 const HttpResponseInfo* response = trans->GetResponseInfo();
3668 EXPECT_FALSE(response == NULL);
3669 // The password prompt info should have been set in response->auth_challenge.
3670 EXPECT_FALSE(response->auth_challenge.get() == NULL);
3671
3672 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
3673 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
3674 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
3675
3676 TestCompletionCallback callback3;
[email protected]13c8a092010-07-29 06:15:443677 rv = trans->RestartWithAuth(kFoo, kBar, &callback3);
[email protected]ea9dc9a2009-09-05 00:43:323678 EXPECT_EQ(ERR_IO_PENDING, rv);
3679 rv = callback3.WaitForResult();
3680 EXPECT_EQ(OK, rv);
3681 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
3682
3683 response = trans->GetResponseInfo();
3684 EXPECT_FALSE(response == NULL);
3685
3686 // There is no challenge info, since the identity worked.
3687 EXPECT_TRUE(response->auth_challenge.get() == NULL);
3688
3689 EXPECT_EQ(100, response->headers->GetContentLength());
3690
3691 // Empty the current queue.
3692 MessageLoop::current()->RunAllPending();
3693}
3694
[email protected]f9ee6b52008-11-08 06:46:233695// Test that previously tried username/passwords for a realm get re-used.
3696TEST_F(HttpNetworkTransactionTest, BasicAuthCacheAndPreauth) {
[email protected]228ff742009-06-05 01:19:593697 SessionDependencies session_deps;
[email protected]ad8e04a2010-11-01 04:16:273698 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]f9ee6b52008-11-08 06:46:233699
3700 // Transaction 1: authenticate (foo, bar) on MyRealm1
3701 {
[email protected]5695b8c2009-09-30 21:36:433702 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]f9ee6b52008-11-08 06:46:233703
[email protected]1c773ea12009-04-28 19:58:423704 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:233705 request.method = "GET";
3706 request.url = GURL("http://www.google.com/x/y/z");
3707 request.load_flags = 0;
3708
3709 MockWrite data_writes1[] = {
3710 MockWrite("GET /x/y/z HTTP/1.1\r\n"
3711 "Host: www.google.com\r\n"
3712 "Connection: keep-alive\r\n\r\n"),
3713 };
3714
3715 MockRead data_reads1[] = {
3716 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
3717 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
3718 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:423719 MockRead(false, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:233720 };
3721
3722 // Resend with authorization (username=foo, password=bar)
3723 MockWrite data_writes2[] = {
3724 MockWrite("GET /x/y/z HTTP/1.1\r\n"
3725 "Host: www.google.com\r\n"
3726 "Connection: keep-alive\r\n"
3727 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
3728 };
3729
3730 // Sever accepts the authorization.
3731 MockRead data_reads2[] = {
3732 MockRead("HTTP/1.0 200 OK\r\n"),
3733 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:423734 MockRead(false, OK),
[email protected]f9ee6b52008-11-08 06:46:233735 };
3736
[email protected]31a2bfe2010-02-09 08:03:393737 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
3738 data_writes1, arraysize(data_writes1));
3739 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
3740 data_writes2, arraysize(data_writes2));
[email protected]5ecc992a42009-11-11 01:41:593741 session_deps.socket_factory.AddSocketDataProvider(&data1);
3742 session_deps.socket_factory.AddSocketDataProvider(&data2);
[email protected]f9ee6b52008-11-08 06:46:233743
3744 TestCompletionCallback callback1;
3745
[email protected]5a1d7ca2010-04-28 20:12:273746 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:423747 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:233748
3749 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:423750 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:233751
[email protected]1c773ea12009-04-28 19:58:423752 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]f9ee6b52008-11-08 06:46:233753 EXPECT_FALSE(response == NULL);
3754
3755 // The password prompt info should have been set in
3756 // response->auth_challenge.
3757 EXPECT_FALSE(response->auth_challenge.get() == NULL);
3758
[email protected]71e4573a2009-05-21 22:03:003759 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
[email protected]f9ee6b52008-11-08 06:46:233760 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
3761 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
3762
3763 TestCompletionCallback callback2;
3764
[email protected]13c8a092010-07-29 06:15:443765 rv = trans->RestartWithAuth(kFoo, kBar, &callback2);
[email protected]1c773ea12009-04-28 19:58:423766 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:233767
3768 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:423769 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:233770
3771 response = trans->GetResponseInfo();
3772 EXPECT_FALSE(response == NULL);
3773 EXPECT_TRUE(response->auth_challenge.get() == NULL);
3774 EXPECT_EQ(100, response->headers->GetContentLength());
3775 }
3776
3777 // ------------------------------------------------------------------------
3778
3779 // Transaction 2: authenticate (foo2, bar2) on MyRealm2
3780 {
[email protected]5695b8c2009-09-30 21:36:433781 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]f9ee6b52008-11-08 06:46:233782
[email protected]1c773ea12009-04-28 19:58:423783 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:233784 request.method = "GET";
3785 // Note that Transaction 1 was at /x/y/z, so this is in the same
3786 // protection space as MyRealm1.
3787 request.url = GURL("http://www.google.com/x/y/a/b");
3788 request.load_flags = 0;
3789
3790 MockWrite data_writes1[] = {
3791 MockWrite("GET /x/y/a/b HTTP/1.1\r\n"
3792 "Host: www.google.com\r\n"
3793 "Connection: keep-alive\r\n"
3794 // Send preemptive authorization for MyRealm1
3795 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
3796 };
3797
3798 // The server didn't like the preemptive authorization, and
3799 // challenges us for a different realm (MyRealm2).
3800 MockRead data_reads1[] = {
3801 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
3802 MockRead("WWW-Authenticate: Basic realm=\"MyRealm2\"\r\n"),
3803 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:423804 MockRead(false, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:233805 };
3806
3807 // Resend with authorization for MyRealm2 (username=foo2, password=bar2)
3808 MockWrite data_writes2[] = {
3809 MockWrite("GET /x/y/a/b HTTP/1.1\r\n"
3810 "Host: www.google.com\r\n"
3811 "Connection: keep-alive\r\n"
3812 "Authorization: Basic Zm9vMjpiYXIy\r\n\r\n"),
3813 };
3814
3815 // Sever accepts the authorization.
3816 MockRead data_reads2[] = {
3817 MockRead("HTTP/1.0 200 OK\r\n"),
3818 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:423819 MockRead(false, OK),
[email protected]f9ee6b52008-11-08 06:46:233820 };
3821
[email protected]31a2bfe2010-02-09 08:03:393822 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
3823 data_writes1, arraysize(data_writes1));
3824 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
3825 data_writes2, arraysize(data_writes2));
[email protected]5ecc992a42009-11-11 01:41:593826 session_deps.socket_factory.AddSocketDataProvider(&data1);
3827 session_deps.socket_factory.AddSocketDataProvider(&data2);
[email protected]f9ee6b52008-11-08 06:46:233828
3829 TestCompletionCallback callback1;
3830
[email protected]5a1d7ca2010-04-28 20:12:273831 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:423832 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:233833
3834 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:423835 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:233836
[email protected]1c773ea12009-04-28 19:58:423837 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]f9ee6b52008-11-08 06:46:233838 EXPECT_FALSE(response == NULL);
3839
3840 // The password prompt info should have been set in
3841 // response->auth_challenge.
3842 EXPECT_FALSE(response->auth_challenge.get() == NULL);
3843
[email protected]71e4573a2009-05-21 22:03:003844 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
[email protected]f9ee6b52008-11-08 06:46:233845 EXPECT_EQ(L"MyRealm2", response->auth_challenge->realm);
3846 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
3847
3848 TestCompletionCallback callback2;
3849
[email protected]13c8a092010-07-29 06:15:443850 rv = trans->RestartWithAuth(kFoo2, kBar2, &callback2);
[email protected]1c773ea12009-04-28 19:58:423851 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:233852
3853 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:423854 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:233855
3856 response = trans->GetResponseInfo();
3857 EXPECT_FALSE(response == NULL);
3858 EXPECT_TRUE(response->auth_challenge.get() == NULL);
3859 EXPECT_EQ(100, response->headers->GetContentLength());
3860 }
3861
3862 // ------------------------------------------------------------------------
3863
3864 // Transaction 3: Resend a request in MyRealm's protection space --
3865 // succeed with preemptive authorization.
3866 {
[email protected]5695b8c2009-09-30 21:36:433867 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]f9ee6b52008-11-08 06:46:233868
[email protected]1c773ea12009-04-28 19:58:423869 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:233870 request.method = "GET";
3871 request.url = GURL("http://www.google.com/x/y/z2");
3872 request.load_flags = 0;
3873
3874 MockWrite data_writes1[] = {
3875 MockWrite("GET /x/y/z2 HTTP/1.1\r\n"
3876 "Host: www.google.com\r\n"
3877 "Connection: keep-alive\r\n"
3878 // The authorization for MyRealm1 gets sent preemptively
3879 // (since the url is in the same protection space)
3880 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
3881 };
3882
3883 // Sever accepts the preemptive authorization
3884 MockRead data_reads1[] = {
3885 MockRead("HTTP/1.0 200 OK\r\n"),
3886 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:423887 MockRead(false, OK),
[email protected]f9ee6b52008-11-08 06:46:233888 };
3889
[email protected]31a2bfe2010-02-09 08:03:393890 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
3891 data_writes1, arraysize(data_writes1));
[email protected]5ecc992a42009-11-11 01:41:593892 session_deps.socket_factory.AddSocketDataProvider(&data1);
[email protected]f9ee6b52008-11-08 06:46:233893
3894 TestCompletionCallback callback1;
3895
[email protected]5a1d7ca2010-04-28 20:12:273896 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:423897 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:233898
3899 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:423900 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:233901
[email protected]1c773ea12009-04-28 19:58:423902 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]f9ee6b52008-11-08 06:46:233903 EXPECT_FALSE(response == NULL);
3904
3905 EXPECT_TRUE(response->auth_challenge.get() == NULL);
3906 EXPECT_EQ(100, response->headers->GetContentLength());
3907 }
3908
3909 // ------------------------------------------------------------------------
3910
3911 // Transaction 4: request another URL in MyRealm (however the
3912 // url is not known to belong to the protection space, so no pre-auth).
3913 {
[email protected]5695b8c2009-09-30 21:36:433914 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]f9ee6b52008-11-08 06:46:233915
[email protected]1c773ea12009-04-28 19:58:423916 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:233917 request.method = "GET";
3918 request.url = GURL("http://www.google.com/x/1");
3919 request.load_flags = 0;
3920
3921 MockWrite data_writes1[] = {
3922 MockWrite("GET /x/1 HTTP/1.1\r\n"
3923 "Host: www.google.com\r\n"
3924 "Connection: keep-alive\r\n\r\n"),
3925 };
3926
3927 MockRead data_reads1[] = {
3928 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
3929 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
3930 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:423931 MockRead(false, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:233932 };
3933
3934 // Resend with authorization from MyRealm's cache.
3935 MockWrite data_writes2[] = {
3936 MockWrite("GET /x/1 HTTP/1.1\r\n"
3937 "Host: www.google.com\r\n"
3938 "Connection: keep-alive\r\n"
3939 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
3940 };
3941
3942 // Sever accepts the authorization.
3943 MockRead data_reads2[] = {
3944 MockRead("HTTP/1.0 200 OK\r\n"),
3945 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:423946 MockRead(false, OK),
[email protected]f9ee6b52008-11-08 06:46:233947 };
3948
[email protected]31a2bfe2010-02-09 08:03:393949 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
3950 data_writes1, arraysize(data_writes1));
3951 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
3952 data_writes2, arraysize(data_writes2));
[email protected]5ecc992a42009-11-11 01:41:593953 session_deps.socket_factory.AddSocketDataProvider(&data1);
3954 session_deps.socket_factory.AddSocketDataProvider(&data2);
[email protected]f9ee6b52008-11-08 06:46:233955
3956 TestCompletionCallback callback1;
3957
[email protected]5a1d7ca2010-04-28 20:12:273958 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:423959 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:233960
3961 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:423962 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:233963
[email protected]0757e7702009-03-27 04:00:223964 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
3965 TestCompletionCallback callback2;
[email protected]13c8a092010-07-29 06:15:443966 rv = trans->RestartWithAuth(string16(), string16(), &callback2);
[email protected]1c773ea12009-04-28 19:58:423967 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]0757e7702009-03-27 04:00:223968 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:423969 EXPECT_EQ(OK, rv);
[email protected]0757e7702009-03-27 04:00:223970 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
3971
[email protected]1c773ea12009-04-28 19:58:423972 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]f9ee6b52008-11-08 06:46:233973 EXPECT_FALSE(response == NULL);
3974 EXPECT_TRUE(response->auth_challenge.get() == NULL);
3975 EXPECT_EQ(100, response->headers->GetContentLength());
3976 }
3977
3978 // ------------------------------------------------------------------------
3979
3980 // Transaction 5: request a URL in MyRealm, but the server rejects the
3981 // cached identity. Should invalidate and re-prompt.
3982 {
[email protected]5695b8c2009-09-30 21:36:433983 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]f9ee6b52008-11-08 06:46:233984
[email protected]1c773ea12009-04-28 19:58:423985 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:233986 request.method = "GET";
3987 request.url = GURL("http://www.google.com/p/q/t");
3988 request.load_flags = 0;
3989
3990 MockWrite data_writes1[] = {
3991 MockWrite("GET /p/q/t HTTP/1.1\r\n"
3992 "Host: www.google.com\r\n"
3993 "Connection: keep-alive\r\n\r\n"),
3994 };
3995
3996 MockRead data_reads1[] = {
3997 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
3998 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
3999 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:424000 MockRead(false, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:234001 };
4002
4003 // Resend with authorization from cache for MyRealm.
4004 MockWrite data_writes2[] = {
4005 MockWrite("GET /p/q/t HTTP/1.1\r\n"
4006 "Host: www.google.com\r\n"
4007 "Connection: keep-alive\r\n"
4008 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
4009 };
4010
4011 // Sever rejects the authorization.
4012 MockRead data_reads2[] = {
4013 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
4014 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
4015 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:424016 MockRead(false, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:234017 };
4018
4019 // At this point we should prompt for new credentials for MyRealm.
4020 // Restart with username=foo3, password=foo4.
4021 MockWrite data_writes3[] = {
4022 MockWrite("GET /p/q/t HTTP/1.1\r\n"
4023 "Host: www.google.com\r\n"
4024 "Connection: keep-alive\r\n"
4025 "Authorization: Basic Zm9vMzpiYXIz\r\n\r\n"),
4026 };
4027
4028 // Sever accepts the authorization.
4029 MockRead data_reads3[] = {
4030 MockRead("HTTP/1.0 200 OK\r\n"),
4031 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:424032 MockRead(false, OK),
[email protected]f9ee6b52008-11-08 06:46:234033 };
4034
[email protected]31a2bfe2010-02-09 08:03:394035 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
4036 data_writes1, arraysize(data_writes1));
4037 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
4038 data_writes2, arraysize(data_writes2));
4039 StaticSocketDataProvider data3(data_reads3, arraysize(data_reads3),
4040 data_writes3, arraysize(data_writes3));
[email protected]5ecc992a42009-11-11 01:41:594041 session_deps.socket_factory.AddSocketDataProvider(&data1);
4042 session_deps.socket_factory.AddSocketDataProvider(&data2);
4043 session_deps.socket_factory.AddSocketDataProvider(&data3);
[email protected]f9ee6b52008-11-08 06:46:234044
4045 TestCompletionCallback callback1;
4046
[email protected]5a1d7ca2010-04-28 20:12:274047 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:424048 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:234049
4050 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:424051 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:234052
[email protected]0757e7702009-03-27 04:00:224053 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
4054 TestCompletionCallback callback2;
[email protected]13c8a092010-07-29 06:15:444055 rv = trans->RestartWithAuth(string16(), string16(), &callback2);
[email protected]1c773ea12009-04-28 19:58:424056 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]0757e7702009-03-27 04:00:224057 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:424058 EXPECT_EQ(OK, rv);
[email protected]0757e7702009-03-27 04:00:224059 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
4060
[email protected]1c773ea12009-04-28 19:58:424061 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]f9ee6b52008-11-08 06:46:234062 EXPECT_FALSE(response == NULL);
4063
4064 // The password prompt info should have been set in
4065 // response->auth_challenge.
4066 EXPECT_FALSE(response->auth_challenge.get() == NULL);
4067
[email protected]71e4573a2009-05-21 22:03:004068 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
[email protected]f9ee6b52008-11-08 06:46:234069 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
4070 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
4071
[email protected]0757e7702009-03-27 04:00:224072 TestCompletionCallback callback3;
[email protected]f9ee6b52008-11-08 06:46:234073
[email protected]13c8a092010-07-29 06:15:444074 rv = trans->RestartWithAuth(kFoo3, kBar3, &callback3);
[email protected]1c773ea12009-04-28 19:58:424075 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:234076
[email protected]0757e7702009-03-27 04:00:224077 rv = callback3.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:424078 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:234079
4080 response = trans->GetResponseInfo();
4081 EXPECT_FALSE(response == NULL);
4082 EXPECT_TRUE(response->auth_challenge.get() == NULL);
4083 EXPECT_EQ(100, response->headers->GetContentLength());
4084 }
4085}
[email protected]89ceba9a2009-03-21 03:46:064086
[email protected]3c32c5f2010-05-18 15:18:124087// Tests that nonce count increments when multiple auth attempts
4088// are started with the same nonce.
4089TEST_F(HttpNetworkTransactionTest, DigestPreAuthNonceCount) {
4090 SessionDependencies session_deps;
[email protected]ad8e04a2010-11-01 04:16:274091 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]3c32c5f2010-05-18 15:18:124092 HttpAuthHandlerDigest::SetFixedCnonce(true);
4093
4094 // Transaction 1: authenticate (foo, bar) on MyRealm1
4095 {
4096 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
4097
4098 HttpRequestInfo request;
4099 request.method = "GET";
4100 request.url = GURL("http://www.google.com/x/y/z");
4101 request.load_flags = 0;
4102
4103 MockWrite data_writes1[] = {
4104 MockWrite("GET /x/y/z HTTP/1.1\r\n"
4105 "Host: www.google.com\r\n"
4106 "Connection: keep-alive\r\n\r\n"),
4107 };
4108
4109 MockRead data_reads1[] = {
4110 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
4111 MockRead("WWW-Authenticate: Digest realm=\"digestive\", nonce=\"OU812\", "
4112 "algorithm=MD5, qop=\"auth\"\r\n\r\n"),
4113 MockRead(false, OK),
4114 };
4115
4116 // Resend with authorization (username=foo, password=bar)
4117 MockWrite data_writes2[] = {
4118 MockWrite("GET /x/y/z HTTP/1.1\r\n"
4119 "Host: www.google.com\r\n"
4120 "Connection: keep-alive\r\n"
4121 "Authorization: Digest username=\"foo\", realm=\"digestive\", "
4122 "nonce=\"OU812\", uri=\"/x/y/z\", algorithm=MD5, "
4123 "response=\"03ffbcd30add722589c1de345d7a927f\", qop=auth, "
4124 "nc=00000001, cnonce=\"0123456789abcdef\"\r\n\r\n"),
4125 };
4126
4127 // Sever accepts the authorization.
4128 MockRead data_reads2[] = {
4129 MockRead("HTTP/1.0 200 OK\r\n"),
4130 MockRead(false, OK),
4131 };
4132
4133 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
4134 data_writes1, arraysize(data_writes1));
4135 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
4136 data_writes2, arraysize(data_writes2));
4137 session_deps.socket_factory.AddSocketDataProvider(&data1);
4138 session_deps.socket_factory.AddSocketDataProvider(&data2);
4139
4140 TestCompletionCallback callback1;
4141
4142 int rv = trans->Start(&request, &callback1, BoundNetLog());
4143 EXPECT_EQ(ERR_IO_PENDING, rv);
4144
4145 rv = callback1.WaitForResult();
4146 EXPECT_EQ(OK, rv);
4147
4148 const HttpResponseInfo* response = trans->GetResponseInfo();
4149 ASSERT_FALSE(response == NULL);
4150
4151 // The password prompt info should have been set in
4152 // response->auth_challenge.
4153 ASSERT_FALSE(response->auth_challenge.get() == NULL);
4154
4155 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
4156 EXPECT_EQ(L"digestive", response->auth_challenge->realm);
4157 EXPECT_EQ(L"digest", response->auth_challenge->scheme);
4158
4159 TestCompletionCallback callback2;
4160
[email protected]13c8a092010-07-29 06:15:444161 rv = trans->RestartWithAuth(kFoo, kBar, &callback2);
[email protected]3c32c5f2010-05-18 15:18:124162 EXPECT_EQ(ERR_IO_PENDING, rv);
4163
4164 rv = callback2.WaitForResult();
4165 EXPECT_EQ(OK, rv);
4166
4167 response = trans->GetResponseInfo();
4168 ASSERT_FALSE(response == NULL);
4169 EXPECT_TRUE(response->auth_challenge.get() == NULL);
4170 }
4171
4172 // ------------------------------------------------------------------------
4173
4174 // Transaction 2: Request another resource in digestive's protection space.
4175 // This will preemptively add an Authorization header which should have an
4176 // "nc" value of 2 (as compared to 1 in the first use.
4177 {
4178 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
4179
4180 HttpRequestInfo request;
4181 request.method = "GET";
4182 // Note that Transaction 1 was at /x/y/z, so this is in the same
4183 // protection space as digest.
4184 request.url = GURL("http://www.google.com/x/y/a/b");
4185 request.load_flags = 0;
4186
4187 MockWrite data_writes1[] = {
4188 MockWrite("GET /x/y/a/b HTTP/1.1\r\n"
4189 "Host: www.google.com\r\n"
4190 "Connection: keep-alive\r\n"
4191 "Authorization: Digest username=\"foo\", realm=\"digestive\", "
4192 "nonce=\"OU812\", uri=\"/x/y/a/b\", algorithm=MD5, "
4193 "response=\"d6f9a2c07d1c5df7b89379dca1269b35\", qop=auth, "
4194 "nc=00000002, cnonce=\"0123456789abcdef\"\r\n\r\n"),
4195 };
4196
4197 // Sever accepts the authorization.
4198 MockRead data_reads1[] = {
4199 MockRead("HTTP/1.0 200 OK\r\n"),
4200 MockRead("Content-Length: 100\r\n\r\n"),
4201 MockRead(false, OK),
4202 };
4203
4204 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
4205 data_writes1, arraysize(data_writes1));
4206 session_deps.socket_factory.AddSocketDataProvider(&data1);
4207
4208 TestCompletionCallback callback1;
4209
4210 int rv = trans->Start(&request, &callback1, BoundNetLog());
4211 EXPECT_EQ(ERR_IO_PENDING, rv);
4212
4213 rv = callback1.WaitForResult();
4214 EXPECT_EQ(OK, rv);
4215
4216 const HttpResponseInfo* response = trans->GetResponseInfo();
4217 ASSERT_FALSE(response == NULL);
4218 EXPECT_TRUE(response->auth_challenge.get() == NULL);
4219 }
4220}
4221
[email protected]89ceba9a2009-03-21 03:46:064222// Test the ResetStateForRestart() private method.
4223TEST_F(HttpNetworkTransactionTest, ResetStateForRestart) {
4224 // Create a transaction (the dependencies aren't important).
[email protected]228ff742009-06-05 01:19:594225 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:404226 scoped_ptr<HttpNetworkTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:434227 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]89ceba9a2009-03-21 03:46:064228
4229 // Setup some state (which we expect ResetStateForRestart() will clear).
[email protected]89ceba9a2009-03-21 03:46:064230 trans->read_buf_ = new IOBuffer(15);
4231 trans->read_buf_len_ = 15;
[email protected]b94f92d2010-10-27 16:45:204232 trans->request_headers_.SetHeader("Authorization", "NTLM");
[email protected]89ceba9a2009-03-21 03:46:064233
4234 // Setup state in response_
[email protected]a7e41312009-12-16 23:18:144235 HttpResponseInfo* response = &trans->response_;
[email protected]0877e3d2009-10-17 22:29:574236 response->auth_challenge = new AuthChallengeInfo();
4237 response->ssl_info.cert_status = -15;
4238 response->response_time = base::Time::Now();
4239 response->was_cached = true; // (Wouldn't ever actually be true...)
[email protected]89ceba9a2009-03-21 03:46:064240
4241 { // Setup state for response_.vary_data
4242 HttpRequestInfo request;
4243 std::string temp("HTTP/1.1 200 OK\nVary: foo, bar\n\n");
4244 std::replace(temp.begin(), temp.end(), '\n', '\0');
[email protected]ad8e04a2010-11-01 04:16:274245 scoped_refptr<HttpResponseHeaders> headers(new HttpResponseHeaders(temp));
[email protected]8c76ae22010-04-20 22:15:434246 request.extra_headers.SetHeader("Foo", "1");
4247 request.extra_headers.SetHeader("bar", "23");
[email protected]0877e3d2009-10-17 22:29:574248 EXPECT_TRUE(response->vary_data.Init(request, *headers));
[email protected]89ceba9a2009-03-21 03:46:064249 }
4250
4251 // Cause the above state to be reset.
4252 trans->ResetStateForRestart();
4253
4254 // Verify that the state that needed to be reset, has been reset.
[email protected]9b6fee12009-09-29 18:13:074255 EXPECT_TRUE(trans->read_buf_.get() == NULL);
[email protected]89ceba9a2009-03-21 03:46:064256 EXPECT_EQ(0, trans->read_buf_len_);
[email protected]b94f92d2010-10-27 16:45:204257 EXPECT_TRUE(trans->request_headers_.IsEmpty());
[email protected]0877e3d2009-10-17 22:29:574258 EXPECT_TRUE(response->auth_challenge.get() == NULL);
4259 EXPECT_TRUE(response->headers.get() == NULL);
[email protected]34f40942010-10-04 00:34:044260 EXPECT_FALSE(response->was_cached);
[email protected]0877e3d2009-10-17 22:29:574261 EXPECT_EQ(0, response->ssl_info.cert_status);
4262 EXPECT_FALSE(response->vary_data.is_valid());
[email protected]89ceba9a2009-03-21 03:46:064263}
4264
[email protected]bacff652009-03-31 17:50:334265// Test HTTPS connections to a site with a bad certificate
4266TEST_F(HttpNetworkTransactionTest, HTTPSBadCertificate) {
[email protected]228ff742009-06-05 01:19:594267 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:404268 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:434269 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]bacff652009-03-31 17:50:334270
4271 HttpRequestInfo request;
4272 request.method = "GET";
4273 request.url = GURL("https://www.google.com/");
4274 request.load_flags = 0;
4275
4276 MockWrite data_writes[] = {
4277 MockWrite("GET / HTTP/1.1\r\n"
4278 "Host: www.google.com\r\n"
4279 "Connection: keep-alive\r\n\r\n"),
4280 };
4281
4282 MockRead data_reads[] = {
4283 MockRead("HTTP/1.0 200 OK\r\n"),
4284 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
4285 MockRead("Content-Length: 100\r\n\r\n"),
4286 MockRead(false, OK),
4287 };
4288
[email protected]5ecc992a42009-11-11 01:41:594289 StaticSocketDataProvider ssl_bad_certificate;
[email protected]31a2bfe2010-02-09 08:03:394290 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
4291 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:594292 SSLSocketDataProvider ssl_bad(true, ERR_CERT_AUTHORITY_INVALID);
4293 SSLSocketDataProvider ssl(true, OK);
[email protected]bacff652009-03-31 17:50:334294
[email protected]5ecc992a42009-11-11 01:41:594295 session_deps.socket_factory.AddSocketDataProvider(&ssl_bad_certificate);
4296 session_deps.socket_factory.AddSocketDataProvider(&data);
4297 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl_bad);
4298 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
[email protected]bacff652009-03-31 17:50:334299
4300 TestCompletionCallback callback;
4301
[email protected]5a1d7ca2010-04-28 20:12:274302 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]bacff652009-03-31 17:50:334303 EXPECT_EQ(ERR_IO_PENDING, rv);
4304
4305 rv = callback.WaitForResult();
4306 EXPECT_EQ(ERR_CERT_AUTHORITY_INVALID, rv);
4307
4308 rv = trans->RestartIgnoringLastError(&callback);
4309 EXPECT_EQ(ERR_IO_PENDING, rv);
4310
4311 rv = callback.WaitForResult();
4312 EXPECT_EQ(OK, rv);
4313
4314 const HttpResponseInfo* response = trans->GetResponseInfo();
4315
4316 EXPECT_FALSE(response == NULL);
4317 EXPECT_EQ(100, response->headers->GetContentLength());
4318}
4319
4320// Test HTTPS connections to a site with a bad certificate, going through a
4321// proxy
4322TEST_F(HttpNetworkTransactionTest, HTTPSBadCertificateViaProxy) {
[email protected]81cdfcd2010-10-16 00:49:004323 SessionDependencies session_deps(ProxyService::CreateFixed("myproxy:70"));
[email protected]bacff652009-03-31 17:50:334324
4325 HttpRequestInfo request;
4326 request.method = "GET";
4327 request.url = GURL("https://www.google.com/");
4328 request.load_flags = 0;
4329
4330 MockWrite proxy_writes[] = {
4331 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
[email protected]e44de5d2009-06-05 20:12:454332 "Host: www.google.com\r\n"
4333 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]bacff652009-03-31 17:50:334334 };
4335
4336 MockRead proxy_reads[] = {
4337 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:424338 MockRead(false, OK)
[email protected]bacff652009-03-31 17:50:334339 };
4340
4341 MockWrite data_writes[] = {
4342 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
[email protected]e44de5d2009-06-05 20:12:454343 "Host: www.google.com\r\n"
4344 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]bacff652009-03-31 17:50:334345 MockWrite("GET / HTTP/1.1\r\n"
4346 "Host: www.google.com\r\n"
4347 "Connection: keep-alive\r\n\r\n"),
4348 };
4349
4350 MockRead data_reads[] = {
4351 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
4352 MockRead("HTTP/1.0 200 OK\r\n"),
4353 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
4354 MockRead("Content-Length: 100\r\n\r\n"),
4355 MockRead(false, OK),
4356 };
4357
[email protected]31a2bfe2010-02-09 08:03:394358 StaticSocketDataProvider ssl_bad_certificate(
4359 proxy_reads, arraysize(proxy_reads),
4360 proxy_writes, arraysize(proxy_writes));
4361 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
4362 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:594363 SSLSocketDataProvider ssl_bad(true, ERR_CERT_AUTHORITY_INVALID);
4364 SSLSocketDataProvider ssl(true, OK);
[email protected]bacff652009-03-31 17:50:334365
[email protected]5ecc992a42009-11-11 01:41:594366 session_deps.socket_factory.AddSocketDataProvider(&ssl_bad_certificate);
4367 session_deps.socket_factory.AddSocketDataProvider(&data);
4368 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl_bad);
4369 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
[email protected]bacff652009-03-31 17:50:334370
4371 TestCompletionCallback callback;
4372
4373 for (int i = 0; i < 2; i++) {
[email protected]228ff742009-06-05 01:19:594374 session_deps.socket_factory.ResetNextMockIndexes();
[email protected]bacff652009-03-31 17:50:334375
[email protected]d207a5f2009-06-04 05:28:404376 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:434377 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]bacff652009-03-31 17:50:334378
[email protected]5a1d7ca2010-04-28 20:12:274379 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]bacff652009-03-31 17:50:334380 EXPECT_EQ(ERR_IO_PENDING, rv);
4381
4382 rv = callback.WaitForResult();
4383 EXPECT_EQ(ERR_CERT_AUTHORITY_INVALID, rv);
4384
4385 rv = trans->RestartIgnoringLastError(&callback);
4386 EXPECT_EQ(ERR_IO_PENDING, rv);
4387
4388 rv = callback.WaitForResult();
4389 EXPECT_EQ(OK, rv);
4390
4391 const HttpResponseInfo* response = trans->GetResponseInfo();
4392
4393 EXPECT_FALSE(response == NULL);
4394 EXPECT_EQ(100, response->headers->GetContentLength());
4395 }
4396}
4397
[email protected]2df19bb2010-08-25 20:13:464398
4399// Test HTTPS connections to a site, going through an HTTPS proxy
4400TEST_F(HttpNetworkTransactionTest, HTTPSViaHttpsProxy) {
[email protected]81cdfcd2010-10-16 00:49:004401 SessionDependencies session_deps(ProxyService::CreateFixed("https://proxy:70"));
[email protected]2df19bb2010-08-25 20:13:464402
4403 HttpRequestInfo request;
4404 request.method = "GET";
4405 request.url = GURL("https://www.google.com/");
4406 request.load_flags = 0;
4407
4408 MockWrite data_writes[] = {
4409 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
4410 "Host: www.google.com\r\n"
4411 "Proxy-Connection: keep-alive\r\n\r\n"),
4412 MockWrite("GET / HTTP/1.1\r\n"
4413 "Host: www.google.com\r\n"
4414 "Connection: keep-alive\r\n\r\n"),
4415 };
4416
4417 MockRead data_reads[] = {
4418 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
4419 MockRead("HTTP/1.1 200 OK\r\n"),
4420 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
4421 MockRead("Content-Length: 100\r\n\r\n"),
4422 MockRead(false, OK),
4423 };
4424
4425 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
4426 data_writes, arraysize(data_writes));
4427 SSLSocketDataProvider proxy_ssl(true, OK); // SSL to the proxy
4428 SSLSocketDataProvider tunnel_ssl(true, OK); // SSL through the tunnel
4429
4430 session_deps.socket_factory.AddSocketDataProvider(&data);
4431 session_deps.socket_factory.AddSSLSocketDataProvider(&proxy_ssl);
4432 session_deps.socket_factory.AddSSLSocketDataProvider(&tunnel_ssl);
4433
4434 TestCompletionCallback callback;
4435
4436 scoped_ptr<HttpTransaction> trans(
4437 new HttpNetworkTransaction(CreateSession(&session_deps)));
4438
4439 int rv = trans->Start(&request, &callback, BoundNetLog());
4440 EXPECT_EQ(ERR_IO_PENDING, rv);
4441
4442 rv = callback.WaitForResult();
4443 EXPECT_EQ(OK, rv);
4444 const HttpResponseInfo* response = trans->GetResponseInfo();
4445
4446 ASSERT_FALSE(response == NULL);
4447
4448 EXPECT_TRUE(response->headers->IsKeepAlive());
4449 EXPECT_EQ(200, response->headers->response_code());
4450 EXPECT_EQ(100, response->headers->GetContentLength());
4451 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
4452}
4453
4454// Test HTTPS connections to a site with a bad certificate, going through an
4455// HTTPS proxy
4456TEST_F(HttpNetworkTransactionTest, HTTPSBadCertificateViaHttpsProxy) {
[email protected]81cdfcd2010-10-16 00:49:004457 SessionDependencies session_deps(ProxyService::CreateFixed("https://proxy:70"));
[email protected]2df19bb2010-08-25 20:13:464458
4459 HttpRequestInfo request;
4460 request.method = "GET";
4461 request.url = GURL("https://www.google.com/");
4462 request.load_flags = 0;
4463
4464 // Attempt to fetch the URL from a server with a bad cert
4465 MockWrite bad_cert_writes[] = {
4466 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
4467 "Host: www.google.com\r\n"
4468 "Proxy-Connection: keep-alive\r\n\r\n"),
4469 };
4470
4471 MockRead bad_cert_reads[] = {
4472 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
4473 MockRead(false, OK)
4474 };
4475
4476 // Attempt to fetch the URL with a good cert
4477 MockWrite good_data_writes[] = {
4478 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
4479 "Host: www.google.com\r\n"
4480 "Proxy-Connection: keep-alive\r\n\r\n"),
4481 MockWrite("GET / HTTP/1.1\r\n"
4482 "Host: www.google.com\r\n"
4483 "Connection: keep-alive\r\n\r\n"),
4484 };
4485
4486 MockRead good_cert_reads[] = {
4487 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
4488 MockRead("HTTP/1.0 200 OK\r\n"),
4489 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
4490 MockRead("Content-Length: 100\r\n\r\n"),
4491 MockRead(false, OK),
4492 };
4493
4494 StaticSocketDataProvider ssl_bad_certificate(
4495 bad_cert_reads, arraysize(bad_cert_reads),
4496 bad_cert_writes, arraysize(bad_cert_writes));
4497 StaticSocketDataProvider data(good_cert_reads, arraysize(good_cert_reads),
4498 good_data_writes, arraysize(good_data_writes));
4499 SSLSocketDataProvider ssl_bad(true, ERR_CERT_AUTHORITY_INVALID);
4500 SSLSocketDataProvider ssl(true, OK);
4501
4502 // SSL to the proxy, then CONNECT request, then SSL with bad certificate
4503 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
4504 session_deps.socket_factory.AddSocketDataProvider(&ssl_bad_certificate);
4505 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl_bad);
4506
4507 // SSL to the proxy, then CONNECT request, then valid SSL certificate
4508 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
4509 session_deps.socket_factory.AddSocketDataProvider(&data);
4510 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
4511
4512 TestCompletionCallback callback;
4513
4514 scoped_ptr<HttpTransaction> trans(
4515 new HttpNetworkTransaction(CreateSession(&session_deps)));
4516
4517 int rv = trans->Start(&request, &callback, BoundNetLog());
4518 EXPECT_EQ(ERR_IO_PENDING, rv);
4519
4520 rv = callback.WaitForResult();
4521 EXPECT_EQ(ERR_CERT_AUTHORITY_INVALID, rv);
4522
4523 rv = trans->RestartIgnoringLastError(&callback);
4524 EXPECT_EQ(ERR_IO_PENDING, rv);
4525
4526 rv = callback.WaitForResult();
4527 EXPECT_EQ(OK, rv);
4528
4529 const HttpResponseInfo* response = trans->GetResponseInfo();
4530
4531 EXPECT_FALSE(response == NULL);
4532 EXPECT_EQ(100, response->headers->GetContentLength());
4533}
4534
[email protected]1c773ea12009-04-28 19:58:424535TEST_F(HttpNetworkTransactionTest, BuildRequest_UserAgent) {
[email protected]228ff742009-06-05 01:19:594536 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:404537 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:434538 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]1c773ea12009-04-28 19:58:424539
4540 HttpRequestInfo request;
4541 request.method = "GET";
4542 request.url = GURL("http://www.google.com/");
[email protected]8c76ae22010-04-20 22:15:434543 request.extra_headers.SetHeader(HttpRequestHeaders::kUserAgent,
4544 "Chromium Ultra Awesome X Edition");
[email protected]1c773ea12009-04-28 19:58:424545
4546 MockWrite data_writes[] = {
4547 MockWrite("GET / HTTP/1.1\r\n"
4548 "Host: www.google.com\r\n"
4549 "Connection: keep-alive\r\n"
4550 "User-Agent: Chromium Ultra Awesome X Edition\r\n\r\n"),
4551 };
4552
4553 // Lastly, the server responds with the actual content.
4554 MockRead data_reads[] = {
4555 MockRead("HTTP/1.0 200 OK\r\n"),
4556 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
4557 MockRead("Content-Length: 100\r\n\r\n"),
4558 MockRead(false, OK),
4559 };
4560
[email protected]31a2bfe2010-02-09 08:03:394561 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
4562 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:594563 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:424564
4565 TestCompletionCallback callback;
4566
[email protected]5a1d7ca2010-04-28 20:12:274567 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:424568 EXPECT_EQ(ERR_IO_PENDING, rv);
4569
4570 rv = callback.WaitForResult();
4571 EXPECT_EQ(OK, rv);
4572}
4573
[email protected]da81f132010-08-18 23:39:294574TEST_F(HttpNetworkTransactionTest, BuildRequest_UserAgentOverTunnel) {
[email protected]81cdfcd2010-10-16 00:49:004575 SessionDependencies session_deps(ProxyService::CreateFixed("myproxy:70"));
[email protected]da81f132010-08-18 23:39:294576 scoped_ptr<HttpTransaction> trans(
4577 new HttpNetworkTransaction(CreateSession(&session_deps)));
4578
4579 HttpRequestInfo request;
4580 request.method = "GET";
4581 request.url = GURL("https://www.google.com/");
4582 request.extra_headers.SetHeader(HttpRequestHeaders::kUserAgent,
4583 "Chromium Ultra Awesome X Edition");
4584
4585 MockWrite data_writes[] = {
4586 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
4587 "Host: www.google.com\r\n"
4588 "Proxy-Connection: keep-alive\r\n"
4589 "User-Agent: Chromium Ultra Awesome X Edition\r\n\r\n"),
4590 };
4591 MockRead data_reads[] = {
4592 // Return an error, so the transaction stops here (this test isn't
4593 // interested in the rest).
4594 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
4595 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
4596 MockRead("Proxy-Connection: close\r\n\r\n"),
4597 };
4598
4599 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
4600 data_writes, arraysize(data_writes));
4601 session_deps.socket_factory.AddSocketDataProvider(&data);
4602
4603 TestCompletionCallback callback;
4604
4605 int rv = trans->Start(&request, &callback, BoundNetLog());
4606 EXPECT_EQ(ERR_IO_PENDING, rv);
4607
4608 rv = callback.WaitForResult();
4609 EXPECT_EQ(OK, rv);
4610}
4611
[email protected]1c773ea12009-04-28 19:58:424612TEST_F(HttpNetworkTransactionTest, BuildRequest_Referer) {
[email protected]228ff742009-06-05 01:19:594613 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:404614 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:434615 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]1c773ea12009-04-28 19:58:424616
4617 HttpRequestInfo request;
4618 request.method = "GET";
4619 request.url = GURL("http://www.google.com/");
4620 request.load_flags = 0;
4621 request.referrer = GURL("http://the.previous.site.com/");
4622
4623 MockWrite data_writes[] = {
4624 MockWrite("GET / HTTP/1.1\r\n"
4625 "Host: www.google.com\r\n"
4626 "Connection: keep-alive\r\n"
4627 "Referer: http://the.previous.site.com/\r\n\r\n"),
4628 };
4629
4630 // Lastly, the server responds with the actual content.
4631 MockRead data_reads[] = {
4632 MockRead("HTTP/1.0 200 OK\r\n"),
4633 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
4634 MockRead("Content-Length: 100\r\n\r\n"),
4635 MockRead(false, OK),
4636 };
4637
[email protected]31a2bfe2010-02-09 08:03:394638 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
4639 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:594640 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:424641
4642 TestCompletionCallback callback;
4643
[email protected]5a1d7ca2010-04-28 20:12:274644 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:424645 EXPECT_EQ(ERR_IO_PENDING, rv);
4646
4647 rv = callback.WaitForResult();
4648 EXPECT_EQ(OK, rv);
4649}
4650
4651TEST_F(HttpNetworkTransactionTest, BuildRequest_PostContentLengthZero) {
[email protected]228ff742009-06-05 01:19:594652 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:404653 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:434654 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]1c773ea12009-04-28 19:58:424655
4656 HttpRequestInfo request;
4657 request.method = "POST";
4658 request.url = GURL("http://www.google.com/");
4659
4660 MockWrite data_writes[] = {
4661 MockWrite("POST / HTTP/1.1\r\n"
4662 "Host: www.google.com\r\n"
4663 "Connection: keep-alive\r\n"
4664 "Content-Length: 0\r\n\r\n"),
4665 };
4666
4667 // Lastly, the server responds with the actual content.
4668 MockRead data_reads[] = {
4669 MockRead("HTTP/1.0 200 OK\r\n"),
4670 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
4671 MockRead("Content-Length: 100\r\n\r\n"),
4672 MockRead(false, OK),
4673 };
4674
[email protected]31a2bfe2010-02-09 08:03:394675 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
4676 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:594677 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:424678
4679 TestCompletionCallback callback;
4680
[email protected]5a1d7ca2010-04-28 20:12:274681 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:424682 EXPECT_EQ(ERR_IO_PENDING, rv);
4683
4684 rv = callback.WaitForResult();
4685 EXPECT_EQ(OK, rv);
4686}
4687
4688TEST_F(HttpNetworkTransactionTest, BuildRequest_PutContentLengthZero) {
[email protected]228ff742009-06-05 01:19:594689 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:404690 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:434691 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]1c773ea12009-04-28 19:58:424692
4693 HttpRequestInfo request;
4694 request.method = "PUT";
4695 request.url = GURL("http://www.google.com/");
4696
4697 MockWrite data_writes[] = {
4698 MockWrite("PUT / HTTP/1.1\r\n"
4699 "Host: www.google.com\r\n"
4700 "Connection: keep-alive\r\n"
4701 "Content-Length: 0\r\n\r\n"),
4702 };
4703
4704 // Lastly, the server responds with the actual content.
4705 MockRead data_reads[] = {
4706 MockRead("HTTP/1.0 200 OK\r\n"),
4707 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
4708 MockRead("Content-Length: 100\r\n\r\n"),
4709 MockRead(false, OK),
4710 };
4711
[email protected]31a2bfe2010-02-09 08:03:394712 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
4713 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:594714 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:424715
4716 TestCompletionCallback callback;
4717
[email protected]5a1d7ca2010-04-28 20:12:274718 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:424719 EXPECT_EQ(ERR_IO_PENDING, rv);
4720
4721 rv = callback.WaitForResult();
4722 EXPECT_EQ(OK, rv);
4723}
4724
4725TEST_F(HttpNetworkTransactionTest, BuildRequest_HeadContentLengthZero) {
[email protected]228ff742009-06-05 01:19:594726 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:404727 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:434728 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]1c773ea12009-04-28 19:58:424729
4730 HttpRequestInfo request;
4731 request.method = "HEAD";
4732 request.url = GURL("http://www.google.com/");
4733
4734 MockWrite data_writes[] = {
4735 MockWrite("HEAD / HTTP/1.1\r\n"
4736 "Host: www.google.com\r\n"
4737 "Connection: keep-alive\r\n"
4738 "Content-Length: 0\r\n\r\n"),
4739 };
4740
4741 // Lastly, the server responds with the actual content.
4742 MockRead data_reads[] = {
4743 MockRead("HTTP/1.0 200 OK\r\n"),
4744 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
4745 MockRead("Content-Length: 100\r\n\r\n"),
4746 MockRead(false, OK),
4747 };
4748
[email protected]31a2bfe2010-02-09 08:03:394749 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
4750 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:594751 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:424752
4753 TestCompletionCallback callback;
4754
[email protected]5a1d7ca2010-04-28 20:12:274755 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:424756 EXPECT_EQ(ERR_IO_PENDING, rv);
4757
4758 rv = callback.WaitForResult();
4759 EXPECT_EQ(OK, rv);
4760}
4761
4762TEST_F(HttpNetworkTransactionTest, BuildRequest_CacheControlNoCache) {
[email protected]228ff742009-06-05 01:19:594763 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:404764 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:434765 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]1c773ea12009-04-28 19:58:424766
4767 HttpRequestInfo request;
4768 request.method = "GET";
4769 request.url = GURL("http://www.google.com/");
4770 request.load_flags = LOAD_BYPASS_CACHE;
4771
4772 MockWrite data_writes[] = {
4773 MockWrite("GET / HTTP/1.1\r\n"
4774 "Host: www.google.com\r\n"
4775 "Connection: keep-alive\r\n"
4776 "Pragma: no-cache\r\n"
4777 "Cache-Control: no-cache\r\n\r\n"),
4778 };
4779
4780 // Lastly, the server responds with the actual content.
4781 MockRead data_reads[] = {
4782 MockRead("HTTP/1.0 200 OK\r\n"),
4783 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
4784 MockRead("Content-Length: 100\r\n\r\n"),
4785 MockRead(false, OK),
4786 };
4787
[email protected]31a2bfe2010-02-09 08:03:394788 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
4789 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:594790 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:424791
4792 TestCompletionCallback callback;
4793
[email protected]5a1d7ca2010-04-28 20:12:274794 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:424795 EXPECT_EQ(ERR_IO_PENDING, rv);
4796
4797 rv = callback.WaitForResult();
4798 EXPECT_EQ(OK, rv);
4799}
4800
4801TEST_F(HttpNetworkTransactionTest,
4802 BuildRequest_CacheControlValidateCache) {
[email protected]228ff742009-06-05 01:19:594803 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:404804 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:434805 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]1c773ea12009-04-28 19:58:424806
4807 HttpRequestInfo request;
4808 request.method = "GET";
4809 request.url = GURL("http://www.google.com/");
4810 request.load_flags = LOAD_VALIDATE_CACHE;
4811
4812 MockWrite data_writes[] = {
4813 MockWrite("GET / HTTP/1.1\r\n"
4814 "Host: www.google.com\r\n"
4815 "Connection: keep-alive\r\n"
4816 "Cache-Control: max-age=0\r\n\r\n"),
4817 };
4818
4819 // Lastly, the server responds with the actual content.
4820 MockRead data_reads[] = {
4821 MockRead("HTTP/1.0 200 OK\r\n"),
4822 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
4823 MockRead("Content-Length: 100\r\n\r\n"),
4824 MockRead(false, OK),
4825 };
4826
[email protected]31a2bfe2010-02-09 08:03:394827 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
4828 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:594829 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:424830
4831 TestCompletionCallback callback;
4832
[email protected]5a1d7ca2010-04-28 20:12:274833 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:424834 EXPECT_EQ(ERR_IO_PENDING, rv);
4835
4836 rv = callback.WaitForResult();
4837 EXPECT_EQ(OK, rv);
4838}
4839
4840TEST_F(HttpNetworkTransactionTest, BuildRequest_ExtraHeaders) {
[email protected]228ff742009-06-05 01:19:594841 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:404842 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:434843 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]1c773ea12009-04-28 19:58:424844
4845 HttpRequestInfo request;
4846 request.method = "GET";
4847 request.url = GURL("http://www.google.com/");
[email protected]8c76ae22010-04-20 22:15:434848 request.extra_headers.SetHeader("FooHeader", "Bar");
[email protected]1c773ea12009-04-28 19:58:424849
4850 MockWrite data_writes[] = {
4851 MockWrite("GET / HTTP/1.1\r\n"
4852 "Host: www.google.com\r\n"
4853 "Connection: keep-alive\r\n"
4854 "FooHeader: Bar\r\n\r\n"),
4855 };
4856
4857 // Lastly, the server responds with the actual content.
4858 MockRead data_reads[] = {
4859 MockRead("HTTP/1.0 200 OK\r\n"),
4860 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
4861 MockRead("Content-Length: 100\r\n\r\n"),
4862 MockRead(false, OK),
4863 };
4864
[email protected]31a2bfe2010-02-09 08:03:394865 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
4866 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:594867 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:424868
4869 TestCompletionCallback callback;
4870
[email protected]5a1d7ca2010-04-28 20:12:274871 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:424872 EXPECT_EQ(ERR_IO_PENDING, rv);
4873
4874 rv = callback.WaitForResult();
4875 EXPECT_EQ(OK, rv);
4876}
4877
[email protected]270c6412010-03-29 22:02:474878TEST_F(HttpNetworkTransactionTest, BuildRequest_ExtraHeadersStripped) {
4879 SessionDependencies session_deps;
4880 scoped_ptr<HttpTransaction> trans(
4881 new HttpNetworkTransaction(CreateSession(&session_deps)));
4882
4883 HttpRequestInfo request;
4884 request.method = "GET";
4885 request.url = GURL("http://www.google.com/");
[email protected]8c76ae22010-04-20 22:15:434886 request.extra_headers.SetHeader("referer", "www.foo.com");
4887 request.extra_headers.SetHeader("hEllo", "Kitty");
4888 request.extra_headers.SetHeader("FoO", "bar");
[email protected]270c6412010-03-29 22:02:474889
4890 MockWrite data_writes[] = {
4891 MockWrite("GET / HTTP/1.1\r\n"
4892 "Host: www.google.com\r\n"
4893 "Connection: keep-alive\r\n"
4894 "hEllo: Kitty\r\n"
4895 "FoO: bar\r\n\r\n"),
4896 };
4897
4898 // Lastly, the server responds with the actual content.
4899 MockRead data_reads[] = {
4900 MockRead("HTTP/1.0 200 OK\r\n"),
4901 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
4902 MockRead("Content-Length: 100\r\n\r\n"),
4903 MockRead(false, OK),
4904 };
4905
4906 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
4907 data_writes, arraysize(data_writes));
4908 session_deps.socket_factory.AddSocketDataProvider(&data);
4909
4910 TestCompletionCallback callback;
4911
[email protected]5a1d7ca2010-04-28 20:12:274912 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]270c6412010-03-29 22:02:474913 EXPECT_EQ(ERR_IO_PENDING, rv);
4914
4915 rv = callback.WaitForResult();
4916 EXPECT_EQ(OK, rv);
4917}
4918
[email protected]3cd17242009-06-23 02:59:024919TEST_F(HttpNetworkTransactionTest, SOCKS4_HTTP_GET) {
[email protected]80d6524d2009-08-18 03:58:094920 SessionDependencies session_deps(
[email protected]81cdfcd2010-10-16 00:49:004921 ProxyService::CreateFixed("socks4://myproxy:1080"));
[email protected]3cd17242009-06-23 02:59:024922
4923 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:434924 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]3cd17242009-06-23 02:59:024925
4926 HttpRequestInfo request;
4927 request.method = "GET";
4928 request.url = GURL("http://www.google.com/");
4929 request.load_flags = 0;
4930
4931 char write_buffer[] = { 0x04, 0x01, 0x00, 0x50, 127, 0, 0, 1, 0 };
4932 char read_buffer[] = { 0x00, 0x5A, 0x00, 0x00, 0, 0, 0, 0 };
4933
4934 MockWrite data_writes[] = {
[email protected]e0c27be2009-07-15 13:09:354935 MockWrite(true, write_buffer, arraysize(write_buffer)),
[email protected]3cd17242009-06-23 02:59:024936 MockWrite("GET / HTTP/1.1\r\n"
4937 "Host: www.google.com\r\n"
4938 "Connection: keep-alive\r\n\r\n")
4939 };
4940
4941 MockRead data_reads[] = {
[email protected]5ecc992a42009-11-11 01:41:594942 MockRead(true, read_buffer, arraysize(read_buffer)),
[email protected]3cd17242009-06-23 02:59:024943 MockRead("HTTP/1.0 200 OK\r\n"),
4944 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
4945 MockRead("Payload"),
4946 MockRead(false, OK)
4947 };
4948
[email protected]31a2bfe2010-02-09 08:03:394949 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
4950 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:594951 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]3cd17242009-06-23 02:59:024952
4953 TestCompletionCallback callback;
4954
[email protected]5a1d7ca2010-04-28 20:12:274955 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]3cd17242009-06-23 02:59:024956 EXPECT_EQ(ERR_IO_PENDING, rv);
4957
4958 rv = callback.WaitForResult();
4959 EXPECT_EQ(OK, rv);
4960
4961 const HttpResponseInfo* response = trans->GetResponseInfo();
4962 EXPECT_FALSE(response == NULL);
4963
4964 std::string response_text;
4965 rv = ReadTransaction(trans.get(), &response_text);
4966 EXPECT_EQ(OK, rv);
4967 EXPECT_EQ("Payload", response_text);
4968}
4969
4970TEST_F(HttpNetworkTransactionTest, SOCKS4_SSL_GET) {
[email protected]80d6524d2009-08-18 03:58:094971 SessionDependencies session_deps(
[email protected]81cdfcd2010-10-16 00:49:004972 ProxyService::CreateFixed("socks4://myproxy:1080"));
[email protected]3cd17242009-06-23 02:59:024973
4974 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:434975 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]3cd17242009-06-23 02:59:024976
4977 HttpRequestInfo request;
4978 request.method = "GET";
4979 request.url = GURL("https://www.google.com/");
4980 request.load_flags = 0;
4981
4982 unsigned char write_buffer[] = { 0x04, 0x01, 0x01, 0xBB, 127, 0, 0, 1, 0 };
4983 unsigned char read_buffer[] = { 0x00, 0x5A, 0x00, 0x00, 0, 0, 0, 0 };
4984
4985 MockWrite data_writes[] = {
[email protected]e0c27be2009-07-15 13:09:354986 MockWrite(true, reinterpret_cast<char*>(write_buffer),
4987 arraysize(write_buffer)),
[email protected]3cd17242009-06-23 02:59:024988 MockWrite("GET / HTTP/1.1\r\n"
4989 "Host: www.google.com\r\n"
4990 "Connection: keep-alive\r\n\r\n")
4991 };
4992
4993 MockRead data_reads[] = {
[email protected]e0c27be2009-07-15 13:09:354994 MockWrite(true, reinterpret_cast<char*>(read_buffer),
4995 arraysize(read_buffer)),
4996 MockRead("HTTP/1.0 200 OK\r\n"),
4997 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
4998 MockRead("Payload"),
4999 MockRead(false, OK)
5000 };
5001
[email protected]31a2bfe2010-02-09 08:03:395002 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
5003 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:595004 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]e0c27be2009-07-15 13:09:355005
[email protected]5ecc992a42009-11-11 01:41:595006 SSLSocketDataProvider ssl(true, OK);
5007 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
[email protected]e0c27be2009-07-15 13:09:355008
5009 TestCompletionCallback callback;
5010
[email protected]5a1d7ca2010-04-28 20:12:275011 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]e0c27be2009-07-15 13:09:355012 EXPECT_EQ(ERR_IO_PENDING, rv);
5013
5014 rv = callback.WaitForResult();
5015 EXPECT_EQ(OK, rv);
5016
5017 const HttpResponseInfo* response = trans->GetResponseInfo();
5018 EXPECT_FALSE(response == NULL);
5019
5020 std::string response_text;
5021 rv = ReadTransaction(trans.get(), &response_text);
5022 EXPECT_EQ(OK, rv);
5023 EXPECT_EQ("Payload", response_text);
5024}
5025
5026TEST_F(HttpNetworkTransactionTest, SOCKS5_HTTP_GET) {
[email protected]80d6524d2009-08-18 03:58:095027 SessionDependencies session_deps(
[email protected]81cdfcd2010-10-16 00:49:005028 ProxyService::CreateFixed("socks5://myproxy:1080"));
[email protected]e0c27be2009-07-15 13:09:355029
5030 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:435031 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]e0c27be2009-07-15 13:09:355032
5033 HttpRequestInfo request;
5034 request.method = "GET";
5035 request.url = GURL("http://www.google.com/");
5036 request.load_flags = 0;
5037
5038 const char kSOCKS5GreetRequest[] = { 0x05, 0x01, 0x00 };
5039 const char kSOCKS5GreetResponse[] = { 0x05, 0x00 };
[email protected]f209dba2009-12-18 00:24:375040 const char kSOCKS5OkRequest[] = {
5041 0x05, // Version
5042 0x01, // Command (CONNECT)
5043 0x00, // Reserved.
5044 0x03, // Address type (DOMAINNAME).
5045 0x0E, // Length of domain (14)
5046 // Domain string:
5047 'w', 'w', 'w', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'c', 'o', 'm',
5048 0x00, 0x50, // 16-bit port (80)
5049 };
[email protected]e0c27be2009-07-15 13:09:355050 const char kSOCKS5OkResponse[] =
5051 { 0x05, 0x00, 0x00, 0x01, 127, 0, 0, 1, 0x00, 0x50 };
5052
5053 MockWrite data_writes[] = {
5054 MockWrite(true, kSOCKS5GreetRequest, arraysize(kSOCKS5GreetRequest)),
5055 MockWrite(true, kSOCKS5OkRequest, arraysize(kSOCKS5OkRequest)),
5056 MockWrite("GET / HTTP/1.1\r\n"
5057 "Host: www.google.com\r\n"
5058 "Connection: keep-alive\r\n\r\n")
5059 };
5060
5061 MockRead data_reads[] = {
5062 MockWrite(true, kSOCKS5GreetResponse, arraysize(kSOCKS5GreetResponse)),
5063 MockWrite(true, kSOCKS5OkResponse, arraysize(kSOCKS5OkResponse)),
5064 MockRead("HTTP/1.0 200 OK\r\n"),
5065 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
5066 MockRead("Payload"),
5067 MockRead(false, OK)
5068 };
5069
[email protected]31a2bfe2010-02-09 08:03:395070 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
5071 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:595072 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]e0c27be2009-07-15 13:09:355073
5074 TestCompletionCallback callback;
5075
[email protected]5a1d7ca2010-04-28 20:12:275076 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]e0c27be2009-07-15 13:09:355077 EXPECT_EQ(ERR_IO_PENDING, rv);
5078
5079 rv = callback.WaitForResult();
5080 EXPECT_EQ(OK, rv);
5081
5082 const HttpResponseInfo* response = trans->GetResponseInfo();
5083 EXPECT_FALSE(response == NULL);
5084
5085 std::string response_text;
5086 rv = ReadTransaction(trans.get(), &response_text);
5087 EXPECT_EQ(OK, rv);
5088 EXPECT_EQ("Payload", response_text);
5089}
5090
5091TEST_F(HttpNetworkTransactionTest, SOCKS5_SSL_GET) {
[email protected]80d6524d2009-08-18 03:58:095092 SessionDependencies session_deps(
[email protected]81cdfcd2010-10-16 00:49:005093 ProxyService::CreateFixed("socks5://myproxy:1080"));
[email protected]e0c27be2009-07-15 13:09:355094
5095 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:435096 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]e0c27be2009-07-15 13:09:355097
5098 HttpRequestInfo request;
5099 request.method = "GET";
5100 request.url = GURL("https://www.google.com/");
5101 request.load_flags = 0;
5102
5103 const char kSOCKS5GreetRequest[] = { 0x05, 0x01, 0x00 };
5104 const char kSOCKS5GreetResponse[] = { 0x05, 0x00 };
[email protected]f209dba2009-12-18 00:24:375105 const unsigned char kSOCKS5OkRequest[] = {
5106 0x05, // Version
5107 0x01, // Command (CONNECT)
5108 0x00, // Reserved.
5109 0x03, // Address type (DOMAINNAME).
5110 0x0E, // Length of domain (14)
5111 // Domain string:
5112 'w', 'w', 'w', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'c', 'o', 'm',
5113 0x01, 0xBB, // 16-bit port (443)
5114 };
5115
[email protected]e0c27be2009-07-15 13:09:355116 const char kSOCKS5OkResponse[] =
5117 { 0x05, 0x00, 0x00, 0x01, 0, 0, 0, 0, 0x00, 0x00 };
5118
5119 MockWrite data_writes[] = {
5120 MockWrite(true, kSOCKS5GreetRequest, arraysize(kSOCKS5GreetRequest)),
5121 MockWrite(true, reinterpret_cast<const char*>(kSOCKS5OkRequest),
5122 arraysize(kSOCKS5OkRequest)),
5123 MockWrite("GET / HTTP/1.1\r\n"
5124 "Host: www.google.com\r\n"
5125 "Connection: keep-alive\r\n\r\n")
5126 };
5127
5128 MockRead data_reads[] = {
5129 MockWrite(true, kSOCKS5GreetResponse, arraysize(kSOCKS5GreetResponse)),
5130 MockWrite(true, kSOCKS5OkResponse, arraysize(kSOCKS5OkResponse)),
[email protected]3cd17242009-06-23 02:59:025131 MockRead("HTTP/1.0 200 OK\r\n"),
5132 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
5133 MockRead("Payload"),
5134 MockRead(false, OK)
5135 };
5136
[email protected]31a2bfe2010-02-09 08:03:395137 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
5138 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:595139 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]3cd17242009-06-23 02:59:025140
[email protected]5ecc992a42009-11-11 01:41:595141 SSLSocketDataProvider ssl(true, OK);
5142 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
[email protected]3cd17242009-06-23 02:59:025143
5144 TestCompletionCallback callback;
5145
[email protected]5a1d7ca2010-04-28 20:12:275146 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]3cd17242009-06-23 02:59:025147 EXPECT_EQ(ERR_IO_PENDING, rv);
5148
5149 rv = callback.WaitForResult();
5150 EXPECT_EQ(OK, rv);
5151
5152 const HttpResponseInfo* response = trans->GetResponseInfo();
5153 EXPECT_FALSE(response == NULL);
5154
5155 std::string response_text;
5156 rv = ReadTransaction(trans.get(), &response_text);
5157 EXPECT_EQ(OK, rv);
5158 EXPECT_EQ("Payload", response_text);
5159}
5160
[email protected]04e5be32009-06-26 20:00:315161// Tests that for connection endpoints the group names are correctly set.
[email protected]2d731a32010-04-29 01:04:065162
5163struct GroupNameTest {
5164 std::string proxy_server;
5165 std::string url;
5166 std::string expected_group_name;
[email protected]e60e47a2010-07-14 03:37:185167 bool ssl;
[email protected]2d731a32010-04-29 01:04:065168};
5169
5170scoped_refptr<HttpNetworkSession> SetupSessionForGroupNameTests(
5171 const std::string& proxy_server) {
[email protected]81cdfcd2010-10-16 00:49:005172 SessionDependencies session_deps(ProxyService::CreateFixed(proxy_server));
[email protected]2d731a32010-04-29 01:04:065173 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
5174
5175 HttpAlternateProtocols* alternate_protocols =
5176 session->mutable_alternate_protocols();
5177 alternate_protocols->SetAlternateProtocolFor(
5178 HostPortPair("host.with.alternate", 80), 443,
[email protected]dae22c52010-07-30 02:16:355179 HttpAlternateProtocols::NPN_SPDY_2);
[email protected]2d731a32010-04-29 01:04:065180
5181 return session;
5182}
5183
5184int GroupNameTransactionHelper(
5185 const std::string& url,
5186 const scoped_refptr<HttpNetworkSession>& session) {
5187 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
5188
5189 HttpRequestInfo request;
5190 request.method = "GET";
5191 request.url = GURL(url);
5192 request.load_flags = 0;
5193
5194 TestCompletionCallback callback;
5195
5196 // We do not complete this request, the dtor will clean the transaction up.
5197 return trans->Start(&request, &callback, BoundNetLog());
5198}
5199
5200TEST_F(HttpNetworkTransactionTest, GroupNameForDirectConnections) {
5201 const GroupNameTest tests[] = {
[email protected]04e5be32009-06-26 20:00:315202 {
[email protected]2d731a32010-04-29 01:04:065203 "", // unused
[email protected]04e5be32009-06-26 20:00:315204 "http://www.google.com/direct",
[email protected]2ff8b312010-04-26 22:20:545205 "www.google.com:80",
[email protected]e60e47a2010-07-14 03:37:185206 false,
[email protected]2ff8b312010-04-26 22:20:545207 },
5208 {
[email protected]2d731a32010-04-29 01:04:065209 "", // unused
[email protected]2ff8b312010-04-26 22:20:545210 "http://[2001:1418:13:1::25]/direct",
5211 "[2001:1418:13:1::25]:80",
[email protected]e60e47a2010-07-14 03:37:185212 false,
[email protected]04e5be32009-06-26 20:00:315213 },
[email protected]04e5be32009-06-26 20:00:315214
5215 // SSL Tests
5216 {
[email protected]2d731a32010-04-29 01:04:065217 "", // unused
[email protected]04e5be32009-06-26 20:00:315218 "https://www.google.com/direct_ssl",
[email protected]0e88ad602010-05-04 23:47:025219 "ssl/www.google.com:443",
[email protected]e60e47a2010-07-14 03:37:185220 true,
[email protected]04e5be32009-06-26 20:00:315221 },
5222 {
[email protected]2d731a32010-04-29 01:04:065223 "", // unused
5224 "https://[2001:1418:13:1::25]/direct",
[email protected]0e88ad602010-05-04 23:47:025225 "ssl/[2001:1418:13:1::25]:443",
[email protected]e60e47a2010-07-14 03:37:185226 true,
[email protected]04e5be32009-06-26 20:00:315227 },
5228 {
[email protected]2d731a32010-04-29 01:04:065229 "", // unused
[email protected]2ff8b312010-04-26 22:20:545230 "http://host.with.alternate/direct",
[email protected]0e88ad602010-05-04 23:47:025231 "ssl/host.with.alternate:443",
[email protected]e60e47a2010-07-14 03:37:185232 true,
[email protected]2ff8b312010-04-26 22:20:545233 },
[email protected]2d731a32010-04-29 01:04:065234 };
[email protected]2ff8b312010-04-26 22:20:545235
[email protected]8e6441ca2010-08-19 05:56:385236 HttpStreamFactory::set_use_alternate_protocols(true);
[email protected]2d731a32010-04-29 01:04:065237
5238 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) {
5239 scoped_refptr<HttpNetworkSession> session(
5240 SetupSessionForGroupNameTests(tests[i].proxy_server));
5241
5242 HttpNetworkSessionPeer peer(session);
[email protected]2431756e2010-09-29 20:26:135243 CaptureGroupNameTCPSocketPool* tcp_conn_pool =
5244 new CaptureGroupNameTCPSocketPool(session);
[email protected]2d731a32010-04-29 01:04:065245 peer.SetTCPSocketPool(tcp_conn_pool);
[email protected]2431756e2010-09-29 20:26:135246 CaptureGroupNameSSLSocketPool* ssl_conn_pool =
5247 new CaptureGroupNameSSLSocketPool(session.get());
[email protected]e60e47a2010-07-14 03:37:185248 peer.SetSSLSocketPool(ssl_conn_pool);
[email protected]2d731a32010-04-29 01:04:065249
5250 EXPECT_EQ(ERR_IO_PENDING,
5251 GroupNameTransactionHelper(tests[i].url, session));
[email protected]e60e47a2010-07-14 03:37:185252 if (tests[i].ssl)
5253 EXPECT_EQ(tests[i].expected_group_name,
5254 ssl_conn_pool->last_group_name_received());
5255 else
5256 EXPECT_EQ(tests[i].expected_group_name,
5257 tcp_conn_pool->last_group_name_received());
[email protected]2d731a32010-04-29 01:04:065258 }
5259
[email protected]8e6441ca2010-08-19 05:56:385260 HttpStreamFactory::set_use_alternate_protocols(false);
[email protected]2d731a32010-04-29 01:04:065261}
5262
5263TEST_F(HttpNetworkTransactionTest, GroupNameForHTTPProxyConnections) {
5264 const GroupNameTest tests[] = {
5265 {
5266 "http_proxy",
5267 "http://www.google.com/http_proxy_normal",
5268 "www.google.com:80",
[email protected]e60e47a2010-07-14 03:37:185269 false,
[email protected]2d731a32010-04-29 01:04:065270 },
5271
5272 // SSL Tests
5273 {
5274 "http_proxy",
5275 "https://www.google.com/http_connect_ssl",
[email protected]0e88ad602010-05-04 23:47:025276 "ssl/www.google.com:443",
[email protected]e60e47a2010-07-14 03:37:185277 true,
[email protected]2d731a32010-04-29 01:04:065278 },
[email protected]af3490e2010-10-16 21:02:295279
[email protected]9faeded92010-04-29 20:03:055280 {
5281 "http_proxy",
5282 "http://host.with.alternate/direct",
[email protected]0e88ad602010-05-04 23:47:025283 "ssl/host.with.alternate:443",
[email protected]e60e47a2010-07-14 03:37:185284 true,
[email protected]9faeded92010-04-29 20:03:055285 },
[email protected]2d731a32010-04-29 01:04:065286 };
5287
[email protected]8e6441ca2010-08-19 05:56:385288 HttpStreamFactory::set_use_alternate_protocols(true);
[email protected]2d731a32010-04-29 01:04:065289
5290 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) {
5291 scoped_refptr<HttpNetworkSession> session(
5292 SetupSessionForGroupNameTests(tests[i].proxy_server));
5293
5294 HttpNetworkSessionPeer peer(session);
5295
[email protected]e60e47a2010-07-14 03:37:185296 HostPortPair proxy_host("http_proxy", 80);
[email protected]2431756e2010-09-29 20:26:135297 CaptureGroupNameHttpProxySocketPool* http_proxy_pool =
5298 new CaptureGroupNameHttpProxySocketPool(session);
[email protected]e60e47a2010-07-14 03:37:185299 peer.SetSocketPoolForHTTPProxy(proxy_host, http_proxy_pool);
[email protected]2431756e2010-09-29 20:26:135300 CaptureGroupNameSSLSocketPool* ssl_conn_pool =
5301 new CaptureGroupNameSSLSocketPool(session);
[email protected]e60e47a2010-07-14 03:37:185302 peer.SetSocketPoolForSSLWithProxy(proxy_host, ssl_conn_pool);
[email protected]2d731a32010-04-29 01:04:065303
5304 EXPECT_EQ(ERR_IO_PENDING,
5305 GroupNameTransactionHelper(tests[i].url, session));
[email protected]e60e47a2010-07-14 03:37:185306 if (tests[i].ssl)
5307 EXPECT_EQ(tests[i].expected_group_name,
5308 ssl_conn_pool->last_group_name_received());
5309 else
5310 EXPECT_EQ(tests[i].expected_group_name,
5311 http_proxy_pool->last_group_name_received());
[email protected]2d731a32010-04-29 01:04:065312 }
5313
[email protected]8e6441ca2010-08-19 05:56:385314 HttpStreamFactory::set_use_alternate_protocols(false);
[email protected]2d731a32010-04-29 01:04:065315}
5316
5317TEST_F(HttpNetworkTransactionTest, GroupNameForSOCKSConnections) {
5318 const GroupNameTest tests[] = {
5319 {
5320 "socks4://socks_proxy:1080",
5321 "http://www.google.com/socks4_direct",
5322 "socks4/www.google.com:80",
[email protected]e60e47a2010-07-14 03:37:185323 false,
[email protected]2d731a32010-04-29 01:04:065324 },
5325 {
5326 "socks5://socks_proxy:1080",
5327 "http://www.google.com/socks5_direct",
5328 "socks5/www.google.com:80",
[email protected]e60e47a2010-07-14 03:37:185329 false,
[email protected]2d731a32010-04-29 01:04:065330 },
5331
5332 // SSL Tests
5333 {
5334 "socks4://socks_proxy:1080",
5335 "https://www.google.com/socks4_ssl",
[email protected]0e88ad602010-05-04 23:47:025336 "socks4/ssl/www.google.com:443",
[email protected]e60e47a2010-07-14 03:37:185337 true,
[email protected]2d731a32010-04-29 01:04:065338 },
5339 {
5340 "socks5://socks_proxy:1080",
5341 "https://www.google.com/socks5_ssl",
[email protected]0e88ad602010-05-04 23:47:025342 "socks5/ssl/www.google.com:443",
[email protected]e60e47a2010-07-14 03:37:185343 true,
[email protected]2d731a32010-04-29 01:04:065344 },
[email protected]af3490e2010-10-16 21:02:295345
[email protected]9faeded92010-04-29 20:03:055346 {
5347 "socks4://socks_proxy:1080",
5348 "http://host.with.alternate/direct",
[email protected]0e88ad602010-05-04 23:47:025349 "socks4/ssl/host.with.alternate:443",
[email protected]e60e47a2010-07-14 03:37:185350 true,
[email protected]9faeded92010-04-29 20:03:055351 },
[email protected]04e5be32009-06-26 20:00:315352 };
5353
[email protected]8e6441ca2010-08-19 05:56:385354 HttpStreamFactory::set_use_alternate_protocols(true);
[email protected]2ff8b312010-04-26 22:20:545355
[email protected]04e5be32009-06-26 20:00:315356 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) {
[email protected]2d731a32010-04-29 01:04:065357 scoped_refptr<HttpNetworkSession> session(
5358 SetupSessionForGroupNameTests(tests[i].proxy_server));
5359 HttpNetworkSessionPeer peer(session);
[email protected]04e5be32009-06-26 20:00:315360
[email protected]e60e47a2010-07-14 03:37:185361 HostPortPair proxy_host("socks_proxy", 1080);
[email protected]2431756e2010-09-29 20:26:135362 CaptureGroupNameSOCKSSocketPool* socks_conn_pool =
5363 new CaptureGroupNameSOCKSSocketPool(session);
[email protected]e60e47a2010-07-14 03:37:185364 peer.SetSocketPoolForSOCKSProxy(proxy_host, socks_conn_pool);
[email protected]2431756e2010-09-29 20:26:135365 CaptureGroupNameSSLSocketPool* ssl_conn_pool =
5366 new CaptureGroupNameSSLSocketPool(session);
[email protected]e60e47a2010-07-14 03:37:185367 peer.SetSocketPoolForSSLWithProxy(proxy_host, ssl_conn_pool);
[email protected]04e5be32009-06-26 20:00:315368
[email protected]5695b8c2009-09-30 21:36:435369 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]04e5be32009-06-26 20:00:315370
[email protected]2d731a32010-04-29 01:04:065371 EXPECT_EQ(ERR_IO_PENDING,
5372 GroupNameTransactionHelper(tests[i].url, session));
[email protected]e60e47a2010-07-14 03:37:185373 if (tests[i].ssl)
5374 EXPECT_EQ(tests[i].expected_group_name,
5375 ssl_conn_pool->last_group_name_received());
5376 else
5377 EXPECT_EQ(tests[i].expected_group_name,
5378 socks_conn_pool->last_group_name_received());
[email protected]04e5be32009-06-26 20:00:315379 }
[email protected]2ff8b312010-04-26 22:20:545380
[email protected]8e6441ca2010-08-19 05:56:385381 HttpStreamFactory::set_use_alternate_protocols(false);
[email protected]04e5be32009-06-26 20:00:315382}
5383
[email protected]9172a982009-06-06 00:30:255384TEST_F(HttpNetworkTransactionTest, ReconsiderProxyAfterFailedConnection) {
[email protected]5c6a17e2009-06-10 00:54:545385 SessionDependencies session_deps(
[email protected]81cdfcd2010-10-16 00:49:005386 ProxyService::CreateFixed("myproxy:70;foobar:80"));
[email protected]b59ff372009-07-15 22:04:325387
[email protected]69719062010-01-05 20:09:215388 // This simulates failure resolving all hostnames; that means we will fail
5389 // connecting to both proxies (myproxy:70 and foobar:80).
[email protected]b59ff372009-07-15 22:04:325390 session_deps.host_resolver->rules()->AddSimulatedFailure("*");
5391
[email protected]9172a982009-06-06 00:30:255392 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:435393 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]9172a982009-06-06 00:30:255394
5395 HttpRequestInfo request;
5396 request.method = "GET";
5397 request.url = GURL("http://www.google.com/");
5398
5399 TestCompletionCallback callback;
5400
[email protected]5a1d7ca2010-04-28 20:12:275401 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]9172a982009-06-06 00:30:255402 EXPECT_EQ(ERR_IO_PENDING, rv);
5403
[email protected]9172a982009-06-06 00:30:255404 rv = callback.WaitForResult();
[email protected]f7fccee2010-09-16 20:53:015405 EXPECT_EQ(ERR_PROXY_CONNECTION_FAILED, rv);
[email protected]9172a982009-06-06 00:30:255406}
5407
[email protected]f3e6c1e2009-06-15 20:52:125408// Host resolution observer used by
5409// HttpNetworkTransactionTest.ResolveMadeWithReferrer to check that host
5410// resovle requests are issued with a referrer of |expected_referrer|.
5411class ResolutionReferrerObserver : public HostResolver::Observer {
5412 public:
5413 explicit ResolutionReferrerObserver(const GURL& expected_referrer)
5414 : expected_referrer_(expected_referrer),
5415 called_start_with_referrer_(false),
5416 called_finish_with_referrer_(false) {
5417 }
5418
5419 virtual void OnStartResolution(int id,
5420 const HostResolver::RequestInfo& info) {
5421 if (info.referrer() == expected_referrer_)
5422 called_start_with_referrer_ = true;
5423 }
5424
5425 virtual void OnFinishResolutionWithStatus(
5426 int id, bool was_resolved, const HostResolver::RequestInfo& info ) {
5427 if (info.referrer() == expected_referrer_)
5428 called_finish_with_referrer_ = true;
5429 }
5430
[email protected]eb255d32009-06-17 02:11:035431 virtual void OnCancelResolution(int id,
5432 const HostResolver::RequestInfo& info ) {
5433 FAIL() << "Should not be cancelling any requests!";
5434 }
5435
[email protected]f3e6c1e2009-06-15 20:52:125436 bool did_complete_with_expected_referrer() const {
5437 return called_start_with_referrer_ && called_finish_with_referrer_;
5438 }
5439
5440 private:
5441 GURL expected_referrer_;
5442 bool called_start_with_referrer_;
5443 bool called_finish_with_referrer_;
5444
5445 DISALLOW_COPY_AND_ASSIGN(ResolutionReferrerObserver);
5446};
5447
5448// Make sure that when HostResolver::Resolve() is invoked, it passes through
5449// the "referrer". This is depended on by the DNS prefetch observer.
5450TEST_F(HttpNetworkTransactionTest, ResolveMadeWithReferrer) {
5451 GURL referrer = GURL("http://expected-referrer/");
5452 EXPECT_TRUE(referrer.is_valid());
5453 ResolutionReferrerObserver resolution_observer(referrer);
5454
5455 SessionDependencies session_deps;
5456 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(
[email protected]5695b8c2009-09-30 21:36:435457 CreateSession(&session_deps)));
[email protected]f3e6c1e2009-06-15 20:52:125458
5459 // Attach an observer to watch the host resolutions being made.
[email protected]94a0d3d92009-06-27 01:50:145460 session_deps.host_resolver->AddObserver(&resolution_observer);
[email protected]f3e6c1e2009-06-15 20:52:125461
5462 // Connect up a mock socket which will fail when reading.
5463 MockRead data_reads[] = {
5464 MockRead(false, ERR_FAILED),
5465 };
[email protected]31a2bfe2010-02-09 08:03:395466 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:595467 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]f3e6c1e2009-06-15 20:52:125468
5469 // Issue a request, containing an HTTP referrer.
5470 HttpRequestInfo request;
5471 request.method = "GET";
5472 request.referrer = referrer;
5473 request.url = GURL("http://www.google.com/");
5474
5475 // Run the request until it fails reading from the socket.
5476 TestCompletionCallback callback;
[email protected]5a1d7ca2010-04-28 20:12:275477 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]f3e6c1e2009-06-15 20:52:125478 EXPECT_EQ(ERR_IO_PENDING, rv);
5479 rv = callback.WaitForResult();
5480 EXPECT_EQ(ERR_FAILED, rv);
5481
5482 // Check that the host resolution observer saw |referrer|.
5483 EXPECT_TRUE(resolution_observer.did_complete_with_expected_referrer());
5484}
5485
[email protected]685af592010-05-11 19:31:245486// Base test to make sure that when the load flags for a request specify to
5487// bypass the cache, the DNS cache is not used.
5488void BypassHostCacheOnRefreshHelper(int load_flags) {
[email protected]3b9cca42009-06-16 01:08:285489 SessionDependencies session_deps;
[email protected]b59ff372009-07-15 22:04:325490
[email protected]a2c2fb92009-07-18 07:31:045491 // Select a host resolver that does caching.
[email protected]73c45322010-10-01 23:57:545492 session_deps.host_resolver.reset(new MockCachingHostResolver);
[email protected]b59ff372009-07-15 22:04:325493
[email protected]3b9cca42009-06-16 01:08:285494 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(
[email protected]5695b8c2009-09-30 21:36:435495 CreateSession(&session_deps)));
[email protected]3b9cca42009-06-16 01:08:285496
5497 // Warm up the host cache so it has an entry for "www.google.com" (by doing
5498 // a synchronous lookup.)
5499 AddressList addrlist;
[email protected]94a0d3d92009-06-27 01:50:145500 int rv = session_deps.host_resolver->Resolve(
[email protected]930cc742010-09-15 22:54:105501 HostResolver::RequestInfo(HostPortPair("www.google.com", 80)), &addrlist,
[email protected]5a1d7ca2010-04-28 20:12:275502 NULL, NULL, BoundNetLog());
[email protected]3b9cca42009-06-16 01:08:285503 EXPECT_EQ(OK, rv);
5504
5505 // Verify that it was added to host cache, by doing a subsequent async lookup
5506 // and confirming it completes synchronously.
5507 TestCompletionCallback resolve_callback;
[email protected]684970b2009-08-14 04:54:465508 rv = session_deps.host_resolver->Resolve(
[email protected]930cc742010-09-15 22:54:105509 HostResolver::RequestInfo(HostPortPair("www.google.com", 80)), &addrlist,
[email protected]5a1d7ca2010-04-28 20:12:275510 &resolve_callback, NULL, BoundNetLog());
[email protected]b59ff372009-07-15 22:04:325511 ASSERT_EQ(OK, rv);
[email protected]3b9cca42009-06-16 01:08:285512
5513 // Inject a failure the next time that "www.google.com" is resolved. This way
5514 // we can tell if the next lookup hit the cache, or the "network".
5515 // (cache --> success, "network" --> failure).
[email protected]b59ff372009-07-15 22:04:325516 session_deps.host_resolver->rules()->AddSimulatedFailure("www.google.com");
[email protected]3b9cca42009-06-16 01:08:285517
5518 // Connect up a mock socket which will fail with ERR_UNEXPECTED during the
5519 // first read -- this won't be reached as the host resolution will fail first.
5520 MockRead data_reads[] = { MockRead(false, ERR_UNEXPECTED) };
[email protected]31a2bfe2010-02-09 08:03:395521 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:595522 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]3b9cca42009-06-16 01:08:285523
5524 // Issue a request, asking to bypass the cache(s).
5525 HttpRequestInfo request;
5526 request.method = "GET";
[email protected]685af592010-05-11 19:31:245527 request.load_flags = load_flags;
[email protected]3b9cca42009-06-16 01:08:285528 request.url = GURL("http://www.google.com/");
5529
5530 // Run the request.
5531 TestCompletionCallback callback;
[email protected]5a1d7ca2010-04-28 20:12:275532 rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]3b9cca42009-06-16 01:08:285533 ASSERT_EQ(ERR_IO_PENDING, rv);
5534 rv = callback.WaitForResult();
5535
5536 // If we bypassed the cache, we would have gotten a failure while resolving
5537 // "www.google.com".
5538 EXPECT_EQ(ERR_NAME_NOT_RESOLVED, rv);
5539}
5540
[email protected]685af592010-05-11 19:31:245541// There are multiple load flags that should trigger the host cache bypass.
5542// Test each in isolation:
5543TEST_F(HttpNetworkTransactionTest, BypassHostCacheOnRefresh1) {
5544 BypassHostCacheOnRefreshHelper(LOAD_BYPASS_CACHE);
5545}
5546
5547TEST_F(HttpNetworkTransactionTest, BypassHostCacheOnRefresh2) {
5548 BypassHostCacheOnRefreshHelper(LOAD_VALIDATE_CACHE);
5549}
5550
5551TEST_F(HttpNetworkTransactionTest, BypassHostCacheOnRefresh3) {
5552 BypassHostCacheOnRefreshHelper(LOAD_DISABLE_CACHE);
5553}
5554
[email protected]0877e3d2009-10-17 22:29:575555// Make sure we can handle an error when writing the request.
5556TEST_F(HttpNetworkTransactionTest, RequestWriteError) {
5557 SessionDependencies session_deps;
[email protected]ad8e04a2010-11-01 04:16:275558 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]0877e3d2009-10-17 22:29:575559
5560 HttpRequestInfo request;
5561 request.method = "GET";
5562 request.url = GURL("http://www.foo.com/");
5563 request.load_flags = 0;
5564
5565 MockWrite write_failure[] = {
5566 MockWrite(true, ERR_CONNECTION_RESET),
5567 };
[email protected]31a2bfe2010-02-09 08:03:395568 StaticSocketDataProvider data(NULL, 0,
5569 write_failure, arraysize(write_failure));
[email protected]5ecc992a42009-11-11 01:41:595570 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]0877e3d2009-10-17 22:29:575571
5572 TestCompletionCallback callback;
5573
5574 scoped_ptr<HttpTransaction> trans(
5575 new HttpNetworkTransaction(CreateSession(&session_deps)));
5576
[email protected]5a1d7ca2010-04-28 20:12:275577 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]0877e3d2009-10-17 22:29:575578 EXPECT_EQ(ERR_IO_PENDING, rv);
5579
5580 rv = callback.WaitForResult();
5581 EXPECT_EQ(ERR_CONNECTION_RESET, rv);
5582}
5583
5584// Check that a connection closed after the start of the headers finishes ok.
5585TEST_F(HttpNetworkTransactionTest, ConnectionClosedAfterStartOfHeaders) {
5586 SessionDependencies session_deps;
[email protected]ad8e04a2010-11-01 04:16:275587 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]0877e3d2009-10-17 22:29:575588
5589 HttpRequestInfo request;
5590 request.method = "GET";
5591 request.url = GURL("http://www.foo.com/");
5592 request.load_flags = 0;
5593
5594 MockRead data_reads[] = {
5595 MockRead("HTTP/1."),
5596 MockRead(false, OK),
5597 };
5598
[email protected]31a2bfe2010-02-09 08:03:395599 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:595600 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]0877e3d2009-10-17 22:29:575601
5602 TestCompletionCallback callback;
5603
5604 scoped_ptr<HttpTransaction> trans(
5605 new HttpNetworkTransaction(CreateSession(&session_deps)));
5606
[email protected]5a1d7ca2010-04-28 20:12:275607 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]0877e3d2009-10-17 22:29:575608 EXPECT_EQ(ERR_IO_PENDING, rv);
5609
5610 rv = callback.WaitForResult();
5611 EXPECT_EQ(OK, rv);
5612
5613 const HttpResponseInfo* response = trans->GetResponseInfo();
5614 EXPECT_TRUE(response != NULL);
5615
5616 EXPECT_TRUE(response->headers != NULL);
5617 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
5618
5619 std::string response_data;
5620 rv = ReadTransaction(trans.get(), &response_data);
5621 EXPECT_EQ(OK, rv);
5622 EXPECT_EQ("", response_data);
5623}
5624
5625// Make sure that a dropped connection while draining the body for auth
5626// restart does the right thing.
5627TEST_F(HttpNetworkTransactionTest, DrainResetOK) {
5628 SessionDependencies session_deps;
[email protected]ad8e04a2010-11-01 04:16:275629 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]0877e3d2009-10-17 22:29:575630
5631 HttpRequestInfo request;
5632 request.method = "GET";
5633 request.url = GURL("http://www.google.com/");
5634 request.load_flags = 0;
5635
5636 MockWrite data_writes1[] = {
5637 MockWrite("GET / HTTP/1.1\r\n"
5638 "Host: www.google.com\r\n"
5639 "Connection: keep-alive\r\n\r\n"),
5640 };
5641
5642 MockRead data_reads1[] = {
5643 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
5644 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
5645 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
5646 MockRead("Content-Length: 14\r\n\r\n"),
5647 MockRead("Unauth"),
5648 MockRead(true, ERR_CONNECTION_RESET),
5649 };
5650
[email protected]31a2bfe2010-02-09 08:03:395651 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
5652 data_writes1, arraysize(data_writes1));
[email protected]5ecc992a42009-11-11 01:41:595653 session_deps.socket_factory.AddSocketDataProvider(&data1);
[email protected]0877e3d2009-10-17 22:29:575654
5655 // After calling trans->RestartWithAuth(), this is the request we should
5656 // be issuing -- the final header line contains the credentials.
5657 MockWrite data_writes2[] = {
5658 MockWrite("GET / HTTP/1.1\r\n"
5659 "Host: www.google.com\r\n"
5660 "Connection: keep-alive\r\n"
5661 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
5662 };
5663
5664 // Lastly, the server responds with the actual content.
5665 MockRead data_reads2[] = {
5666 MockRead("HTTP/1.1 200 OK\r\n"),
5667 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
5668 MockRead("Content-Length: 100\r\n\r\n"),
5669 MockRead(false, OK),
5670 };
5671
[email protected]31a2bfe2010-02-09 08:03:395672 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
5673 data_writes2, arraysize(data_writes2));
[email protected]5ecc992a42009-11-11 01:41:595674 session_deps.socket_factory.AddSocketDataProvider(&data2);
[email protected]0877e3d2009-10-17 22:29:575675
5676 TestCompletionCallback callback1;
5677
[email protected]0b0bf032010-09-21 18:08:505678 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
5679
[email protected]5a1d7ca2010-04-28 20:12:275680 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]0877e3d2009-10-17 22:29:575681 EXPECT_EQ(ERR_IO_PENDING, rv);
5682
5683 rv = callback1.WaitForResult();
5684 EXPECT_EQ(OK, rv);
5685
5686 const HttpResponseInfo* response = trans->GetResponseInfo();
5687 EXPECT_FALSE(response == NULL);
5688
5689 // The password prompt info should have been set in response->auth_challenge.
5690 EXPECT_FALSE(response->auth_challenge.get() == NULL);
5691
5692 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
5693 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
5694 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
5695
5696 TestCompletionCallback callback2;
5697
[email protected]13c8a092010-07-29 06:15:445698 rv = trans->RestartWithAuth(kFoo, kBar, &callback2);
[email protected]0877e3d2009-10-17 22:29:575699 EXPECT_EQ(ERR_IO_PENDING, rv);
5700
5701 rv = callback2.WaitForResult();
5702 EXPECT_EQ(OK, rv);
5703
5704 response = trans->GetResponseInfo();
5705 EXPECT_FALSE(response == NULL);
5706 EXPECT_TRUE(response->auth_challenge.get() == NULL);
5707 EXPECT_EQ(100, response->headers->GetContentLength());
5708}
5709
5710// Test HTTPS connections going through a proxy that sends extra data.
5711TEST_F(HttpNetworkTransactionTest, HTTPSViaProxyWithExtraData) {
[email protected]81cdfcd2010-10-16 00:49:005712 SessionDependencies session_deps(ProxyService::CreateFixed("myproxy:70"));
[email protected]0877e3d2009-10-17 22:29:575713
5714 HttpRequestInfo request;
5715 request.method = "GET";
5716 request.url = GURL("https://www.google.com/");
5717 request.load_flags = 0;
5718
5719 MockRead proxy_reads[] = {
5720 MockRead("HTTP/1.0 200 Connected\r\n\r\nExtra data"),
5721 MockRead(false, OK)
5722 };
5723
[email protected]31a2bfe2010-02-09 08:03:395724 StaticSocketDataProvider data(proxy_reads, arraysize(proxy_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:595725 SSLSocketDataProvider ssl(true, OK);
[email protected]0877e3d2009-10-17 22:29:575726
[email protected]5ecc992a42009-11-11 01:41:595727 session_deps.socket_factory.AddSocketDataProvider(&data);
5728 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
[email protected]0877e3d2009-10-17 22:29:575729
5730 TestCompletionCallback callback;
5731
5732 session_deps.socket_factory.ResetNextMockIndexes();
5733
5734 scoped_ptr<HttpTransaction> trans(
5735 new HttpNetworkTransaction(CreateSession(&session_deps)));
5736
[email protected]5a1d7ca2010-04-28 20:12:275737 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]0877e3d2009-10-17 22:29:575738 EXPECT_EQ(ERR_IO_PENDING, rv);
5739
5740 rv = callback.WaitForResult();
5741 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED, rv);
5742}
5743
[email protected]e22e1362009-11-23 21:31:125744TEST_F(HttpNetworkTransactionTest, LargeContentLengthThenClose) {
[email protected]9492e4a2010-02-24 00:58:465745 SessionDependencies session_deps;
5746 scoped_ptr<HttpTransaction> trans(
5747 new HttpNetworkTransaction(CreateSession(&session_deps)));
5748
5749 HttpRequestInfo request;
5750 request.method = "GET";
5751 request.url = GURL("http://www.google.com/");
5752 request.load_flags = 0;
5753
[email protected]e22e1362009-11-23 21:31:125754 MockRead data_reads[] = {
5755 MockRead("HTTP/1.0 200 OK\r\nContent-Length:6719476739\r\n\r\n"),
5756 MockRead(false, OK),
5757 };
[email protected]9492e4a2010-02-24 00:58:465758
5759 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
5760 session_deps.socket_factory.AddSocketDataProvider(&data);
5761
5762 TestCompletionCallback callback;
5763
[email protected]5a1d7ca2010-04-28 20:12:275764 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]9492e4a2010-02-24 00:58:465765 EXPECT_EQ(ERR_IO_PENDING, rv);
5766
5767 EXPECT_EQ(OK, callback.WaitForResult());
5768
5769 const HttpResponseInfo* response = trans->GetResponseInfo();
5770 EXPECT_TRUE(response != NULL);
5771
5772 EXPECT_TRUE(response->headers != NULL);
5773 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
5774
5775 std::string response_data;
5776 rv = ReadTransaction(trans.get(), &response_data);
5777 EXPECT_EQ(ERR_CONNECTION_CLOSED, rv);
[email protected]e22e1362009-11-23 21:31:125778}
5779
[email protected]95d88ffe2010-02-04 21:25:335780TEST_F(HttpNetworkTransactionTest, UploadFileSmallerThanLength) {
5781 SessionDependencies session_deps;
5782 scoped_ptr<HttpTransaction> trans(
5783 new HttpNetworkTransaction(CreateSession(&session_deps)));
5784
5785 HttpRequestInfo request;
5786 request.method = "POST";
5787 request.url = GURL("http://www.google.com/upload");
5788 request.upload_data = new UploadData;
5789 request.load_flags = 0;
5790
5791 FilePath temp_file_path;
5792 ASSERT_TRUE(file_util::CreateTemporaryFile(&temp_file_path));
5793 const uint64 kFakeSize = 100000; // file is actually blank
5794
5795 std::vector<UploadData::Element> elements;
5796 UploadData::Element element;
5797 element.SetToFilePath(temp_file_path);
5798 element.SetContentLength(kFakeSize);
5799 elements.push_back(element);
[email protected]9349cfb2010-08-31 18:00:535800 request.upload_data->SetElements(elements);
[email protected]95d88ffe2010-02-04 21:25:335801 EXPECT_EQ(kFakeSize, request.upload_data->GetContentLength());
5802
5803 MockRead data_reads[] = {
5804 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
5805 MockRead("hello world"),
5806 MockRead(false, OK),
5807 };
[email protected]31a2bfe2010-02-09 08:03:395808 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]95d88ffe2010-02-04 21:25:335809 session_deps.socket_factory.AddSocketDataProvider(&data);
5810
5811 TestCompletionCallback callback;
5812
[email protected]5a1d7ca2010-04-28 20:12:275813 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]95d88ffe2010-02-04 21:25:335814 EXPECT_EQ(ERR_IO_PENDING, rv);
5815
5816 rv = callback.WaitForResult();
5817 EXPECT_EQ(OK, rv);
5818
5819 const HttpResponseInfo* response = trans->GetResponseInfo();
5820 EXPECT_TRUE(response != NULL);
5821
5822 EXPECT_TRUE(response->headers != NULL);
5823 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
5824
5825 std::string response_data;
5826 rv = ReadTransaction(trans.get(), &response_data);
5827 EXPECT_EQ(OK, rv);
5828 EXPECT_EQ("hello world", response_data);
5829
5830 file_util::Delete(temp_file_path, false);
5831}
5832
[email protected]6624b4622010-03-29 19:58:365833TEST_F(HttpNetworkTransactionTest, UploadUnreadableFile) {
5834 // If we try to upload an unreadable file, the network stack should report
5835 // the file size as zero and upload zero bytes for that file.
5836 SessionDependencies session_deps;
5837 scoped_ptr<HttpTransaction> trans(
5838 new HttpNetworkTransaction(CreateSession(&session_deps)));
5839
5840 FilePath temp_file;
5841 ASSERT_TRUE(file_util::CreateTemporaryFile(&temp_file));
5842 std::string temp_file_content("Unreadable file.");
5843 ASSERT_TRUE(file_util::WriteFile(temp_file, temp_file_content.c_str(),
5844 temp_file_content.length()));
5845 ASSERT_TRUE(file_util::MakeFileUnreadable(temp_file));
5846
5847 HttpRequestInfo request;
5848 request.method = "POST";
5849 request.url = GURL("http://www.google.com/upload");
5850 request.upload_data = new UploadData;
5851 request.load_flags = 0;
5852
5853 std::vector<UploadData::Element> elements;
5854 UploadData::Element element;
5855 element.SetToFilePath(temp_file);
5856 elements.push_back(element);
[email protected]9349cfb2010-08-31 18:00:535857 request.upload_data->SetElements(elements);
[email protected]6624b4622010-03-29 19:58:365858
5859 MockRead data_reads[] = {
5860 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
5861 MockRead(false, OK),
5862 };
5863 MockWrite data_writes[] = {
5864 MockWrite("POST /upload HTTP/1.1\r\n"
5865 "Host: www.google.com\r\n"
5866 "Connection: keep-alive\r\n"
5867 "Content-Length: 0\r\n\r\n"),
5868 MockWrite(false, OK),
5869 };
5870 StaticSocketDataProvider data(data_reads, arraysize(data_reads), data_writes,
5871 arraysize(data_writes));
5872 session_deps.socket_factory.AddSocketDataProvider(&data);
5873
5874 TestCompletionCallback callback;
5875
[email protected]5a1d7ca2010-04-28 20:12:275876 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]6624b4622010-03-29 19:58:365877 EXPECT_EQ(ERR_IO_PENDING, rv);
5878
5879 rv = callback.WaitForResult();
5880 EXPECT_EQ(OK, rv);
5881
5882 const HttpResponseInfo* response = trans->GetResponseInfo();
5883 EXPECT_TRUE(response != NULL);
5884 EXPECT_TRUE(response->headers != NULL);
5885 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
5886
5887 file_util::Delete(temp_file, false);
5888}
5889
5890TEST_F(HttpNetworkTransactionTest, UnreadableUploadFileAfterAuthRestart) {
5891 SessionDependencies session_deps;
5892 scoped_ptr<HttpTransaction> trans(
5893 new HttpNetworkTransaction(CreateSession(&session_deps)));
5894
5895 FilePath temp_file;
5896 ASSERT_TRUE(file_util::CreateTemporaryFile(&temp_file));
5897 std::string temp_file_contents("Unreadable file.");
5898 std::string unreadable_contents(temp_file_contents.length(), '\0');
5899 ASSERT_TRUE(file_util::WriteFile(temp_file, temp_file_contents.c_str(),
5900 temp_file_contents.length()));
5901
5902 HttpRequestInfo request;
5903 request.method = "POST";
5904 request.url = GURL("http://www.google.com/upload");
5905 request.upload_data = new UploadData;
5906 request.load_flags = 0;
5907
5908 std::vector<UploadData::Element> elements;
5909 UploadData::Element element;
5910 element.SetToFilePath(temp_file);
5911 elements.push_back(element);
[email protected]9349cfb2010-08-31 18:00:535912 request.upload_data->SetElements(elements);
[email protected]6624b4622010-03-29 19:58:365913
5914 MockRead data_reads[] = {
5915 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
5916 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
5917 MockRead("Content-Length: 0\r\n\r\n"), // No response body.
5918
5919 MockRead("HTTP/1.1 200 OK\r\n"),
5920 MockRead("Content-Length: 0\r\n\r\n"),
5921 MockRead(false, OK),
5922 };
5923 MockWrite data_writes[] = {
5924 MockWrite("POST /upload HTTP/1.1\r\n"
5925 "Host: www.google.com\r\n"
5926 "Connection: keep-alive\r\n"
5927 "Content-Length: 16\r\n\r\n"),
5928 MockWrite(false, temp_file_contents.c_str()),
5929
5930 MockWrite("POST /upload HTTP/1.1\r\n"
5931 "Host: www.google.com\r\n"
5932 "Connection: keep-alive\r\n"
5933 "Content-Length: 16\r\n"
5934 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
5935 MockWrite(false, unreadable_contents.c_str(), temp_file_contents.length()),
5936 MockWrite(false, OK),
5937 };
5938 StaticSocketDataProvider data(data_reads, arraysize(data_reads), data_writes,
5939 arraysize(data_writes));
5940 session_deps.socket_factory.AddSocketDataProvider(&data);
5941
5942 TestCompletionCallback callback1;
5943
[email protected]5a1d7ca2010-04-28 20:12:275944 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]6624b4622010-03-29 19:58:365945 EXPECT_EQ(ERR_IO_PENDING, rv);
5946
5947 rv = callback1.WaitForResult();
5948 EXPECT_EQ(OK, rv);
5949
5950 const HttpResponseInfo* response = trans->GetResponseInfo();
5951 EXPECT_TRUE(response != NULL);
5952 EXPECT_TRUE(response->headers != NULL);
5953 EXPECT_EQ("HTTP/1.1 401 Unauthorized", response->headers->GetStatusLine());
5954
5955 // The password prompt info should have been set in response->auth_challenge.
5956 EXPECT_TRUE(response->auth_challenge.get() != NULL);
5957 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
5958 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
5959 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
5960
5961 // Now make the file unreadable and try again.
5962 ASSERT_TRUE(file_util::MakeFileUnreadable(temp_file));
5963
5964 TestCompletionCallback callback2;
5965
[email protected]13c8a092010-07-29 06:15:445966 rv = trans->RestartWithAuth(kFoo, kBar, &callback2);
[email protected]6624b4622010-03-29 19:58:365967 EXPECT_EQ(ERR_IO_PENDING, rv);
5968
5969 rv = callback2.WaitForResult();
5970 EXPECT_EQ(OK, rv);
5971
5972 response = trans->GetResponseInfo();
5973 EXPECT_TRUE(response != NULL);
5974 EXPECT_TRUE(response->headers != NULL);
5975 EXPECT_TRUE(response->auth_challenge.get() == NULL);
5976 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
5977
5978 file_util::Delete(temp_file, false);
5979}
5980
[email protected]aeefc9e82010-02-19 16:18:275981// Tests that changes to Auth realms are treated like auth rejections.
5982TEST_F(HttpNetworkTransactionTest, ChangeAuthRealms) {
5983 SessionDependencies session_deps;
[email protected]aeefc9e82010-02-19 16:18:275984
5985 HttpRequestInfo request;
5986 request.method = "GET";
5987 request.url = GURL("http://www.google.com/");
5988 request.load_flags = 0;
5989
5990 // First transaction will request a resource and receive a Basic challenge
5991 // with realm="first_realm".
5992 MockWrite data_writes1[] = {
5993 MockWrite("GET / HTTP/1.1\r\n"
5994 "Host: www.google.com\r\n"
5995 "Connection: keep-alive\r\n"
5996 "\r\n"),
5997 };
5998 MockRead data_reads1[] = {
5999 MockRead("HTTP/1.1 401 Unauthorized\r\n"
6000 "WWW-Authenticate: Basic realm=\"first_realm\"\r\n"
6001 "\r\n"),
6002 };
6003
6004 // After calling trans->RestartWithAuth(), provide an Authentication header
6005 // for first_realm. The server will reject and provide a challenge with
6006 // second_realm.
6007 MockWrite data_writes2[] = {
6008 MockWrite("GET / HTTP/1.1\r\n"
6009 "Host: www.google.com\r\n"
6010 "Connection: keep-alive\r\n"
6011 "Authorization: Basic Zmlyc3Q6YmF6\r\n"
6012 "\r\n"),
6013 };
6014 MockRead data_reads2[] = {
6015 MockRead("HTTP/1.1 401 Unauthorized\r\n"
6016 "WWW-Authenticate: Basic realm=\"second_realm\"\r\n"
6017 "\r\n"),
6018 };
6019
6020 // This again fails, and goes back to first_realm. Make sure that the
6021 // entry is removed from cache.
6022 MockWrite data_writes3[] = {
6023 MockWrite("GET / HTTP/1.1\r\n"
6024 "Host: www.google.com\r\n"
6025 "Connection: keep-alive\r\n"
6026 "Authorization: Basic c2Vjb25kOmZvdQ==\r\n"
6027 "\r\n"),
6028 };
6029 MockRead data_reads3[] = {
6030 MockRead("HTTP/1.1 401 Unauthorized\r\n"
6031 "WWW-Authenticate: Basic realm=\"first_realm\"\r\n"
6032 "\r\n"),
6033 };
6034
6035 // Try one last time (with the correct password) and get the resource.
6036 MockWrite data_writes4[] = {
6037 MockWrite("GET / HTTP/1.1\r\n"
6038 "Host: www.google.com\r\n"
6039 "Connection: keep-alive\r\n"
6040 "Authorization: Basic Zmlyc3Q6YmFy\r\n"
6041 "\r\n"),
6042 };
6043 MockRead data_reads4[] = {
6044 MockRead("HTTP/1.1 200 OK\r\n"
6045 "Content-Type: text/html; charset=iso-8859-1\r\n"
[email protected]0b0bf032010-09-21 18:08:506046 "Content-Length: 5\r\n"
6047 "\r\n"
6048 "hello"),
[email protected]aeefc9e82010-02-19 16:18:276049 };
6050
6051 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
6052 data_writes1, arraysize(data_writes1));
6053 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
6054 data_writes2, arraysize(data_writes2));
6055 StaticSocketDataProvider data3(data_reads3, arraysize(data_reads3),
6056 data_writes3, arraysize(data_writes3));
6057 StaticSocketDataProvider data4(data_reads4, arraysize(data_reads4),
6058 data_writes4, arraysize(data_writes4));
6059 session_deps.socket_factory.AddSocketDataProvider(&data1);
6060 session_deps.socket_factory.AddSocketDataProvider(&data2);
6061 session_deps.socket_factory.AddSocketDataProvider(&data3);
6062 session_deps.socket_factory.AddSocketDataProvider(&data4);
6063
6064 TestCompletionCallback callback1;
6065
[email protected]0b0bf032010-09-21 18:08:506066 scoped_ptr<HttpTransaction> trans(
6067 new HttpNetworkTransaction(CreateSession(&session_deps)));
6068
[email protected]aeefc9e82010-02-19 16:18:276069 // Issue the first request with Authorize headers. There should be a
6070 // password prompt for first_realm waiting to be filled in after the
6071 // transaction completes.
[email protected]5a1d7ca2010-04-28 20:12:276072 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]aeefc9e82010-02-19 16:18:276073 EXPECT_EQ(ERR_IO_PENDING, rv);
6074 rv = callback1.WaitForResult();
6075 EXPECT_EQ(OK, rv);
6076 const HttpResponseInfo* response = trans->GetResponseInfo();
6077 ASSERT_FALSE(response == NULL);
6078 ASSERT_FALSE(response->auth_challenge.get() == NULL);
6079 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
6080 EXPECT_EQ(L"first_realm", response->auth_challenge->realm);
6081 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
6082
6083 // Issue the second request with an incorrect password. There should be a
6084 // password prompt for second_realm waiting to be filled in after the
6085 // transaction completes.
6086 TestCompletionCallback callback2;
[email protected]13c8a092010-07-29 06:15:446087 rv = trans->RestartWithAuth(kFirst, kBaz, &callback2);
[email protected]aeefc9e82010-02-19 16:18:276088 EXPECT_EQ(ERR_IO_PENDING, rv);
6089 rv = callback2.WaitForResult();
6090 EXPECT_EQ(OK, rv);
6091 response = trans->GetResponseInfo();
6092 ASSERT_FALSE(response == NULL);
6093 ASSERT_FALSE(response->auth_challenge.get() == NULL);
6094 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
6095 EXPECT_EQ(L"second_realm", response->auth_challenge->realm);
6096 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
6097
6098 // Issue the third request with another incorrect password. There should be
6099 // a password prompt for first_realm waiting to be filled in. If the password
6100 // prompt is not present, it indicates that the HttpAuthCacheEntry for
6101 // first_realm was not correctly removed.
6102 TestCompletionCallback callback3;
[email protected]13c8a092010-07-29 06:15:446103 rv = trans->RestartWithAuth(kSecond, kFou, &callback3);
[email protected]aeefc9e82010-02-19 16:18:276104 EXPECT_EQ(ERR_IO_PENDING, rv);
6105 rv = callback3.WaitForResult();
6106 EXPECT_EQ(OK, rv);
6107 response = trans->GetResponseInfo();
6108 ASSERT_FALSE(response == NULL);
6109 ASSERT_FALSE(response->auth_challenge.get() == NULL);
6110 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
6111 EXPECT_EQ(L"first_realm", response->auth_challenge->realm);
6112 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
6113
6114 // Issue the fourth request with the correct password and username.
6115 TestCompletionCallback callback4;
[email protected]13c8a092010-07-29 06:15:446116 rv = trans->RestartWithAuth(kFirst, kBar, &callback4);
[email protected]aeefc9e82010-02-19 16:18:276117 EXPECT_EQ(ERR_IO_PENDING, rv);
6118 rv = callback4.WaitForResult();
6119 EXPECT_EQ(OK, rv);
6120 response = trans->GetResponseInfo();
6121 ASSERT_FALSE(response == NULL);
6122 EXPECT_TRUE(response->auth_challenge.get() == NULL);
6123}
6124
[email protected]564b4912010-03-09 16:30:426125TEST_F(HttpNetworkTransactionTest, HonorAlternateProtocolHeader) {
[email protected]8e6441ca2010-08-19 05:56:386126 HttpStreamFactory::set_next_protos("needs_to_be_set_for_this_test");
6127 HttpStreamFactory::set_use_alternate_protocols(true);
[email protected]a2cb8122010-03-10 17:22:426128
[email protected]564b4912010-03-09 16:30:426129 SessionDependencies session_deps;
6130
6131 MockRead data_reads[] = {
6132 MockRead("HTTP/1.1 200 OK\r\n"),
[email protected]dae22c52010-07-30 02:16:356133 MockRead(kAlternateProtocolHttpHeader),
[email protected]564b4912010-03-09 16:30:426134 MockRead("hello world"),
6135 MockRead(false, OK),
6136 };
6137
6138 HttpRequestInfo request;
6139 request.method = "GET";
6140 request.url = GURL("http://www.google.com/");
6141 request.load_flags = 0;
6142
6143 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
6144
6145 session_deps.socket_factory.AddSocketDataProvider(&data);
6146
6147 TestCompletionCallback callback;
6148
6149 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
6150 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
6151
[email protected]5a1d7ca2010-04-28 20:12:276152 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]564b4912010-03-09 16:30:426153 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]9e743cd2010-03-16 07:03:536154
[email protected]2fbaecf22010-07-22 22:20:356155 HostPortPair http_host_port_pair("www.google.com", 80);
[email protected]564b4912010-03-09 16:30:426156 const HttpAlternateProtocols& alternate_protocols =
6157 session->alternate_protocols();
6158 EXPECT_FALSE(
6159 alternate_protocols.HasAlternateProtocolFor(http_host_port_pair));
6160
6161 EXPECT_EQ(OK, callback.WaitForResult());
6162
6163 const HttpResponseInfo* response = trans->GetResponseInfo();
6164 ASSERT_TRUE(response != NULL);
6165 ASSERT_TRUE(response->headers != NULL);
6166 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
[email protected]65041fa2010-05-21 06:56:536167 EXPECT_FALSE(response->was_fetched_via_spdy);
6168 EXPECT_FALSE(response->was_npn_negotiated);
[email protected]193b0b892010-06-26 03:57:576169 EXPECT_FALSE(response->was_alternate_protocol_available);
[email protected]564b4912010-03-09 16:30:426170
6171 std::string response_data;
6172 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
6173 EXPECT_EQ("hello world", response_data);
6174
6175 ASSERT_TRUE(alternate_protocols.HasAlternateProtocolFor(http_host_port_pair));
6176 const HttpAlternateProtocols::PortProtocolPair alternate =
6177 alternate_protocols.GetAlternateProtocolFor(http_host_port_pair);
6178 HttpAlternateProtocols::PortProtocolPair expected_alternate;
6179 expected_alternate.port = 443;
[email protected]dae22c52010-07-30 02:16:356180 expected_alternate.protocol = HttpAlternateProtocols::NPN_SPDY_2;
[email protected]564b4912010-03-09 16:30:426181 EXPECT_TRUE(expected_alternate.Equals(alternate));
[email protected]a2cb8122010-03-10 17:22:426182
[email protected]8e6441ca2010-08-19 05:56:386183 HttpStreamFactory::set_use_alternate_protocols(false);
6184 HttpStreamFactory::set_next_protos("");
[email protected]564b4912010-03-09 16:30:426185}
6186
6187TEST_F(HttpNetworkTransactionTest, MarkBrokenAlternateProtocol) {
[email protected]8e6441ca2010-08-19 05:56:386188 HttpStreamFactory::set_use_alternate_protocols(true);
[email protected]564b4912010-03-09 16:30:426189 SessionDependencies session_deps;
6190
6191 HttpRequestInfo request;
6192 request.method = "GET";
6193 request.url = GURL("http://www.google.com/");
6194 request.load_flags = 0;
6195
6196 MockConnect mock_connect(true, ERR_CONNECTION_REFUSED);
6197 StaticSocketDataProvider first_data;
6198 first_data.set_connect_data(mock_connect);
6199 session_deps.socket_factory.AddSocketDataProvider(&first_data);
6200
6201 MockRead data_reads[] = {
6202 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
6203 MockRead("hello world"),
6204 MockRead(true, OK),
6205 };
6206 StaticSocketDataProvider second_data(
6207 data_reads, arraysize(data_reads), NULL, 0);
6208 session_deps.socket_factory.AddSocketDataProvider(&second_data);
6209
6210 // TODO(willchan): Delete this extra data provider. It's necessary due to a
6211 // ClientSocketPoolBaseHelper bug that starts up too many ConnectJobs:
6212 // http://crbug.com/37454.
6213 session_deps.socket_factory.AddSocketDataProvider(&second_data);
6214
6215 TestCompletionCallback callback;
6216
6217 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
6218
[email protected]2fbaecf22010-07-22 22:20:356219 HostPortPair http_host_port_pair("www.google.com", 80);
[email protected]564b4912010-03-09 16:30:426220 HttpAlternateProtocols* alternate_protocols =
6221 session->mutable_alternate_protocols();
6222 alternate_protocols->SetAlternateProtocolFor(
6223 http_host_port_pair, 1234 /* port is ignored by MockConnect anyway */,
[email protected]dae22c52010-07-30 02:16:356224 HttpAlternateProtocols::NPN_SPDY_2);
[email protected]564b4912010-03-09 16:30:426225
6226 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
6227
[email protected]5a1d7ca2010-04-28 20:12:276228 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]564b4912010-03-09 16:30:426229 EXPECT_EQ(ERR_IO_PENDING, rv);
6230 EXPECT_EQ(OK, callback.WaitForResult());
6231
6232 const HttpResponseInfo* response = trans->GetResponseInfo();
6233 ASSERT_TRUE(response != NULL);
6234 ASSERT_TRUE(response->headers != NULL);
6235 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
6236
6237 std::string response_data;
6238 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
6239 EXPECT_EQ("hello world", response_data);
6240
6241 ASSERT_TRUE(
6242 alternate_protocols->HasAlternateProtocolFor(http_host_port_pair));
6243 const HttpAlternateProtocols::PortProtocolPair alternate =
6244 alternate_protocols->GetAlternateProtocolFor(http_host_port_pair);
6245 EXPECT_EQ(HttpAlternateProtocols::BROKEN, alternate.protocol);
[email protected]8e6441ca2010-08-19 05:56:386246 HttpStreamFactory::set_use_alternate_protocols(false);
[email protected]564b4912010-03-09 16:30:426247}
6248
6249// TODO(willchan): Redo this test to use TLS/NPN=>SPDY. Currently, the code
6250// says that it does SPDY, but it just does the TLS handshake, but the NPN
6251// response does not indicate SPDY, so we just do standard HTTPS over the port.
6252// We should add code such that we don't fallback to HTTPS, but fallback to HTTP
6253// on the original port.
[email protected]a2cb8122010-03-10 17:22:426254// TEST_F(HttpNetworkTransactionTest, UseAlternateProtocol) {
6255// SessionDependencies session_deps;
[email protected]9e743cd2010-03-16 07:03:536256//
[email protected]a2cb8122010-03-10 17:22:426257// HttpRequestInfo request;
6258// request.method = "GET";
6259// request.url = GURL("http://www.google.com/");
6260// request.load_flags = 0;
[email protected]9e743cd2010-03-16 07:03:536261//
[email protected]a2cb8122010-03-10 17:22:426262// MockRead data_reads[] = {
6263// MockRead("HTTP/1.1 200 OK\r\n\r\n"),
6264// MockRead("hello world"),
6265// MockRead(true, OK),
6266// };
6267// StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
6268// session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]9e743cd2010-03-16 07:03:536269//
[email protected]a2cb8122010-03-10 17:22:426270// SSLSocketDataProvider ssl(true, OK);
6271// session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
[email protected]9e743cd2010-03-16 07:03:536272//
[email protected]a2cb8122010-03-10 17:22:426273// TestCompletionCallback callback;
[email protected]9e743cd2010-03-16 07:03:536274//
[email protected]a2cb8122010-03-10 17:22:426275// scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]9e743cd2010-03-16 07:03:536276//
[email protected]a2cb8122010-03-10 17:22:426277// HostPortPair http_host_port_pair;
6278// http_host_port_pair.host = "www.google.com";
6279// http_host_port_pair.port = 80;
6280// HttpAlternateProtocols* alternate_protocols =
6281// session->mutable_alternate_protocols();
6282// alternate_protocols->SetAlternateProtocolFor(
6283// http_host_port_pair, 1234 /* port is ignored */,
[email protected]31e2c69e2010-04-15 18:06:066284// HttpAlternateProtocols::NPN_SPDY_1);
[email protected]9e743cd2010-03-16 07:03:536285//
[email protected]a2cb8122010-03-10 17:22:426286// scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]9e743cd2010-03-16 07:03:536287//
[email protected]5a1d7ca2010-04-28 20:12:276288// int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]a2cb8122010-03-10 17:22:426289// EXPECT_EQ(ERR_IO_PENDING, rv);
6290// EXPECT_EQ(OK, callback.WaitForResult());
[email protected]9e743cd2010-03-16 07:03:536291//
[email protected]a2cb8122010-03-10 17:22:426292// const HttpResponseInfo* response = trans->GetResponseInfo();
6293// ASSERT_TRUE(response != NULL);
6294// ASSERT_TRUE(response->headers != NULL);
6295// EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
[email protected]9e743cd2010-03-16 07:03:536296//
[email protected]a2cb8122010-03-10 17:22:426297// std::string response_data;
6298// ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
6299// EXPECT_EQ("hello world", response_data);
6300// }
6301
6302TEST_F(HttpNetworkTransactionTest, FailNpnSpdyAndFallback) {
[email protected]8e6441ca2010-08-19 05:56:386303 HttpStreamFactory::set_use_alternate_protocols(true);
6304 HttpStreamFactory::set_next_protos(kExpectedNPNString);
[email protected]564b4912010-03-09 16:30:426305 SessionDependencies session_deps;
6306
6307 HttpRequestInfo request;
6308 request.method = "GET";
6309 request.url = GURL("http://www.google.com/");
6310 request.load_flags = 0;
6311
[email protected]a2cb8122010-03-10 17:22:426312 StaticSocketDataProvider first_tcp_connect;
6313 session_deps.socket_factory.AddSocketDataProvider(&first_tcp_connect);
6314
6315 SSLSocketDataProvider ssl(true, OK);
6316 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
6317
[email protected]564b4912010-03-09 16:30:426318 MockRead data_reads[] = {
6319 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
6320 MockRead("hello world"),
6321 MockRead(true, OK),
6322 };
[email protected]a2cb8122010-03-10 17:22:426323 StaticSocketDataProvider fallback_data(
6324 data_reads, arraysize(data_reads), NULL, 0);
6325 session_deps.socket_factory.AddSocketDataProvider(&fallback_data);
[email protected]564b4912010-03-09 16:30:426326
6327 TestCompletionCallback callback;
6328
6329 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
6330
[email protected]2fbaecf22010-07-22 22:20:356331 HostPortPair http_host_port_pair("www.google.com", 80);
[email protected]564b4912010-03-09 16:30:426332 HttpAlternateProtocols* alternate_protocols =
6333 session->mutable_alternate_protocols();
6334 alternate_protocols->SetAlternateProtocolFor(
6335 http_host_port_pair, 1234 /* port is ignored */,
[email protected]dae22c52010-07-30 02:16:356336 HttpAlternateProtocols::NPN_SPDY_2);
[email protected]564b4912010-03-09 16:30:426337
6338 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
6339
[email protected]5a1d7ca2010-04-28 20:12:276340 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]564b4912010-03-09 16:30:426341 EXPECT_EQ(ERR_IO_PENDING, rv);
6342 EXPECT_EQ(OK, callback.WaitForResult());
6343
6344 const HttpResponseInfo* response = trans->GetResponseInfo();
6345 ASSERT_TRUE(response != NULL);
6346 ASSERT_TRUE(response->headers != NULL);
6347 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
6348
6349 std::string response_data;
6350 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
6351 EXPECT_EQ("hello world", response_data);
[email protected]8e6441ca2010-08-19 05:56:386352 HttpStreamFactory::set_next_protos("");
6353 HttpStreamFactory::set_use_alternate_protocols(false);
[email protected]2ff8b312010-04-26 22:20:546354}
6355
6356TEST_F(HttpNetworkTransactionTest, UseAlternateProtocolForNpnSpdy) {
[email protected]8e6441ca2010-08-19 05:56:386357 HttpStreamFactory::set_use_alternate_protocols(true);
6358 HttpStreamFactory::set_next_protos(kExpectedNPNString);
[email protected]2ff8b312010-04-26 22:20:546359 SessionDependencies session_deps;
6360
6361 HttpRequestInfo request;
6362 request.method = "GET";
6363 request.url = GURL("http://www.google.com/");
6364 request.load_flags = 0;
6365
6366 MockRead data_reads[] = {
6367 MockRead("HTTP/1.1 200 OK\r\n"),
[email protected]dae22c52010-07-30 02:16:356368 MockRead(kAlternateProtocolHttpHeader),
[email protected]2ff8b312010-04-26 22:20:546369 MockRead("hello world"),
6370 MockRead(true, OK),
6371 };
6372
6373 StaticSocketDataProvider first_transaction(
6374 data_reads, arraysize(data_reads), NULL, 0);
6375 session_deps.socket_factory.AddSocketDataProvider(&first_transaction);
6376
6377 SSLSocketDataProvider ssl(true, OK);
6378 ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
[email protected]dae22c52010-07-30 02:16:356379 ssl.next_proto = "spdy/2";
[email protected]65041fa2010-05-21 06:56:536380 ssl.was_npn_negotiated = true;
[email protected]2ff8b312010-04-26 22:20:546381 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
6382
[email protected]2bd93022010-07-17 00:58:446383 scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
[email protected]e7f75092010-07-01 22:39:136384 MockWrite spdy_writes[] = { CreateMockWrite(*req) };
[email protected]2ff8b312010-04-26 22:20:546385
[email protected]2bd93022010-07-17 00:58:446386 scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1));
6387 scoped_ptr<spdy::SpdyFrame> data(ConstructSpdyBodyFrame(1, true));
[email protected]2ff8b312010-04-26 22:20:546388 MockRead spdy_reads[] = {
[email protected]e7f75092010-07-01 22:39:136389 CreateMockRead(*resp),
6390 CreateMockRead(*data),
[email protected]2ff8b312010-04-26 22:20:546391 MockRead(true, 0, 0),
6392 };
6393
6394 scoped_refptr<DelayedSocketData> spdy_data(
6395 new DelayedSocketData(
6396 1, // wait for one write to finish before reading.
6397 spdy_reads, arraysize(spdy_reads),
6398 spdy_writes, arraysize(spdy_writes)));
6399 session_deps.socket_factory.AddSocketDataProvider(spdy_data);
6400
6401 TestCompletionCallback callback;
6402
6403 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
6404 scoped_ptr<HttpNetworkTransaction> trans(new HttpNetworkTransaction(session));
6405
[email protected]5a1d7ca2010-04-28 20:12:276406 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]2ff8b312010-04-26 22:20:546407 EXPECT_EQ(ERR_IO_PENDING, rv);
6408 EXPECT_EQ(OK, callback.WaitForResult());
6409
6410 const HttpResponseInfo* response = trans->GetResponseInfo();
6411 ASSERT_TRUE(response != NULL);
6412 ASSERT_TRUE(response->headers != NULL);
6413 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
6414
6415 std::string response_data;
6416 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
6417 EXPECT_EQ("hello world", response_data);
6418
6419 trans.reset(new HttpNetworkTransaction(session));
6420
[email protected]5a1d7ca2010-04-28 20:12:276421 rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]2ff8b312010-04-26 22:20:546422 EXPECT_EQ(ERR_IO_PENDING, rv);
6423 EXPECT_EQ(OK, callback.WaitForResult());
6424
6425 response = trans->GetResponseInfo();
6426 ASSERT_TRUE(response != NULL);
6427 ASSERT_TRUE(response->headers != NULL);
6428 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
[email protected]65041fa2010-05-21 06:56:536429 EXPECT_TRUE(response->was_fetched_via_spdy);
6430 EXPECT_TRUE(response->was_npn_negotiated);
[email protected]193b0b892010-06-26 03:57:576431 EXPECT_TRUE(response->was_alternate_protocol_available);
[email protected]2ff8b312010-04-26 22:20:546432
6433 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
6434 EXPECT_EQ("hello!", response_data);
6435
[email protected]8e6441ca2010-08-19 05:56:386436 HttpStreamFactory::set_next_protos("");
6437 HttpStreamFactory::set_use_alternate_protocols(false);
[email protected]2ff8b312010-04-26 22:20:546438}
6439
[email protected]631f1322010-04-30 17:59:116440class CapturingProxyResolver : public ProxyResolver {
6441 public:
6442 CapturingProxyResolver() : ProxyResolver(false /* expects_pac_bytes */) {}
6443 virtual ~CapturingProxyResolver() {}
6444
6445 virtual int GetProxyForURL(const GURL& url,
6446 ProxyInfo* results,
6447 CompletionCallback* callback,
6448 RequestHandle* request,
6449 const BoundNetLog& net_log) {
[email protected]fae7669f2010-08-02 21:49:406450 ProxyServer proxy_server(ProxyServer::SCHEME_HTTP,
6451 HostPortPair("myproxy", 80));
[email protected]d911f1b2010-05-05 22:39:426452 results->UseProxyServer(proxy_server);
[email protected]631f1322010-04-30 17:59:116453 resolved_.push_back(url);
[email protected]d911f1b2010-05-05 22:39:426454 return OK;
[email protected]631f1322010-04-30 17:59:116455 }
6456
6457 virtual void CancelRequest(RequestHandle request) {
6458 NOTREACHED();
6459 }
6460
[email protected]24476402010-07-20 20:55:176461 virtual int SetPacScript(const scoped_refptr<ProxyResolverScriptData>&,
[email protected]631f1322010-04-30 17:59:116462 CompletionCallback* /*callback*/) {
[email protected]d911f1b2010-05-05 22:39:426463 return OK;
[email protected]631f1322010-04-30 17:59:116464 }
6465
[email protected]24476402010-07-20 20:55:176466 const std::vector<GURL>& resolved() const { return resolved_; }
6467
6468 private:
[email protected]631f1322010-04-30 17:59:116469 std::vector<GURL> resolved_;
6470
6471 DISALLOW_COPY_AND_ASSIGN(CapturingProxyResolver);
6472};
6473
[email protected]631f1322010-04-30 17:59:116474TEST_F(HttpNetworkTransactionTest, UseAlternateProtocolForTunneledNpnSpdy) {
[email protected]8e6441ca2010-08-19 05:56:386475 HttpStreamFactory::set_use_alternate_protocols(true);
6476 HttpStreamFactory::set_next_protos(kExpectedNPNString);
[email protected]631f1322010-04-30 17:59:116477
6478 ProxyConfig proxy_config;
[email protected]d911f1b2010-05-05 22:39:426479 proxy_config.set_auto_detect(true);
6480 proxy_config.set_pac_url(GURL("http://fooproxyurl"));
[email protected]2227c692010-05-04 15:36:116481
[email protected]631f1322010-04-30 17:59:116482 CapturingProxyResolver* capturing_proxy_resolver =
6483 new CapturingProxyResolver();
[email protected]66761b952010-06-25 21:30:386484 SessionDependencies session_deps(new ProxyService(
6485 new ProxyConfigServiceFixed(proxy_config), capturing_proxy_resolver,
6486 NULL));
[email protected]631f1322010-04-30 17:59:116487
6488 HttpRequestInfo request;
6489 request.method = "GET";
6490 request.url = GURL("http://www.google.com/");
6491 request.load_flags = 0;
6492
6493 MockRead data_reads[] = {
6494 MockRead("HTTP/1.1 200 OK\r\n"),
[email protected]dae22c52010-07-30 02:16:356495 MockRead(kAlternateProtocolHttpHeader),
[email protected]631f1322010-04-30 17:59:116496 MockRead("hello world"),
6497 MockRead(true, OK),
6498 };
6499
6500 StaticSocketDataProvider first_transaction(
6501 data_reads, arraysize(data_reads), NULL, 0);
6502 session_deps.socket_factory.AddSocketDataProvider(&first_transaction);
6503
6504 SSLSocketDataProvider ssl(true, OK);
6505 ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
[email protected]dae22c52010-07-30 02:16:356506 ssl.next_proto = "spdy/2";
[email protected]65041fa2010-05-21 06:56:536507 ssl.was_npn_negotiated = true;
[email protected]631f1322010-04-30 17:59:116508 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
6509
[email protected]2bd93022010-07-17 00:58:446510 scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
[email protected]631f1322010-04-30 17:59:116511 MockWrite spdy_writes[] = {
6512 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
6513 "Host: www.google.com\r\n"
[email protected]d911f1b2010-05-05 22:39:426514 "Proxy-Connection: keep-alive\r\n\r\n"), // 0
[email protected]e7f75092010-07-01 22:39:136515 CreateMockWrite(*req) // 3
[email protected]631f1322010-04-30 17:59:116516 };
6517
[email protected]d911f1b2010-05-05 22:39:426518 const char kCONNECTResponse[] = "HTTP/1.1 200 Connected\r\n\r\n";
6519
[email protected]2bd93022010-07-17 00:58:446520 scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1));
6521 scoped_ptr<spdy::SpdyFrame> data(ConstructSpdyBodyFrame(1, true));
[email protected]631f1322010-04-30 17:59:116522 MockRead spdy_reads[] = {
[email protected]d911f1b2010-05-05 22:39:426523 MockRead(true, kCONNECTResponse, arraysize(kCONNECTResponse) - 1, 1), // 1
[email protected]e7f75092010-07-01 22:39:136524 CreateMockRead(*resp.get(), 4), // 2, 4
6525 CreateMockRead(*data.get(), 4), // 5
[email protected]d911f1b2010-05-05 22:39:426526 MockRead(true, 0, 0, 4), // 6
[email protected]631f1322010-04-30 17:59:116527 };
6528
[email protected]d911f1b2010-05-05 22:39:426529 scoped_refptr<OrderedSocketData> spdy_data(
6530 new OrderedSocketData(
[email protected]631f1322010-04-30 17:59:116531 spdy_reads, arraysize(spdy_reads),
6532 spdy_writes, arraysize(spdy_writes)));
6533 session_deps.socket_factory.AddSocketDataProvider(spdy_data);
6534
6535 TestCompletionCallback callback;
6536
6537 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
6538 scoped_ptr<HttpNetworkTransaction> trans(new HttpNetworkTransaction(session));
6539
6540 int rv = trans->Start(&request, &callback, BoundNetLog());
6541 EXPECT_EQ(ERR_IO_PENDING, rv);
6542 EXPECT_EQ(OK, callback.WaitForResult());
6543
6544 const HttpResponseInfo* response = trans->GetResponseInfo();
6545 ASSERT_TRUE(response != NULL);
6546 ASSERT_TRUE(response->headers != NULL);
6547 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
[email protected]65041fa2010-05-21 06:56:536548 EXPECT_FALSE(response->was_fetched_via_spdy);
6549 EXPECT_FALSE(response->was_npn_negotiated);
[email protected]631f1322010-04-30 17:59:116550
6551 std::string response_data;
6552 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
6553 EXPECT_EQ("hello world", response_data);
6554
6555 trans.reset(new HttpNetworkTransaction(session));
6556
6557 rv = trans->Start(&request, &callback, BoundNetLog());
6558 EXPECT_EQ(ERR_IO_PENDING, rv);
6559 EXPECT_EQ(OK, callback.WaitForResult());
6560
6561 response = trans->GetResponseInfo();
6562 ASSERT_TRUE(response != NULL);
6563 ASSERT_TRUE(response->headers != NULL);
6564 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
[email protected]65041fa2010-05-21 06:56:536565 EXPECT_TRUE(response->was_fetched_via_spdy);
6566 EXPECT_TRUE(response->was_npn_negotiated);
[email protected]631f1322010-04-30 17:59:116567
6568 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
6569 EXPECT_EQ("hello!", response_data);
[email protected]d911f1b2010-05-05 22:39:426570 ASSERT_EQ(2u, capturing_proxy_resolver->resolved().size());
6571 EXPECT_EQ("http://www.google.com/",
[email protected]631f1322010-04-30 17:59:116572 capturing_proxy_resolver->resolved()[0].spec());
[email protected]d911f1b2010-05-05 22:39:426573 EXPECT_EQ("https://www.google.com/",
6574 capturing_proxy_resolver->resolved()[1].spec());
[email protected]631f1322010-04-30 17:59:116575
[email protected]8e6441ca2010-08-19 05:56:386576 HttpStreamFactory::set_next_protos("");
6577 HttpStreamFactory::set_use_alternate_protocols(false);
[email protected]631f1322010-04-30 17:59:116578}
[email protected]631f1322010-04-30 17:59:116579
[email protected]2ff8b312010-04-26 22:20:546580TEST_F(HttpNetworkTransactionTest,
6581 UseAlternateProtocolForNpnSpdyWithExistingSpdySession) {
[email protected]8e6441ca2010-08-19 05:56:386582 HttpStreamFactory::set_use_alternate_protocols(true);
6583 HttpStreamFactory::set_next_protos(kExpectedNPNString);
[email protected]2ff8b312010-04-26 22:20:546584 SessionDependencies session_deps;
6585
6586 HttpRequestInfo request;
6587 request.method = "GET";
6588 request.url = GURL("http://www.google.com/");
6589 request.load_flags = 0;
6590
6591 MockRead data_reads[] = {
6592 MockRead("HTTP/1.1 200 OK\r\n"),
[email protected]dae22c52010-07-30 02:16:356593 MockRead(kAlternateProtocolHttpHeader),
[email protected]2ff8b312010-04-26 22:20:546594 MockRead("hello world"),
6595 MockRead(true, OK),
6596 };
6597
6598 StaticSocketDataProvider first_transaction(
6599 data_reads, arraysize(data_reads), NULL, 0);
6600 session_deps.socket_factory.AddSocketDataProvider(&first_transaction);
6601
6602 SSLSocketDataProvider ssl(true, OK);
6603 ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
[email protected]dae22c52010-07-30 02:16:356604 ssl.next_proto = "spdy/2";
[email protected]65041fa2010-05-21 06:56:536605 ssl.was_npn_negotiated = true;
[email protected]2ff8b312010-04-26 22:20:546606 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
[email protected]65041fa2010-05-21 06:56:536607 // Make sure we use ssl for spdy here.
6608 SpdySession::SetSSLMode(true);
[email protected]2ff8b312010-04-26 22:20:546609
[email protected]2bd93022010-07-17 00:58:446610 scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
[email protected]e7f75092010-07-01 22:39:136611 MockWrite spdy_writes[] = { CreateMockWrite(*req) };
[email protected]2ff8b312010-04-26 22:20:546612
[email protected]2bd93022010-07-17 00:58:446613 scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1));
6614 scoped_ptr<spdy::SpdyFrame> data(ConstructSpdyBodyFrame(1, true));
[email protected]2ff8b312010-04-26 22:20:546615 MockRead spdy_reads[] = {
[email protected]e7f75092010-07-01 22:39:136616 CreateMockRead(*resp),
6617 CreateMockRead(*data),
[email protected]2ff8b312010-04-26 22:20:546618 MockRead(true, 0, 0),
6619 };
6620
6621 scoped_refptr<DelayedSocketData> spdy_data(
6622 new DelayedSocketData(
6623 1, // wait for one write to finish before reading.
6624 spdy_reads, arraysize(spdy_reads),
6625 spdy_writes, arraysize(spdy_writes)));
6626 session_deps.socket_factory.AddSocketDataProvider(spdy_data);
6627
6628 TestCompletionCallback callback;
6629
6630 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
6631
6632 scoped_ptr<HttpNetworkTransaction> trans(new HttpNetworkTransaction(session));
6633
[email protected]5a1d7ca2010-04-28 20:12:276634 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]2ff8b312010-04-26 22:20:546635 EXPECT_EQ(ERR_IO_PENDING, rv);
6636 EXPECT_EQ(OK, callback.WaitForResult());
6637
6638 const HttpResponseInfo* response = trans->GetResponseInfo();
6639 ASSERT_TRUE(response != NULL);
6640 ASSERT_TRUE(response->headers != NULL);
6641 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
6642
6643 std::string response_data;
6644 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
6645 EXPECT_EQ("hello world", response_data);
6646
6647 // Set up an initial SpdySession in the pool to reuse.
[email protected]02b0c342010-09-25 21:09:386648 HostPortPair host_port_pair("www.google.com", 443);
6649 HostPortProxyPair pair(host_port_pair, ProxyServer::Direct());
[email protected]2ff8b312010-04-26 22:20:546650 scoped_refptr<SpdySession> spdy_session =
[email protected]f4580332010-09-25 21:20:276651 session->spdy_session_pool()->Get(pair, session->mutable_spdy_settings(),
6652 BoundNetLog());
[email protected]ad8e04a2010-11-01 04:16:276653 scoped_refptr<TCPSocketParams> tcp_params(
6654 new TCPSocketParams("www.google.com", 443, MEDIUM, GURL(), false));
[email protected]02b0c342010-09-25 21:09:386655
6656 scoped_ptr<ClientSocketHandle> connection(new ClientSocketHandle);
6657 EXPECT_EQ(ERR_IO_PENDING,
6658 connection->Init(host_port_pair.ToString(),tcp_params, LOWEST,
6659 &callback, session->tcp_socket_pool(),
6660 BoundNetLog()));
6661 EXPECT_EQ(OK, callback.WaitForResult());
6662
6663 SSLConfig ssl_config;
6664 session->ssl_config_service()->GetSSLConfig(&ssl_config);
6665 ClientSocket* socket = connection->release_socket();
[email protected]7ab5bbd12010-10-19 13:33:216666 socket = session->socket_factory()->CreateSSLClientSocket(
6667 socket, "" , ssl_config, NULL /* ssl_host_info */);
[email protected]02b0c342010-09-25 21:09:386668 connection->set_socket(socket);
6669 EXPECT_EQ(ERR_IO_PENDING, socket->Connect(&callback));
6670 EXPECT_EQ(OK, callback.WaitForResult());
6671
6672 EXPECT_EQ(OK, spdy_session->InitializeWithSocket(connection.release(),
6673 true, OK));
6674
[email protected]2ff8b312010-04-26 22:20:546675 trans.reset(new HttpNetworkTransaction(session));
6676
[email protected]5a1d7ca2010-04-28 20:12:276677 rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]2ff8b312010-04-26 22:20:546678 EXPECT_EQ(ERR_IO_PENDING, rv);
6679 EXPECT_EQ(OK, callback.WaitForResult());
6680
6681 response = trans->GetResponseInfo();
6682 ASSERT_TRUE(response != NULL);
6683 ASSERT_TRUE(response->headers != NULL);
6684 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
[email protected]65041fa2010-05-21 06:56:536685 EXPECT_TRUE(response->was_fetched_via_spdy);
6686 EXPECT_TRUE(response->was_npn_negotiated);
[email protected]193b0b892010-06-26 03:57:576687 EXPECT_TRUE(response->was_alternate_protocol_available);
[email protected]2ff8b312010-04-26 22:20:546688
6689 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
6690 EXPECT_EQ("hello!", response_data);
6691
[email protected]8e6441ca2010-08-19 05:56:386692 HttpStreamFactory::set_next_protos("");
6693 HttpStreamFactory::set_use_alternate_protocols(false);
[email protected]564b4912010-03-09 16:30:426694}
6695
[email protected]044de0642010-06-17 10:42:156696// GenerateAuthToken is a mighty big test.
6697// It tests all permutation of GenerateAuthToken behavior:
6698// - Synchronous and Asynchronous completion.
6699// - OK or error on completion.
6700// - Direct connection, non-authenticating proxy, and authenticating proxy.
6701// - HTTP or HTTPS backend (to include proxy tunneling).
6702// - Non-authenticating and authenticating backend.
6703//
6704// In all, there are 44 reasonable permuations (for example, if there are
6705// problems generating an auth token for an authenticating proxy, we don't
6706// need to test all permutations of the backend server).
6707//
6708// The test proceeds by going over each of the configuration cases, and
6709// potentially running up to three rounds in each of the tests. The TestConfig
6710// specifies both the configuration for the test as well as the expectations
6711// for the results.
6712TEST_F(HttpNetworkTransactionTest, GenerateAuthToken) {
[email protected]0b0bf032010-09-21 18:08:506713 static const char kServer[] = "http://www.example.com";
6714 static const char kSecureServer[] = "https://www.example.com";
6715 static const char kProxy[] = "myproxy:70";
[email protected]044de0642010-06-17 10:42:156716 const int kAuthErr = ERR_INVALID_AUTH_CREDENTIALS;
6717
6718 enum AuthTiming {
6719 AUTH_NONE,
6720 AUTH_SYNC,
6721 AUTH_ASYNC,
6722 };
6723
6724 const MockWrite kGet(
6725 "GET / HTTP/1.1\r\n"
6726 "Host: www.example.com\r\n"
6727 "Connection: keep-alive\r\n\r\n");
6728 const MockWrite kGetProxy(
6729 "GET http://www.example.com/ HTTP/1.1\r\n"
6730 "Host: www.example.com\r\n"
6731 "Proxy-Connection: keep-alive\r\n\r\n");
6732 const MockWrite kGetAuth(
6733 "GET / HTTP/1.1\r\n"
6734 "Host: www.example.com\r\n"
6735 "Connection: keep-alive\r\n"
6736 "Authorization: auth_token\r\n\r\n");
6737 const MockWrite kGetProxyAuth(
6738 "GET http://www.example.com/ HTTP/1.1\r\n"
6739 "Host: www.example.com\r\n"
6740 "Proxy-Connection: keep-alive\r\n"
6741 "Proxy-Authorization: auth_token\r\n\r\n");
6742 const MockWrite kGetAuthThroughProxy(
6743 "GET http://www.example.com/ HTTP/1.1\r\n"
6744 "Host: www.example.com\r\n"
6745 "Proxy-Connection: keep-alive\r\n"
6746 "Authorization: auth_token\r\n\r\n");
6747 const MockWrite kGetAuthWithProxyAuth(
6748 "GET http://www.example.com/ HTTP/1.1\r\n"
6749 "Host: www.example.com\r\n"
6750 "Proxy-Connection: keep-alive\r\n"
6751 "Proxy-Authorization: auth_token\r\n"
6752 "Authorization: auth_token\r\n\r\n");
6753 const MockWrite kConnect(
6754 "CONNECT www.example.com:443 HTTP/1.1\r\n"
6755 "Host: www.example.com\r\n"
6756 "Proxy-Connection: keep-alive\r\n\r\n");
6757 const MockWrite kConnectProxyAuth(
6758 "CONNECT www.example.com:443 HTTP/1.1\r\n"
6759 "Host: www.example.com\r\n"
6760 "Proxy-Connection: keep-alive\r\n"
6761 "Proxy-Authorization: auth_token\r\n\r\n");
6762
6763 const MockRead kSuccess(
6764 "HTTP/1.1 200 OK\r\n"
6765 "Content-Type: text/html; charset=iso-8859-1\r\n"
6766 "Content-Length: 3\r\n\r\n"
6767 "Yes");
6768 const MockRead kFailure(
6769 "Should not be called.");
6770 const MockRead kServerChallenge(
6771 "HTTP/1.1 401 Unauthorized\r\n"
6772 "WWW-Authenticate: Mock realm=server\r\n"
6773 "Content-Type: text/html; charset=iso-8859-1\r\n"
6774 "Content-Length: 14\r\n\r\n"
6775 "Unauthorized\r\n");
6776 const MockRead kProxyChallenge(
6777 "HTTP/1.1 407 Unauthorized\r\n"
6778 "Proxy-Authenticate: Mock realm=proxy\r\n"
6779 "Proxy-Connection: close\r\n"
6780 "Content-Type: text/html; charset=iso-8859-1\r\n"
6781 "Content-Length: 14\r\n\r\n"
6782 "Unauthorized\r\n");
6783 const MockRead kProxyConnected(
6784 "HTTP/1.1 200 Connection Established\r\n\r\n");
6785
6786 // NOTE(cbentzel): I wanted TestReadWriteRound to be a simple struct with
6787 // no constructors, but the C++ compiler on Windows warns about
6788 // unspecified data in compound literals. So, moved to using constructors,
6789 // and TestRound's created with the default constructor should not be used.
6790 struct TestRound {
6791 TestRound()
6792 : expected_rv(ERR_UNEXPECTED),
6793 extra_write(NULL),
6794 extra_read(NULL) {
6795 }
6796 TestRound(const MockWrite& write_arg, const MockRead& read_arg,
6797 int expected_rv_arg)
6798 : write(write_arg),
6799 read(read_arg),
6800 expected_rv(expected_rv_arg),
6801 extra_write(NULL),
6802 extra_read(NULL) {
6803 }
6804 TestRound(const MockWrite& write_arg, const MockRead& read_arg,
6805 int expected_rv_arg, const MockWrite* extra_write_arg,
6806 const MockWrite* extra_read_arg)
6807 : write(write_arg),
6808 read(read_arg),
6809 expected_rv(expected_rv_arg),
6810 extra_write(extra_write_arg),
6811 extra_read(extra_read_arg) {
6812 }
6813 MockWrite write;
6814 MockRead read;
6815 int expected_rv;
6816 const MockWrite* extra_write;
6817 const MockRead* extra_read;
6818 };
6819
6820 static const int kNoSSL = 500;
6821
6822 struct TestConfig {
6823 const char* proxy_url;
6824 AuthTiming proxy_auth_timing;
6825 int proxy_auth_rv;
6826 const char* server_url;
6827 AuthTiming server_auth_timing;
6828 int server_auth_rv;
6829 int num_auth_rounds;
6830 int first_ssl_round;
6831 TestRound rounds[3];
6832 } test_configs[] = {
6833 // Non-authenticating HTTP server with a direct connection.
6834 { NULL, AUTH_NONE, OK, kServer, AUTH_NONE, OK, 1, kNoSSL,
6835 { TestRound(kGet, kSuccess, OK)}},
6836 // Authenticating HTTP server with a direct connection.
6837 { NULL, AUTH_NONE, OK, kServer, AUTH_SYNC, OK, 2, kNoSSL,
6838 { TestRound(kGet, kServerChallenge, OK),
6839 TestRound(kGetAuth, kSuccess, OK)}},
6840 { NULL, AUTH_NONE, OK, kServer, AUTH_SYNC, kAuthErr, 2, kNoSSL,
6841 { TestRound(kGet, kServerChallenge, OK),
6842 TestRound(kGetAuth, kFailure, kAuthErr)}},
6843 { NULL, AUTH_NONE, OK, kServer, AUTH_ASYNC, OK, 2, kNoSSL,
6844 { TestRound(kGet, kServerChallenge, OK),
6845 TestRound(kGetAuth, kSuccess, OK)}},
6846 { NULL, AUTH_NONE, OK, kServer, AUTH_ASYNC, kAuthErr, 2, kNoSSL,
6847 { TestRound(kGet, kServerChallenge, OK),
6848 TestRound(kGetAuth, kFailure, kAuthErr)}},
6849 // Non-authenticating HTTP server through a non-authenticating proxy.
6850 { kProxy, AUTH_NONE, OK, kServer, AUTH_NONE, OK, 1, kNoSSL,
6851 { TestRound(kGetProxy, kSuccess, OK)}},
6852 // Authenticating HTTP server through a non-authenticating proxy.
6853 { kProxy, AUTH_NONE, OK, kServer, AUTH_SYNC, OK, 2, kNoSSL,
6854 { TestRound(kGetProxy, kServerChallenge, OK),
6855 TestRound(kGetAuthThroughProxy, kSuccess, OK)}},
6856 { kProxy, AUTH_NONE, OK, kServer, AUTH_SYNC, kAuthErr, 2, kNoSSL,
6857 { TestRound(kGetProxy, kServerChallenge, OK),
6858 TestRound(kGetAuthThroughProxy, kFailure, kAuthErr)}},
6859 { kProxy, AUTH_NONE, OK, kServer, AUTH_ASYNC, OK, 2, kNoSSL,
6860 { TestRound(kGetProxy, kServerChallenge, OK),
6861 TestRound(kGetAuthThroughProxy, kSuccess, OK)}},
6862 { kProxy, AUTH_NONE, OK, kServer, AUTH_ASYNC, kAuthErr, 2, kNoSSL,
6863 { TestRound(kGetProxy, kServerChallenge, OK),
6864 TestRound(kGetAuthThroughProxy, kFailure, kAuthErr)}},
6865 // Non-authenticating HTTP server through an authenticating proxy.
6866 { kProxy, AUTH_SYNC, OK, kServer, AUTH_NONE, OK, 2, kNoSSL,
6867 { TestRound(kGetProxy, kProxyChallenge, OK),
6868 TestRound(kGetProxyAuth, kSuccess, OK)}},
6869 { kProxy, AUTH_SYNC, kAuthErr, kServer, AUTH_NONE, OK, 2, kNoSSL,
6870 { TestRound(kGetProxy, kProxyChallenge, OK),
6871 TestRound(kGetProxyAuth, kFailure, kAuthErr)}},
6872 { kProxy, AUTH_ASYNC, OK, kServer, AUTH_NONE, OK, 2, kNoSSL,
6873 { TestRound(kGetProxy, kProxyChallenge, OK),
6874 TestRound(kGetProxyAuth, kSuccess, OK)}},
6875 { kProxy, AUTH_ASYNC, kAuthErr, kServer, AUTH_NONE, OK, 2, kNoSSL,
6876 { TestRound(kGetProxy, kProxyChallenge, OK),
6877 TestRound(kGetProxyAuth, kFailure, kAuthErr)}},
6878 // Authenticating HTTP server through an authenticating proxy.
6879 { kProxy, AUTH_SYNC, OK, kServer, AUTH_SYNC, OK, 3, kNoSSL,
6880 { TestRound(kGetProxy, kProxyChallenge, OK),
6881 TestRound(kGetProxyAuth, kServerChallenge, OK),
6882 TestRound(kGetAuthWithProxyAuth, kSuccess, OK)}},
6883 { kProxy, AUTH_SYNC, OK, kServer, AUTH_SYNC, kAuthErr, 3, kNoSSL,
6884 { TestRound(kGetProxy, kProxyChallenge, OK),
6885 TestRound(kGetProxyAuth, kServerChallenge, OK),
6886 TestRound(kGetAuthWithProxyAuth, kFailure, kAuthErr)}},
6887 { kProxy, AUTH_ASYNC, OK, kServer, AUTH_SYNC, OK, 3, kNoSSL,
6888 { TestRound(kGetProxy, kProxyChallenge, OK),
6889 TestRound(kGetProxyAuth, kServerChallenge, OK),
6890 TestRound(kGetAuthWithProxyAuth, kSuccess, OK)}},
6891 { kProxy, AUTH_ASYNC, OK, kServer, AUTH_SYNC, kAuthErr, 3, kNoSSL,
6892 { TestRound(kGetProxy, kProxyChallenge, OK),
6893 TestRound(kGetProxyAuth, kServerChallenge, OK),
6894 TestRound(kGetAuthWithProxyAuth, kFailure, kAuthErr)}},
6895 { kProxy, AUTH_SYNC, OK, kServer, AUTH_ASYNC, OK, 3, kNoSSL,
6896 { TestRound(kGetProxy, kProxyChallenge, OK),
6897 TestRound(kGetProxyAuth, kServerChallenge, OK),
6898 TestRound(kGetAuthWithProxyAuth, kSuccess, OK)}},
6899 { kProxy, AUTH_SYNC, OK, kServer, AUTH_ASYNC, kAuthErr, 3, kNoSSL,
6900 { TestRound(kGetProxy, kProxyChallenge, OK),
6901 TestRound(kGetProxyAuth, kServerChallenge, OK),
6902 TestRound(kGetAuthWithProxyAuth, kFailure, kAuthErr)}},
6903 { kProxy, AUTH_ASYNC, OK, kServer, AUTH_ASYNC, OK, 3, kNoSSL,
6904 { TestRound(kGetProxy, kProxyChallenge, OK),
6905 TestRound(kGetProxyAuth, kServerChallenge, OK),
6906 TestRound(kGetAuthWithProxyAuth, kSuccess, OK)}},
6907 { kProxy, AUTH_ASYNC, OK, kServer, AUTH_ASYNC, kAuthErr, 3, kNoSSL,
6908 { TestRound(kGetProxy, kProxyChallenge, OK),
6909 TestRound(kGetProxyAuth, kServerChallenge, OK),
6910 TestRound(kGetAuthWithProxyAuth, kFailure, kAuthErr)}},
6911 // Non-authenticating HTTPS server with a direct connection.
6912 { NULL, AUTH_NONE, OK, kSecureServer, AUTH_NONE, OK, 1, 0,
6913 { TestRound(kGet, kSuccess, OK)}},
6914 // Authenticating HTTPS server with a direct connection.
6915 { NULL, AUTH_NONE, OK, kSecureServer, AUTH_SYNC, OK, 2, 0,
6916 { TestRound(kGet, kServerChallenge, OK),
6917 TestRound(kGetAuth, kSuccess, OK)}},
6918 { NULL, AUTH_NONE, OK, kSecureServer, AUTH_SYNC, kAuthErr, 2, 0,
6919 { TestRound(kGet, kServerChallenge, OK),
6920 TestRound(kGetAuth, kFailure, kAuthErr)}},
6921 { NULL, AUTH_NONE, OK, kSecureServer, AUTH_ASYNC, OK, 2, 0,
6922 { TestRound(kGet, kServerChallenge, OK),
6923 TestRound(kGetAuth, kSuccess, OK)}},
6924 { NULL, AUTH_NONE, OK, kSecureServer, AUTH_ASYNC, kAuthErr, 2, 0,
6925 { TestRound(kGet, kServerChallenge, OK),
6926 TestRound(kGetAuth, kFailure, kAuthErr)}},
6927 // Non-authenticating HTTPS server with a non-authenticating proxy.
6928 { kProxy, AUTH_NONE, OK, kSecureServer, AUTH_NONE, OK, 1, 0,
6929 { TestRound(kConnect, kProxyConnected, OK, &kGet, &kSuccess)}},
6930 // Authenticating HTTPS server through a non-authenticating proxy.
6931 { kProxy, AUTH_NONE, OK, kSecureServer, AUTH_SYNC, OK, 2, 0,
6932 { TestRound(kConnect, kProxyConnected, OK, &kGet, &kServerChallenge),
6933 TestRound(kGetAuth, kSuccess, OK)}},
6934 { kProxy, AUTH_NONE, OK, kSecureServer, AUTH_SYNC, kAuthErr, 2, 0,
6935 { TestRound(kConnect, kProxyConnected, OK, &kGet, &kServerChallenge),
6936 TestRound(kGetAuth, kFailure, kAuthErr)}},
6937 { kProxy, AUTH_NONE, OK, kSecureServer, AUTH_ASYNC, OK, 2, 0,
6938 { TestRound(kConnect, kProxyConnected, OK, &kGet, &kServerChallenge),
6939 TestRound(kGetAuth, kSuccess, OK)}},
6940 { kProxy, AUTH_NONE, OK, kSecureServer, AUTH_ASYNC, kAuthErr, 2, 0,
6941 { TestRound(kConnect, kProxyConnected, OK, &kGet, &kServerChallenge),
6942 TestRound(kGetAuth, kFailure, kAuthErr)}},
6943 // Non-Authenticating HTTPS server through an authenticating proxy.
6944 { kProxy, AUTH_SYNC, OK, kSecureServer, AUTH_NONE, OK, 2, 1,
6945 { TestRound(kConnect, kProxyChallenge, OK),
6946 TestRound(kConnectProxyAuth, kProxyConnected, OK, &kGet, &kSuccess)}},
6947 { kProxy, AUTH_SYNC, kAuthErr, kSecureServer, AUTH_NONE, OK, 2, kNoSSL,
6948 { TestRound(kConnect, kProxyChallenge, OK),
6949 TestRound(kConnectProxyAuth, kFailure, kAuthErr)}},
6950 { kProxy, AUTH_ASYNC, OK, kSecureServer, AUTH_NONE, OK, 2, 1,
6951 { TestRound(kConnect, kProxyChallenge, OK),
6952 TestRound(kConnectProxyAuth, kProxyConnected, OK, &kGet, &kSuccess)}},
6953 { kProxy, AUTH_ASYNC, kAuthErr, kSecureServer, AUTH_NONE, OK, 2, kNoSSL,
6954 { TestRound(kConnect, kProxyChallenge, OK),
6955 TestRound(kConnectProxyAuth, kFailure, kAuthErr)}},
6956 // Authenticating HTTPS server through an authenticating proxy.
6957 { kProxy, AUTH_SYNC, OK, kSecureServer, AUTH_SYNC, OK, 3, 1,
6958 { TestRound(kConnect, kProxyChallenge, OK),
6959 TestRound(kConnectProxyAuth, kProxyConnected, OK,
6960 &kGet, &kServerChallenge),
6961 TestRound(kGetAuth, kSuccess, OK)}},
6962 { kProxy, AUTH_SYNC, OK, kSecureServer, AUTH_SYNC, kAuthErr, 3, 1,
6963 { TestRound(kConnect, kProxyChallenge, OK),
6964 TestRound(kConnectProxyAuth, kProxyConnected, OK,
6965 &kGet, &kServerChallenge),
6966 TestRound(kGetAuth, kFailure, kAuthErr)}},
6967 { kProxy, AUTH_ASYNC, OK, kSecureServer, AUTH_SYNC, OK, 3, 1,
6968 { TestRound(kConnect, kProxyChallenge, OK),
6969 TestRound(kConnectProxyAuth, kProxyConnected, OK,
6970 &kGet, &kServerChallenge),
6971 TestRound(kGetAuth, kSuccess, OK)}},
6972 { kProxy, AUTH_ASYNC, OK, kSecureServer, AUTH_SYNC, kAuthErr, 3, 1,
6973 { TestRound(kConnect, kProxyChallenge, OK),
6974 TestRound(kConnectProxyAuth, kProxyConnected, OK,
6975 &kGet, &kServerChallenge),
6976 TestRound(kGetAuth, kFailure, kAuthErr)}},
6977 { kProxy, AUTH_SYNC, OK, kSecureServer, AUTH_ASYNC, OK, 3, 1,
6978 { TestRound(kConnect, kProxyChallenge, OK),
6979 TestRound(kConnectProxyAuth, kProxyConnected, OK,
6980 &kGet, &kServerChallenge),
6981 TestRound(kGetAuth, kSuccess, OK)}},
6982 { kProxy, AUTH_SYNC, OK, kSecureServer, AUTH_ASYNC, kAuthErr, 3, 1,
6983 { TestRound(kConnect, kProxyChallenge, OK),
6984 TestRound(kConnectProxyAuth, kProxyConnected, OK,
6985 &kGet, &kServerChallenge),
6986 TestRound(kGetAuth, kFailure, kAuthErr)}},
6987 { kProxy, AUTH_ASYNC, OK, kSecureServer, AUTH_ASYNC, OK, 3, 1,
6988 { TestRound(kConnect, kProxyChallenge, OK),
6989 TestRound(kConnectProxyAuth, kProxyConnected, OK,
6990 &kGet, &kServerChallenge),
6991 TestRound(kGetAuth, kSuccess, OK)}},
6992 { kProxy, AUTH_ASYNC, OK, kSecureServer, AUTH_ASYNC, kAuthErr, 3, 1,
6993 { TestRound(kConnect, kProxyChallenge, OK),
6994 TestRound(kConnectProxyAuth, kProxyConnected, OK,
6995 &kGet, &kServerChallenge),
6996 TestRound(kGetAuth, kFailure, kAuthErr)}},
6997 };
6998
6999 SessionDependencies session_deps;
[email protected]3fd9dae2010-06-21 11:39:007000 HttpAuthHandlerMock::Factory* auth_factory(
7001 new HttpAuthHandlerMock::Factory());
[email protected]044de0642010-06-17 10:42:157002 session_deps.http_auth_handler_factory.reset(auth_factory);
7003
7004 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(test_configs); ++i) {
7005 const TestConfig& test_config = test_configs[i];
[email protected]65d34382010-07-01 18:12:267006
7007 // Set up authentication handlers as necessary.
[email protected]044de0642010-06-17 10:42:157008 if (test_config.proxy_auth_timing != AUTH_NONE) {
[email protected]3fd9dae2010-06-21 11:39:007009 HttpAuthHandlerMock* auth_handler(new HttpAuthHandlerMock());
[email protected]044de0642010-06-17 10:42:157010 std::string auth_challenge = "Mock realm=proxy";
7011 GURL origin(test_config.proxy_url);
7012 HttpAuth::ChallengeTokenizer tokenizer(auth_challenge.begin(),
7013 auth_challenge.end());
7014 auth_handler->InitFromChallenge(&tokenizer, HttpAuth::AUTH_PROXY,
7015 origin, BoundNetLog());
7016 auth_handler->SetGenerateExpectation(
7017 test_config.proxy_auth_timing == AUTH_ASYNC,
7018 test_config.proxy_auth_rv);
[email protected]044de0642010-06-17 10:42:157019 auth_factory->set_mock_handler(auth_handler, HttpAuth::AUTH_PROXY);
7020 }
7021 if (test_config.server_auth_timing != AUTH_NONE) {
[email protected]3fd9dae2010-06-21 11:39:007022 HttpAuthHandlerMock* auth_handler(new HttpAuthHandlerMock());
[email protected]044de0642010-06-17 10:42:157023 std::string auth_challenge = "Mock realm=server";
7024 GURL origin(test_config.server_url);
7025 HttpAuth::ChallengeTokenizer tokenizer(auth_challenge.begin(),
7026 auth_challenge.end());
7027 auth_handler->InitFromChallenge(&tokenizer, HttpAuth::AUTH_SERVER,
7028 origin, BoundNetLog());
7029 auth_handler->SetGenerateExpectation(
7030 test_config.server_auth_timing == AUTH_ASYNC,
7031 test_config.server_auth_rv);
[email protected]044de0642010-06-17 10:42:157032 auth_factory->set_mock_handler(auth_handler, HttpAuth::AUTH_SERVER);
7033 }
7034 if (test_config.proxy_url) {
7035 session_deps.proxy_service =
[email protected]81cdfcd2010-10-16 00:49:007036 ProxyService::CreateFixed(test_config.proxy_url);
[email protected]044de0642010-06-17 10:42:157037 } else {
[email protected]ebeefff32010-09-15 05:10:027038 session_deps.proxy_service = ProxyService::CreateDirect();
[email protected]044de0642010-06-17 10:42:157039 }
7040
7041 HttpRequestInfo request;
7042 request.method = "GET";
7043 request.url = GURL(test_config.server_url);
7044 request.load_flags = 0;
7045
[email protected]0b0bf032010-09-21 18:08:507046 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
7047 HttpNetworkTransaction trans(CreateSession(&session_deps));
[email protected]044de0642010-06-17 10:42:157048
7049 for (int round = 0; round < test_config.num_auth_rounds; ++round) {
7050 const TestRound& read_write_round = test_config.rounds[round];
7051
7052 // Set up expected reads and writes.
7053 MockRead reads[2];
7054 reads[0] = read_write_round.read;
7055 size_t length_reads = 1;
7056 if (read_write_round.extra_read) {
7057 reads[1] = *read_write_round.extra_read;
7058 length_reads = 2;
7059 }
7060
7061 MockWrite writes[2];
7062 writes[0] = read_write_round.write;
7063 size_t length_writes = 1;
7064 if (read_write_round.extra_write) {
7065 writes[1] = *read_write_round.extra_write;
7066 length_writes = 2;
7067 }
7068 StaticSocketDataProvider data_provider(
7069 reads, length_reads, writes, length_writes);
7070 session_deps.socket_factory.AddSocketDataProvider(&data_provider);
7071
7072 // Add an SSL sequence if necessary.
7073 SSLSocketDataProvider ssl_socket_data_provider(false, OK);
7074 if (round >= test_config.first_ssl_round)
7075 session_deps.socket_factory.AddSSLSocketDataProvider(
7076 &ssl_socket_data_provider);
7077
7078 // Start or restart the transaction.
7079 TestCompletionCallback callback;
7080 int rv;
7081 if (round == 0) {
[email protected]0b0bf032010-09-21 18:08:507082 rv = trans.Start(&request, &callback, BoundNetLog());
[email protected]044de0642010-06-17 10:42:157083 } else {
[email protected]0b0bf032010-09-21 18:08:507084 rv = trans.RestartWithAuth(kFoo, kBar, &callback);
[email protected]044de0642010-06-17 10:42:157085 }
7086 if (rv == ERR_IO_PENDING)
7087 rv = callback.WaitForResult();
7088
7089 // Compare results with expected data.
7090 EXPECT_EQ(read_write_round.expected_rv, rv);
[email protected]0b0bf032010-09-21 18:08:507091 const HttpResponseInfo* response = trans.GetResponseInfo();
[email protected]044de0642010-06-17 10:42:157092 if (read_write_round.expected_rv == OK) {
7093 EXPECT_FALSE(response == NULL);
7094 } else {
7095 EXPECT_TRUE(response == NULL);
7096 EXPECT_EQ(round + 1, test_config.num_auth_rounds);
7097 continue;
7098 }
7099 if (round + 1 < test_config.num_auth_rounds) {
7100 EXPECT_FALSE(response->auth_challenge.get() == NULL);
7101 } else {
7102 EXPECT_TRUE(response->auth_challenge.get() == NULL);
7103 }
7104 }
[email protected]e5ae96a2010-04-14 20:12:457105 }
7106}
7107
[email protected]c871bce92010-07-15 21:51:147108TEST_F(HttpNetworkTransactionTest, MultiRoundAuth) {
7109 // Do multi-round authentication and make sure it works correctly.
7110 SessionDependencies session_deps;
7111 HttpAuthHandlerMock::Factory* auth_factory(
7112 new HttpAuthHandlerMock::Factory());
7113 session_deps.http_auth_handler_factory.reset(auth_factory);
[email protected]ebeefff32010-09-15 05:10:027114 session_deps.proxy_service = ProxyService::CreateDirect();
[email protected]c871bce92010-07-15 21:51:147115 session_deps.host_resolver->rules()->AddRule("www.example.com", "10.0.0.1");
7116 session_deps.host_resolver->set_synchronous_mode(true);
7117
7118 HttpAuthHandlerMock* auth_handler(new HttpAuthHandlerMock());
7119 auth_handler->set_connection_based(true);
7120 std::string auth_challenge = "Mock realm=server";
7121 GURL origin("http://www.example.com");
7122 HttpAuth::ChallengeTokenizer tokenizer(auth_challenge.begin(),
7123 auth_challenge.end());
7124 auth_handler->InitFromChallenge(&tokenizer, HttpAuth::AUTH_SERVER,
7125 origin, BoundNetLog());
7126 auth_factory->set_mock_handler(auth_handler, HttpAuth::AUTH_SERVER);
7127
[email protected]ad8e04a2010-11-01 04:16:277128 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]c871bce92010-07-15 21:51:147129 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
7130
7131 int rv = OK;
7132 const HttpResponseInfo* response = NULL;
7133 HttpRequestInfo request;
7134 request.method = "GET";
7135 request.url = origin;
7136 request.load_flags = 0;
7137 TestCompletionCallback callback;
7138
7139 const MockWrite kGet(
7140 "GET / HTTP/1.1\r\n"
7141 "Host: www.example.com\r\n"
7142 "Connection: keep-alive\r\n\r\n");
7143 const MockWrite kGetAuth(
7144 "GET / HTTP/1.1\r\n"
7145 "Host: www.example.com\r\n"
7146 "Connection: keep-alive\r\n"
7147 "Authorization: auth_token\r\n\r\n");
7148
7149 const MockRead kServerChallenge(
7150 "HTTP/1.1 401 Unauthorized\r\n"
7151 "WWW-Authenticate: Mock realm=server\r\n"
7152 "Content-Type: text/html; charset=iso-8859-1\r\n"
7153 "Content-Length: 14\r\n\r\n"
7154 "Unauthorized\r\n");
7155 const MockRead kSuccess(
7156 "HTTP/1.1 200 OK\r\n"
7157 "Content-Type: text/html; charset=iso-8859-1\r\n"
7158 "Content-Length: 3\r\n\r\n"
7159 "Yes");
7160
7161 MockWrite writes[] = {
7162 // First round
7163 kGet,
7164 // Second round
7165 kGetAuth,
7166 // Third round
7167 kGetAuth,
[email protected]eca50e122010-09-11 14:03:307168 // Fourth round
7169 kGetAuth
[email protected]c871bce92010-07-15 21:51:147170 };
7171 MockRead reads[] = {
7172 // First round
7173 kServerChallenge,
7174 // Second round
7175 kServerChallenge,
7176 // Third round
[email protected]eca50e122010-09-11 14:03:307177 kServerChallenge,
7178 // Fourth round
[email protected]c871bce92010-07-15 21:51:147179 kSuccess,
7180 };
7181 StaticSocketDataProvider data_provider(reads, arraysize(reads),
7182 writes, arraysize(writes));
7183 session_deps.socket_factory.AddSocketDataProvider(&data_provider);
7184
7185 // First round
7186 auth_handler->SetGenerateExpectation(false, OK);
7187 rv = trans->Start(&request, &callback, BoundNetLog());
7188 if (rv == ERR_IO_PENDING)
7189 rv = callback.WaitForResult();
7190 EXPECT_EQ(OK, rv);
7191 response = trans->GetResponseInfo();
7192 ASSERT_FALSE(response == NULL);
7193 EXPECT_FALSE(response->auth_challenge.get() == NULL);
7194
7195 // Second round
7196 auth_handler->SetGenerateExpectation(false, OK);
[email protected]13c8a092010-07-29 06:15:447197 rv = trans->RestartWithAuth(kFoo, kBar, &callback);
[email protected]c871bce92010-07-15 21:51:147198 if (rv == ERR_IO_PENDING)
7199 rv = callback.WaitForResult();
7200 EXPECT_EQ(OK, rv);
7201 response = trans->GetResponseInfo();
7202 ASSERT_FALSE(response == NULL);
7203 EXPECT_TRUE(response->auth_challenge.get() == NULL);
7204
7205 // Third round
7206 auth_handler->SetGenerateExpectation(false, OK);
[email protected]13c8a092010-07-29 06:15:447207 rv = trans->RestartWithAuth(string16(), string16(), &callback);
[email protected]c871bce92010-07-15 21:51:147208 if (rv == ERR_IO_PENDING)
7209 rv = callback.WaitForResult();
7210 EXPECT_EQ(OK, rv);
7211 response = trans->GetResponseInfo();
7212 ASSERT_FALSE(response == NULL);
7213 EXPECT_TRUE(response->auth_challenge.get() == NULL);
[email protected]eca50e122010-09-11 14:03:307214
7215 // Fourth round
7216 auth_handler->SetGenerateExpectation(false, OK);
7217 rv = trans->RestartWithAuth(string16(), string16(), &callback);
7218 if (rv == ERR_IO_PENDING)
7219 rv = callback.WaitForResult();
7220 EXPECT_EQ(OK, rv);
7221 response = trans->GetResponseInfo();
7222 ASSERT_FALSE(response == NULL);
7223 EXPECT_TRUE(response->auth_challenge.get() == NULL);
[email protected]c871bce92010-07-15 21:51:147224}
7225
[email protected]aeaca1f2010-04-20 22:05:217226class TLSDecompressionFailureSocketDataProvider : public SocketDataProvider {
7227 public:
[email protected]06650c52010-06-03 00:49:177228 explicit TLSDecompressionFailureSocketDataProvider(bool fail_all)
[email protected]aeaca1f2010-04-20 22:05:217229 : fail_all_(fail_all) {
7230 }
7231
7232 virtual MockRead GetNextRead() {
7233 if (fail_all_)
7234 return MockRead(false /* async */, ERR_SSL_DECOMPRESSION_FAILURE_ALERT);
7235
7236 return MockRead(false /* async */,
7237 "HTTP/1.1 200 OK\r\nContent-Length: 3\r\n\r\nok.\r\n");
7238 }
7239
7240 virtual MockWriteResult OnWrite(const std::string& data) {
7241 return MockWriteResult(false /* async */, data.size());
7242 }
7243
7244 void Reset() {
7245 }
7246
7247 private:
7248 const bool fail_all_;
7249};
7250
7251// Test that we restart a connection when we see a decompression failure from
7252// the peer during the handshake. (In the real world we'll restart with SSLv3
7253// and we won't offer DEFLATE in that case.)
7254TEST_F(HttpNetworkTransactionTest, RestartAfterTLSDecompressionFailure) {
7255 HttpRequestInfo request;
7256 request.method = "GET";
7257 request.url = GURL("https://tlsdecompressionfailure.example.com/");
7258 request.load_flags = 0;
7259
7260 SessionDependencies session_deps;
7261 TLSDecompressionFailureSocketDataProvider socket_data_provider1(
7262 false /* fail all reads */);
7263 TLSDecompressionFailureSocketDataProvider socket_data_provider2(false);
7264 SSLSocketDataProvider ssl_socket_data_provider1(
[email protected]2227c692010-05-04 15:36:117265 false, ERR_SSL_DECOMPRESSION_FAILURE_ALERT);
[email protected]aeaca1f2010-04-20 22:05:217266 SSLSocketDataProvider ssl_socket_data_provider2(false, OK);
7267 session_deps.socket_factory.AddSocketDataProvider(&socket_data_provider1);
7268 session_deps.socket_factory.AddSocketDataProvider(&socket_data_provider2);
7269 session_deps.socket_factory.AddSSLSocketDataProvider(
7270 &ssl_socket_data_provider1);
7271 session_deps.socket_factory.AddSSLSocketDataProvider(
7272 &ssl_socket_data_provider2);
7273
[email protected]e60e47a2010-07-14 03:37:187274 // Work around http://crbug.com/37454
7275 StaticSocketDataProvider bug37454_connection;
7276 bug37454_connection.set_connect_data(MockConnect(true, ERR_UNEXPECTED));
7277 session_deps.socket_factory.AddSocketDataProvider(&bug37454_connection);
7278
[email protected]aeaca1f2010-04-20 22:05:217279 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
7280 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
7281 TestCompletionCallback callback;
7282
[email protected]5a1d7ca2010-04-28 20:12:277283 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]aeaca1f2010-04-20 22:05:217284 EXPECT_EQ(ERR_IO_PENDING, rv);
7285 EXPECT_EQ(OK, callback.WaitForResult());
7286
7287 const HttpResponseInfo* response = trans->GetResponseInfo();
7288 ASSERT_TRUE(response != NULL);
7289 ASSERT_TRUE(response->headers != NULL);
7290 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
7291
7292 std::string response_data;
7293 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
7294 EXPECT_EQ("ok.", response_data);
7295}
7296
7297// Test that we restart a connection if we get a decompression failure from the
7298// peer while reading the first bytes from the connection. This occurs when the
7299// peer cannot handle DEFLATE but we're using False Start, so we don't notice
7300// in the handshake.
7301TEST_F(HttpNetworkTransactionTest,
7302 RestartAfterTLSDecompressionFailureWithFalseStart) {
7303 HttpRequestInfo request;
7304 request.method = "GET";
7305 request.url = GURL("https://tlsdecompressionfailure2.example.com/");
7306 request.load_flags = 0;
7307
7308 SessionDependencies session_deps;
7309 TLSDecompressionFailureSocketDataProvider socket_data_provider1(
7310 true /* fail all reads */);
7311 TLSDecompressionFailureSocketDataProvider socket_data_provider2(false);
7312 SSLSocketDataProvider ssl_socket_data_provider1(false, OK);
7313 SSLSocketDataProvider ssl_socket_data_provider2(false, OK);
7314 session_deps.socket_factory.AddSocketDataProvider(&socket_data_provider1);
7315 session_deps.socket_factory.AddSocketDataProvider(&socket_data_provider2);
7316 session_deps.socket_factory.AddSSLSocketDataProvider(
7317 &ssl_socket_data_provider1);
7318 session_deps.socket_factory.AddSSLSocketDataProvider(
7319 &ssl_socket_data_provider2);
7320
7321 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
7322 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
7323 TestCompletionCallback callback;
7324
[email protected]5a1d7ca2010-04-28 20:12:277325 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]aeaca1f2010-04-20 22:05:217326 EXPECT_EQ(ERR_IO_PENDING, rv);
7327 EXPECT_EQ(OK, callback.WaitForResult());
7328
7329 const HttpResponseInfo* response = trans->GetResponseInfo();
7330 ASSERT_TRUE(response != NULL);
7331 ASSERT_TRUE(response->headers != NULL);
7332 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
7333
7334 std::string response_data;
7335 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
7336 EXPECT_EQ("ok.", response_data);
7337}
7338
[email protected]65041fa2010-05-21 06:56:537339// This tests the case that a request is issued via http instead of spdy after
7340// npn is negotiated.
7341TEST_F(HttpNetworkTransactionTest, NpnWithHttpOverSSL) {
[email protected]8e6441ca2010-08-19 05:56:387342 HttpStreamFactory::set_use_alternate_protocols(true);
7343 HttpStreamFactory::set_next_protos("\x08http/1.1\x07http1.1");
[email protected]65041fa2010-05-21 06:56:537344 SessionDependencies session_deps;
7345 HttpRequestInfo request;
7346 request.method = "GET";
7347 request.url = GURL("https://www.google.com/");
7348 request.load_flags = 0;
7349
7350 MockWrite data_writes[] = {
7351 MockWrite("GET / HTTP/1.1\r\n"
7352 "Host: www.google.com\r\n"
7353 "Connection: keep-alive\r\n\r\n"),
7354 };
7355
7356 MockRead data_reads[] = {
7357 MockRead("HTTP/1.1 200 OK\r\n"),
[email protected]dae22c52010-07-30 02:16:357358 MockRead(kAlternateProtocolHttpHeader),
[email protected]65041fa2010-05-21 06:56:537359 MockRead("hello world"),
7360 MockRead(false, OK),
7361 };
7362
7363 SSLSocketDataProvider ssl(true, OK);
7364 ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
7365 ssl.next_proto = "http/1.1";
7366
7367 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
7368
7369 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
7370 data_writes, arraysize(data_writes));
7371 session_deps.socket_factory.AddSocketDataProvider(&data);
7372
7373 TestCompletionCallback callback;
7374
7375 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
7376 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
7377
7378 int rv = trans->Start(&request, &callback, BoundNetLog());
7379
7380 EXPECT_EQ(ERR_IO_PENDING, rv);
7381 EXPECT_EQ(OK, callback.WaitForResult());
7382
7383 const HttpResponseInfo* response = trans->GetResponseInfo();
7384 ASSERT_TRUE(response != NULL);
7385 ASSERT_TRUE(response->headers != NULL);
7386 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
7387
7388 std::string response_data;
7389 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
7390 EXPECT_EQ("hello world", response_data);
7391
7392 EXPECT_FALSE(response->was_fetched_via_spdy);
7393 EXPECT_TRUE(response->was_npn_negotiated);
[email protected]193b0b892010-06-26 03:57:577394 EXPECT_FALSE(response->was_alternate_protocol_available);
[email protected]65041fa2010-05-21 06:56:537395
[email protected]8e6441ca2010-08-19 05:56:387396 HttpStreamFactory::set_next_protos("");
7397 HttpStreamFactory::set_use_alternate_protocols(false);
[email protected]65041fa2010-05-21 06:56:537398}
[email protected]26ef6582010-06-24 02:30:477399
7400TEST_F(HttpNetworkTransactionTest, SpdyPostNPNServerHangup) {
7401 // Simulate the SSL handshake completing with an NPN negotiation
7402 // followed by an immediate server closing of the socket.
7403 // Fix crash: http://crbug.com/46369
[email protected]8e6441ca2010-08-19 05:56:387404 HttpStreamFactory::set_use_alternate_protocols(true);
7405 HttpStreamFactory::set_next_protos(kExpectedNPNString);
[email protected]26ef6582010-06-24 02:30:477406 SessionDependencies session_deps;
7407
7408 HttpRequestInfo request;
7409 request.method = "GET";
7410 request.url = GURL("https://www.google.com/");
7411 request.load_flags = 0;
7412
7413 SSLSocketDataProvider ssl(true, OK);
7414 ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
[email protected]dae22c52010-07-30 02:16:357415 ssl.next_proto = "spdy/2";
[email protected]26ef6582010-06-24 02:30:477416 ssl.was_npn_negotiated = true;
7417 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
7418
[email protected]2bd93022010-07-17 00:58:447419 scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
[email protected]e7f75092010-07-01 22:39:137420 MockWrite spdy_writes[] = { CreateMockWrite(*req) };
[email protected]26ef6582010-06-24 02:30:477421
7422 MockRead spdy_reads[] = {
7423 MockRead(false, 0, 0) // Not async - return 0 immediately.
7424 };
7425
7426 scoped_refptr<DelayedSocketData> spdy_data(
7427 new DelayedSocketData(
7428 0, // don't wait in this case, immediate hangup.
7429 spdy_reads, arraysize(spdy_reads),
7430 spdy_writes, arraysize(spdy_writes)));
7431 session_deps.socket_factory.AddSocketDataProvider(spdy_data);
7432
7433 TestCompletionCallback callback;
7434
7435 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
7436 scoped_ptr<HttpNetworkTransaction> trans(new HttpNetworkTransaction(session));
7437
7438 int rv = trans->Start(&request, &callback, BoundNetLog());
7439 EXPECT_EQ(ERR_IO_PENDING, rv);
7440 EXPECT_EQ(ERR_CONNECTION_CLOSED, callback.WaitForResult());
7441
[email protected]8e6441ca2010-08-19 05:56:387442 HttpStreamFactory::set_next_protos("");
7443 HttpStreamFactory::set_use_alternate_protocols(false);
[email protected]26ef6582010-06-24 02:30:477444}
[email protected]65d34382010-07-01 18:12:267445
[email protected]f45c1ee2010-08-03 00:54:307446TEST_F(HttpNetworkTransactionTest, SpdyAlternateProtocolThroughProxy) {
7447 // This test ensures that the URL passed into the proxy is upgraded
7448 // to https when doing an Alternate Protocol upgrade.
[email protected]8e6441ca2010-08-19 05:56:387449 HttpStreamFactory::set_use_alternate_protocols(true);
7450 HttpStreamFactory::set_next_protos(
[email protected]f45c1ee2010-08-03 00:54:307451 "\x08http/1.1\x07http1.1\x06spdy/2\x04spdy");
7452
[email protected]81cdfcd2010-10-16 00:49:007453 SessionDependencies session_deps(ProxyService::CreateFixed("myproxy:70"));
[email protected]f45c1ee2010-08-03 00:54:307454 HttpAuthHandlerMock::Factory* auth_factory =
7455 new HttpAuthHandlerMock::Factory();
7456 HttpAuthHandlerMock* auth_handler = new HttpAuthHandlerMock();
7457 auth_factory->set_mock_handler(auth_handler, HttpAuth::AUTH_PROXY);
7458 auth_factory->set_do_init_from_challenge(true);
7459 session_deps.http_auth_handler_factory.reset(auth_factory);
7460
7461 HttpRequestInfo request;
7462 request.method = "GET";
7463 request.url = GURL("http://www.google.com");
7464 request.load_flags = 0;
7465
7466 // First round goes unauthenticated through the proxy.
7467 MockWrite data_writes_1[] = {
7468 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
7469 "Host: www.google.com\r\n"
7470 "Proxy-Connection: keep-alive\r\n"
7471 "\r\n"),
7472 };
7473 MockRead data_reads_1[] = {
[email protected]394816e92010-08-03 07:38:597474 MockRead(false, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
[email protected]f45c1ee2010-08-03 00:54:307475 MockRead("HTTP/1.1 200 OK\r\n"
7476 "Alternate-Protocol: 443:npn-spdy/2\r\n"
7477 "Proxy-Connection: close\r\n"
7478 "\r\n"),
7479 };
7480 StaticSocketDataProvider data_1(data_reads_1, arraysize(data_reads_1),
7481 data_writes_1, arraysize(data_writes_1));
7482
7483 // Second round tries to tunnel to www.google.com due to the
7484 // Alternate-Protocol announcement in the first round. It fails due
7485 // to a proxy authentication challenge.
[email protected]394816e92010-08-03 07:38:597486 // After the failure, a tunnel is established to www.google.com using
7487 // Proxy-Authorization headers. There is then a SPDY request round.
7488 //
7489 // NOTE: Despite the "Proxy-Connection: Close", these are done on the
7490 // same MockTCPClientSocket since the underlying HttpNetworkClientSocket
7491 // does a Disconnect and Connect on the same socket, rather than trying
7492 // to obtain a new one.
7493 //
7494 // NOTE: Originally, the proxy response to the second CONNECT request
7495 // simply returned another 407 so the unit test could skip the SSL connection
7496 // establishment and SPDY framing issues. Alas, the
7497 // retry-http-when-alternate-protocol fails logic kicks in, which was more
[email protected]f45c1ee2010-08-03 00:54:307498 // complicated to set up expectations for than the SPDY session.
[email protected]394816e92010-08-03 07:38:597499
[email protected]f45c1ee2010-08-03 00:54:307500 scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
7501 scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1));
7502 scoped_ptr<spdy::SpdyFrame> data(ConstructSpdyBodyFrame(1, true));
7503
[email protected]394816e92010-08-03 07:38:597504 MockWrite data_writes_2[] = {
7505 // First connection attempt without Proxy-Authorization.
7506 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
7507 "Host: www.google.com\r\n"
7508 "Proxy-Connection: keep-alive\r\n"
7509 "\r\n"),
7510
7511 // Second connection attempt with Proxy-Authorization.
[email protected]f45c1ee2010-08-03 00:54:307512 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
7513 "Host: www.google.com\r\n"
7514 "Proxy-Connection: keep-alive\r\n"
7515 "Proxy-Authorization: auth_token\r\n"
7516 "\r\n"),
[email protected]f45c1ee2010-08-03 00:54:307517
[email protected]394816e92010-08-03 07:38:597518 // SPDY request
7519 CreateMockWrite(*req),
[email protected]f45c1ee2010-08-03 00:54:307520 };
[email protected]394816e92010-08-03 07:38:597521 const char kRejectConnectResponse[] = ("HTTP/1.1 407 Unauthorized\r\n"
7522 "Proxy-Authenticate: Mock\r\n"
7523 "Proxy-Connection: close\r\n"
7524 "\r\n");
7525 const char kAcceptConnectResponse[] = "HTTP/1.1 200 Connected\r\n\r\n";
7526 MockRead data_reads_2[] = {
7527 // First connection attempt fails
7528 MockRead(false, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ, 1),
7529 MockRead(true, kRejectConnectResponse,
7530 arraysize(kRejectConnectResponse) - 1, 1),
7531
7532 // Second connection attempt passes
7533 MockRead(true, kAcceptConnectResponse,
7534 arraysize(kAcceptConnectResponse) -1, 4),
7535
7536 // SPDY response
7537 CreateMockRead(*resp.get(), 6),
7538 CreateMockRead(*data.get(), 6),
7539 MockRead(true, 0, 0, 6),
7540 };
7541 scoped_refptr<OrderedSocketData> data_2(
7542 new OrderedSocketData(data_reads_2, arraysize(data_reads_2),
7543 data_writes_2, arraysize(data_writes_2)));
[email protected]f45c1ee2010-08-03 00:54:307544
7545 SSLSocketDataProvider ssl(true, OK);
7546 ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
7547 ssl.next_proto = "spdy/2";
7548 ssl.was_npn_negotiated = true;
7549
7550 session_deps.socket_factory.AddSocketDataProvider(&data_1);
[email protected]394816e92010-08-03 07:38:597551 session_deps.socket_factory.AddSocketDataProvider(data_2.get());
[email protected]f45c1ee2010-08-03 00:54:307552 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
7553 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
7554
7555 // First round should work and provide the Alternate-Protocol state.
7556 TestCompletionCallback callback_1;
7557 scoped_ptr<HttpTransaction> trans_1(new HttpNetworkTransaction(session));
7558 int rv = trans_1->Start(&request, &callback_1, BoundNetLog());
7559 EXPECT_EQ(ERR_IO_PENDING, rv);
7560 EXPECT_EQ(OK, callback_1.WaitForResult());
7561
7562 // Second round should attempt a tunnel connect and get an auth challenge.
7563 TestCompletionCallback callback_2;
7564 scoped_ptr<HttpTransaction> trans_2(new HttpNetworkTransaction(session));
7565 rv = trans_2->Start(&request, &callback_2, BoundNetLog());
7566 EXPECT_EQ(ERR_IO_PENDING, rv);
7567 EXPECT_EQ(OK, callback_2.WaitForResult());
7568 const HttpResponseInfo* response = trans_2->GetResponseInfo();
7569 ASSERT_FALSE(response == NULL);
7570 ASSERT_FALSE(response->auth_challenge.get() == NULL);
7571
7572 // Restart with auth. Tunnel should work and response received.
7573 TestCompletionCallback callback_3;
7574 rv = trans_2->RestartWithAuth(kFoo, kBar, &callback_3);
7575 EXPECT_EQ(ERR_IO_PENDING, rv);
7576 EXPECT_EQ(OK, callback_3.WaitForResult());
7577
7578 // After all that work, these two lines (or actually, just the scheme) are
7579 // what this test is all about. Make sure it happens correctly.
7580 const GURL& request_url = auth_handler->request_url();
7581 EXPECT_EQ("https", request_url.scheme());
7582 EXPECT_EQ("www.google.com", request_url.host());
7583
[email protected]8e6441ca2010-08-19 05:56:387584 HttpStreamFactory::set_next_protos("");
7585 HttpStreamFactory::set_use_alternate_protocols(false);
7586}
7587
7588// Test that if we cancel the transaction as the connection is completing, that
7589// everything tears down correctly.
7590TEST_F(HttpNetworkTransactionTest, SimpleCancel) {
7591 // Setup everything about the connection to complete synchronously, so that
7592 // after calling HttpNetworkTransaction::Start, the only thing we're waiting
7593 // for is the callback from the HttpStreamRequest.
7594 // Then cancel the transaction.
7595 // Verify that we don't crash.
7596 MockConnect mock_connect(false, OK);
7597 MockRead data_reads[] = {
7598 MockRead(false, "HTTP/1.0 200 OK\r\n\r\n"),
7599 MockRead(false, "hello world"),
7600 MockRead(false, OK),
7601 };
7602
7603 SessionDependencies session_deps;
7604 session_deps.host_resolver->set_synchronous_mode(true);
7605 scoped_ptr<HttpTransaction> trans(
7606 new HttpNetworkTransaction(CreateSession(&session_deps)));
7607
7608 HttpRequestInfo request;
7609 request.method = "GET";
7610 request.url = GURL("http://www.google.com/");
7611 request.load_flags = 0;
7612
7613 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
7614 data.set_connect_data(mock_connect);
7615 session_deps.socket_factory.AddSocketDataProvider(&data);
7616
7617 TestCompletionCallback callback;
7618
7619 CapturingBoundNetLog log(CapturingNetLog::kUnbounded);
7620 int rv = trans->Start(&request, &callback, log.bound());
7621 EXPECT_EQ(ERR_IO_PENDING, rv);
7622 trans.reset(); // Cancel the transaction here.
7623
7624 MessageLoop::current()->RunAllPending();
[email protected]f45c1ee2010-08-03 00:54:307625}
7626
[email protected]76a505b2010-08-25 06:23:007627// Test a basic GET request through a proxy.
7628TEST_F(HttpNetworkTransactionTest, ProxyGet) {
[email protected]81cdfcd2010-10-16 00:49:007629 SessionDependencies session_deps(ProxyService::CreateFixed("myproxy:70"));
[email protected]76a505b2010-08-25 06:23:007630 CapturingBoundNetLog log(CapturingNetLog::kUnbounded);
7631 session_deps.net_log = log.bound().net_log();
7632 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
7633
[email protected]76a505b2010-08-25 06:23:007634 HttpRequestInfo request;
7635 request.method = "GET";
7636 request.url = GURL("http://www.google.com/");
7637
7638 MockWrite data_writes1[] = {
7639 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
7640 "Host: www.google.com\r\n"
7641 "Proxy-Connection: keep-alive\r\n\r\n"),
7642 };
7643
7644 MockRead data_reads1[] = {
7645 MockRead("HTTP/1.1 200 OK\r\n"),
7646 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
7647 MockRead("Content-Length: 100\r\n\r\n"),
7648 MockRead(false, OK),
7649 };
7650
7651 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
7652 data_writes1, arraysize(data_writes1));
7653 session_deps.socket_factory.AddSocketDataProvider(&data1);
7654
7655 TestCompletionCallback callback1;
7656
[email protected]0b0bf032010-09-21 18:08:507657 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
7658
[email protected]76a505b2010-08-25 06:23:007659 int rv = trans->Start(&request, &callback1, log.bound());
7660 EXPECT_EQ(ERR_IO_PENDING, rv);
7661
7662 rv = callback1.WaitForResult();
7663 EXPECT_EQ(OK, rv);
7664
7665 const HttpResponseInfo* response = trans->GetResponseInfo();
7666 ASSERT_FALSE(response == NULL);
7667
7668 EXPECT_TRUE(response->headers->IsKeepAlive());
7669 EXPECT_EQ(200, response->headers->response_code());
7670 EXPECT_EQ(100, response->headers->GetContentLength());
7671 EXPECT_TRUE(response->was_fetched_via_proxy);
7672 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
7673}
7674
7675// Test a basic HTTPS GET request through a proxy.
7676TEST_F(HttpNetworkTransactionTest, ProxyTunnelGet) {
[email protected]81cdfcd2010-10-16 00:49:007677 SessionDependencies session_deps(ProxyService::CreateFixed("myproxy:70"));
[email protected]76a505b2010-08-25 06:23:007678 CapturingBoundNetLog log(CapturingNetLog::kUnbounded);
7679 session_deps.net_log = log.bound().net_log();
7680 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
7681
[email protected]76a505b2010-08-25 06:23:007682 HttpRequestInfo request;
7683 request.method = "GET";
7684 request.url = GURL("https://www.google.com/");
7685
7686 // Since we have proxy, should try to establish tunnel.
7687 MockWrite data_writes1[] = {
7688 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
7689 "Host: www.google.com\r\n"
7690 "Proxy-Connection: keep-alive\r\n\r\n"),
7691
7692 MockWrite("GET / HTTP/1.1\r\n"
7693 "Host: www.google.com\r\n"
7694 "Connection: keep-alive\r\n\r\n"),
7695 };
7696
7697 MockRead data_reads1[] = {
7698 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
7699
7700 MockRead("HTTP/1.1 200 OK\r\n"),
7701 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
7702 MockRead("Content-Length: 100\r\n\r\n"),
7703 MockRead(false, OK),
7704 };
7705
7706 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
7707 data_writes1, arraysize(data_writes1));
7708 session_deps.socket_factory.AddSocketDataProvider(&data1);
7709 SSLSocketDataProvider ssl(true, OK);
7710 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
7711
7712 TestCompletionCallback callback1;
7713
[email protected]0b0bf032010-09-21 18:08:507714 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
7715
[email protected]76a505b2010-08-25 06:23:007716 int rv = trans->Start(&request, &callback1, log.bound());
7717 EXPECT_EQ(ERR_IO_PENDING, rv);
7718
7719 rv = callback1.WaitForResult();
7720 EXPECT_EQ(OK, rv);
7721 size_t pos = ExpectLogContainsSomewhere(
7722 log.entries(), 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
7723 NetLog::PHASE_NONE);
7724 ExpectLogContainsSomewhere(
7725 log.entries(), pos,
7726 NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
7727 NetLog::PHASE_NONE);
7728
7729 const HttpResponseInfo* response = trans->GetResponseInfo();
7730 ASSERT_FALSE(response == NULL);
7731
7732 EXPECT_TRUE(response->headers->IsKeepAlive());
7733 EXPECT_EQ(200, response->headers->response_code());
7734 EXPECT_EQ(100, response->headers->GetContentLength());
7735 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
7736 EXPECT_TRUE(response->was_fetched_via_proxy);
7737}
7738
7739// Test a basic HTTPS GET request through a proxy, but the server hangs up
7740// while establishing the tunnel.
7741TEST_F(HttpNetworkTransactionTest, ProxyTunnelGetHangup) {
[email protected]81cdfcd2010-10-16 00:49:007742 SessionDependencies session_deps(ProxyService::CreateFixed("myproxy:70"));
[email protected]76a505b2010-08-25 06:23:007743 CapturingBoundNetLog log(CapturingNetLog::kUnbounded);
7744 session_deps.net_log = log.bound().net_log();
7745 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
7746
[email protected]76a505b2010-08-25 06:23:007747 HttpRequestInfo request;
7748 request.method = "GET";
7749 request.url = GURL("https://www.google.com/");
7750
7751 // Since we have proxy, should try to establish tunnel.
7752 MockWrite data_writes1[] = {
7753 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
7754 "Host: www.google.com\r\n"
7755 "Proxy-Connection: keep-alive\r\n\r\n"),
7756
7757 MockWrite("GET / HTTP/1.1\r\n"
7758 "Host: www.google.com\r\n"
7759 "Connection: keep-alive\r\n\r\n"),
7760 };
7761
7762 MockRead data_reads1[] = {
7763 MockRead(false, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
7764 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
7765 MockRead(true, 0, 0), // EOF
7766 };
7767
7768 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
7769 data_writes1, arraysize(data_writes1));
7770 session_deps.socket_factory.AddSocketDataProvider(&data1);
7771 SSLSocketDataProvider ssl(true, OK);
7772 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
7773
7774 TestCompletionCallback callback1;
7775
[email protected]0b0bf032010-09-21 18:08:507776 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
7777
[email protected]76a505b2010-08-25 06:23:007778 int rv = trans->Start(&request, &callback1, log.bound());
7779 EXPECT_EQ(ERR_IO_PENDING, rv);
7780
7781 rv = callback1.WaitForResult();
7782 EXPECT_EQ(ERR_EMPTY_RESPONSE, rv);
7783 size_t pos = ExpectLogContainsSomewhere(
7784 log.entries(), 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
7785 NetLog::PHASE_NONE);
7786 ExpectLogContainsSomewhere(
7787 log.entries(), pos,
7788 NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
7789 NetLog::PHASE_NONE);
7790}
7791
[email protected]749eefa82010-09-13 22:14:037792// Test for crbug.com/55424.
7793TEST_F(HttpNetworkTransactionTest, PreconnectWithExistingSpdySession) {
7794 SessionDependencies session_deps;
7795
7796 scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(
7797 "https://www.google.com", false, 1, LOWEST));
7798 MockWrite spdy_writes[] = { CreateMockWrite(*req) };
7799
7800 scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1));
7801 scoped_ptr<spdy::SpdyFrame> data(ConstructSpdyBodyFrame(1, true));
7802 MockRead spdy_reads[] = {
7803 CreateMockRead(*resp),
7804 CreateMockRead(*data),
7805 MockRead(true, 0, 0),
7806 };
7807
7808 scoped_refptr<DelayedSocketData> spdy_data(
7809 new DelayedSocketData(
7810 1, // wait for one write to finish before reading.
7811 spdy_reads, arraysize(spdy_reads),
7812 spdy_writes, arraysize(spdy_writes)));
7813 session_deps.socket_factory.AddSocketDataProvider(spdy_data);
7814
7815 SSLSocketDataProvider ssl(true, OK);
7816 ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
7817 ssl.next_proto = "spdy/2";
7818 ssl.was_npn_negotiated = true;
7819 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
7820
7821 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
7822
7823 // Set up an initial SpdySession in the pool to reuse.
[email protected]02b0c342010-09-25 21:09:387824 HostPortPair host_port_pair("www.google.com", 443);
7825 HostPortProxyPair pair(host_port_pair, ProxyServer::Direct());
[email protected]749eefa82010-09-13 22:14:037826 scoped_refptr<SpdySession> spdy_session =
[email protected]f4580332010-09-25 21:20:277827 session->spdy_session_pool()->Get(pair, session->mutable_spdy_settings(),
7828 BoundNetLog());
[email protected]ad8e04a2010-11-01 04:16:277829 scoped_refptr<TCPSocketParams> tcp_params(
7830 new TCPSocketParams("www.google.com", 443, MEDIUM, GURL(), false));
[email protected]02b0c342010-09-25 21:09:387831 TestCompletionCallback callback;
7832
7833 scoped_ptr<ClientSocketHandle> connection(new ClientSocketHandle);
7834 EXPECT_EQ(ERR_IO_PENDING,
7835 connection->Init(host_port_pair.ToString(), tcp_params, LOWEST,
7836 &callback, session->tcp_socket_pool(),
7837 BoundNetLog()));
7838 EXPECT_EQ(OK, callback.WaitForResult());
7839 spdy_session->InitializeWithSocket(connection.release(), false, OK);
[email protected]749eefa82010-09-13 22:14:037840
7841 HttpRequestInfo request;
7842 request.method = "GET";
7843 request.url = GURL("https://www.google.com/");
7844 request.load_flags = 0;
7845
7846 // This is the important line that marks this as a preconnect.
7847 request.motivation = HttpRequestInfo::PRECONNECT_MOTIVATED;
7848
7849 scoped_ptr<HttpNetworkTransaction> trans(new HttpNetworkTransaction(session));
7850
[email protected]749eefa82010-09-13 22:14:037851 int rv = trans->Start(&request, &callback, BoundNetLog());
7852 EXPECT_EQ(ERR_IO_PENDING, rv);
7853 EXPECT_EQ(OK, callback.WaitForResult());
7854}
7855
[email protected]73b8dd222010-11-11 19:55:247856// Given a net error, cause that error to be returned from the first Write()
7857// call and verify that the HttpTransaction fails with that error.
7858static void CheckErrorIsPassedBack(int error, bool async) {
7859 SessionDependencies session_deps;
7860
7861 SSLSocketDataProvider ssl_data(async, OK);
7862 net::MockWrite data_writes[] = {
7863 net::MockWrite(async, error),
7864 };
7865 net::StaticSocketDataProvider data(NULL, 0,
7866 data_writes, arraysize(data_writes));
7867 session_deps.socket_factory.AddSocketDataProvider(&data);
7868 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl_data);
7869
7870 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
7871 scoped_ptr<HttpNetworkTransaction> trans(new HttpNetworkTransaction(session));
7872
7873 net::HttpRequestInfo request_info;
7874 request_info.url = GURL("https://www.example.com/");
7875 request_info.method = "GET";
7876 request_info.load_flags = net::LOAD_NORMAL;
7877
7878 TestCompletionCallback callback;
7879 int rv = trans->Start(&request_info, &callback, net::BoundNetLog());
7880 if (rv == net::ERR_IO_PENDING)
7881 rv = callback.WaitForResult();
7882 ASSERT_EQ(error, rv);
7883}
7884
7885TEST_F(HttpNetworkTransactionTest, SSLWriteCertError) {
7886 // Just check a grab bag of cert errors.
7887 static const int kErrors[] = {
7888 ERR_CERT_COMMON_NAME_INVALID,
7889 ERR_CERT_AUTHORITY_INVALID,
7890 ERR_CERT_DATE_INVALID,
7891 };
7892 for (size_t i = 0; i < arraysize(kErrors); i++) {
7893 CheckErrorIsPassedBack(kErrors[i], false /* not async */);
7894 CheckErrorIsPassedBack(kErrors[i], true /* async */);
7895 }
7896}
7897
7898// Test that the transaction is restarted in the event of an NPN misprediction.
7899TEST_F(HttpNetworkTransactionTest, NPNMispredict) {
7900 SessionDependencies session_deps;
7901
7902 SSLSocketDataProvider ssl_data1(true /* async */, OK);
7903 SSLSocketDataProvider ssl_data2(true /* async */, OK);
7904
7905 net::MockWrite data1_writes[] = {
7906 net::MockWrite(true /* async */, ERR_SSL_SNAP_START_NPN_MISPREDICTION),
7907 };
7908 net::MockRead data2_reads[] = {
7909 net::MockRead("HTTP/1.0 200 OK\r\n\r\n"),
7910 net::MockRead("hello world"),
7911 net::MockRead(false, net::OK),
7912 };
7913 net::MockWrite data2_writes[] = {
7914 net::MockWrite("GET / HTTP/1.1\r\n"
7915 "Host: www.example.com\r\n"
7916 "Connection: keep-alive\r\n\r\n"),
7917 };
7918 net::StaticSocketDataProvider data1(
7919 NULL, 0, data1_writes, arraysize(data1_writes));
7920 net::StaticSocketDataProvider data2(data2_reads, arraysize(data2_reads),
7921 data2_writes, arraysize(data2_writes));
7922
7923 session_deps.socket_factory.AddSocketDataProvider(&data1);
7924 session_deps.socket_factory.AddSocketDataProvider(&data2);
7925 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl_data1);
7926 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl_data2);
7927
7928 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
7929 scoped_ptr<HttpNetworkTransaction> trans(new HttpNetworkTransaction(session));
7930
7931 net::HttpRequestInfo request_info;
7932 request_info.url = GURL("https://www.example.com/");
7933 request_info.method = "GET";
7934 request_info.load_flags = net::LOAD_NORMAL;
7935
7936 TestCompletionCallback callback;
7937 int rv = trans->Start(&request_info, &callback, net::BoundNetLog());
7938 if (rv == net::ERR_IO_PENDING)
7939 rv = callback.WaitForResult();
7940 ASSERT_EQ(OK, rv);
7941
7942 std::string contents;
7943 rv = ReadTransaction(trans.get(), &contents);
7944 EXPECT_EQ(net::OK, rv);
7945 EXPECT_EQ("hello world", contents);
7946}
7947
[email protected]89ceba9a2009-03-21 03:46:067948} // namespace net