1 // Copyright 2013 The Chromium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "net/http/http_network_transaction.h"
6
7 #include <math.h> // ceil
8 #include <stdarg.h>
9 #include <stdint.h>
10
11 #include <limits>
12 #include <memory>
13 #include <optional>
14 #include <set>
15 #include <string>
16 #include <string_view>
17 #include <utility>
18 #include <vector>
19
20 #include "base/compiler_specific.h"
21 #include "base/files/file_path.h"
22 #include "base/files/file_util.h"
23 #include "base/functional/bind.h"
24 #include "base/json/json_writer.h"
25 #include "base/logging.h"
26 #include "base/memory/ptr_util.h"
27 #include "base/memory/raw_ptr.h"
28 #include "base/memory/weak_ptr.h"
29 #include "base/run_loop.h"
30 #include "base/strings/string_util.h"
31 #include "base/strings/stringprintf.h"
32 #include "base/strings/utf_string_conversions.h"
33 #include "base/task/single_thread_task_runner.h"
34 #include "base/test/metrics/histogram_tester.h"
35 #include "base/test/scoped_feature_list.h"
36 #include "base/test/simple_test_clock.h"
37 #include "base/test/simple_test_tick_clock.h"
38 #include "base/test/task_environment.h"
39 #include "base/test/test_file_util.h"
40 #include "base/time/time.h"
41 #include "build/build_config.h"
42 #include "net/base/auth.h"
43 #include "net/base/chunked_upload_data_stream.h"
44 #include "net/base/completion_once_callback.h"
45 #include "net/base/elements_upload_data_stream.h"
46 #include "net/base/features.h"
47 #include "net/base/host_port_pair.h"
48 #include "net/base/ip_address.h"
49 #include "net/base/ip_endpoint.h"
50 #include "net/base/load_timing_info.h"
51 #include "net/base/load_timing_info_test_util.h"
52 #include "net/base/net_errors.h"
53 #include "net/base/network_anonymization_key.h"
54 #include "net/base/network_isolation_key.h"
55 #include "net/base/privacy_mode.h"
56 #include "net/base/proxy_chain.h"
57 #include "net/base/proxy_delegate.h"
58 #include "net/base/proxy_server.h"
59 #include "net/base/proxy_string_util.h"
60 #include "net/base/request_priority.h"
61 #include "net/base/schemeful_site.h"
62 #include "net/base/session_usage.h"
63 #include "net/base/test_completion_callback.h"
64 #include "net/base/test_proxy_delegate.h"
65 #include "net/base/upload_bytes_element_reader.h"
66 #include "net/base/upload_file_element_reader.h"
67 #include "net/cert/cert_status_flags.h"
68 #include "net/cert/mock_cert_verifier.h"
69 #include "net/dns/mock_host_resolver.h"
70 #include "net/dns/public/secure_dns_policy.h"
71 #include "net/http/http_auth_challenge_tokenizer.h"
72 #include "net/http/http_auth_handler_digest.h"
73 #include "net/http/http_auth_handler_mock.h"
74 #include "net/http/http_auth_handler_ntlm.h"
75 #include "net/http/http_auth_ntlm_mechanism.h"
76 #include "net/http/http_auth_scheme.h"
77 #include "net/http/http_basic_stream.h"
78 #include "net/http/http_network_session.h"
79 #include "net/http/http_network_session_peer.h"
80 #include "net/http/http_proxy_connect_job.h"
81 #include "net/http/http_request_headers.h"
82 #include "net/http/http_response_info.h"
83 #include "net/http/http_server_properties.h"
84 #include "net/http/http_stream.h"
85 #include "net/http/http_stream_factory.h"
86 #include "net/http/http_transaction_test_util.h"
87 #include "net/log/net_log.h"
88 #include "net/log/net_log_event_type.h"
89 #include "net/log/net_log_source.h"
90 #include "net/log/test_net_log.h"
91 #include "net/log/test_net_log_util.h"
92 #include "net/proxy_resolution/configured_proxy_resolution_service.h"
93 #include "net/proxy_resolution/mock_proxy_resolver.h"
94 #include "net/proxy_resolution/proxy_config_service_fixed.h"
95 #include "net/proxy_resolution/proxy_info.h"
96 #include "net/proxy_resolution/proxy_resolver.h"
97 #include "net/proxy_resolution/proxy_resolver_factory.h"
98 #include "net/socket/client_socket_factory.h"
99 #include "net/socket/client_socket_pool.h"
100 #include "net/socket/client_socket_pool_manager.h"
101 #include "net/socket/connect_job.h"
102 #include "net/socket/connection_attempts.h"
103 #include "net/socket/mock_client_socket_pool_manager.h"
104 #include "net/socket/next_proto.h"
105 #include "net/socket/socket_tag.h"
106 #include "net/socket/socket_test_util.h"
107 #include "net/socket/socks_connect_job.h"
108 #include "net/socket/ssl_client_socket.h"
109 #include "net/spdy/spdy_session.h"
110 #include "net/spdy/spdy_session_pool.h"
111 #include "net/spdy/spdy_test_util_common.h"
112 #include "net/ssl/client_cert_identity_test_util.h"
113 #include "net/ssl/ssl_cert_request_info.h"
114 #include "net/ssl/ssl_config.h"
115 #include "net/ssl/ssl_config_service.h"
116 #include "net/ssl/ssl_info.h"
117 #include "net/ssl/ssl_private_key.h"
118 #include "net/ssl/test_ssl_config_service.h"
119 #include "net/test/cert_test_util.h"
120 #include "net/test/gtest_util.h"
121 #include "net/test/test_data_directory.h"
122 #include "net/test/test_with_task_environment.h"
123 #include "net/third_party/quiche/src/quiche/spdy/core/spdy_framer.h"
124 #include "net/traffic_annotation/network_traffic_annotation_test_helper.h"
125 #include "net/url_request/static_http_user_agent_settings.h"
126 #include "net/websockets/websocket_handshake_stream_base.h"
127 #include "net/websockets/websocket_test_util.h"
128 #include "testing/gmock/include/gmock/gmock.h"
129 #include "testing/gtest/include/gtest/gtest.h"
130 #include "testing/platform_test.h"
131 #include "url/gurl.h"
132 #include "url/scheme_host_port.h"
133 #include "url/url_constants.h"
134
135 #if defined(NTLM_PORTABLE)
136 #include "base/base64.h"
137 #include "net/ntlm/ntlm_test_data.h"
138 #endif
139
140 #if BUILDFLAG(ENABLE_REPORTING)
141 #include "net/network_error_logging/network_error_logging_service.h"
142 #include "net/network_error_logging/network_error_logging_test_util.h"
143 #include "net/reporting/reporting_cache.h"
144 #include "net/reporting/reporting_endpoint.h"
145 #include "net/reporting/reporting_header_parser.h"
146 #include "net/reporting/reporting_service.h"
147 #include "net/reporting/reporting_test_util.h"
148 #endif // BUILDFLAG(ENABLE_REPORTING)
149
150 using net::test::IsError;
151 using net::test::IsOk;
152
153 using base::ASCIIToUTF16;
154
155 using testing::AnyOf;
156 using testing::ElementsAre;
157 using testing::IsEmpty;
158
159 //-----------------------------------------------------------------------------
160
161 namespace net {
162
163 namespace {
164
165 const std::u16string kBar(u"bar");
166 const std::u16string kBar2(u"bar2");
167 const std::u16string kBar3(u"bar3");
168 const std::u16string kBaz(u"baz");
169 const std::u16string kFirst(u"first");
170 const std::u16string kFoo(u"foo");
171 const std::u16string kFoo2(u"foo2");
172 const std::u16string kFoo3(u"foo3");
173 const std::u16string kFou(u"fou");
174 const std::u16string kSecond(u"second");
175 const std::u16string kWrongPassword(u"wrongpassword");
176
177 const char kAlternativeServiceHttpHeader[] =
178 "Alt-Svc: h2=\"mail.example.org:443\"\r\n";
179
GetIdleSocketCountInTransportSocketPool(HttpNetworkSession * session)180 int GetIdleSocketCountInTransportSocketPool(HttpNetworkSession* session) {
181 return session
182 ->GetSocketPool(HttpNetworkSession::NORMAL_SOCKET_POOL,
183 ProxyChain::Direct())
184 ->IdleSocketCount();
185 }
186
IsTransportSocketPoolStalled(HttpNetworkSession * session)187 bool IsTransportSocketPoolStalled(HttpNetworkSession* session) {
188 return session
189 ->GetSocketPool(HttpNetworkSession::NORMAL_SOCKET_POOL,
190 ProxyChain::Direct())
191 ->IsStalled();
192 }
193
194 // Takes in a Value created from a NetLogHttpResponseParameter, and returns
195 // a JSONified list of headers as a single string. Uses single quotes instead
196 // of double quotes for easier comparison.
GetHeaders(const base::Value::Dict & params)197 std::string GetHeaders(const base::Value::Dict& params) {
198 const base::Value::List* header_list = params.FindList("headers");
199 if (!header_list) {
200 return "";
201 }
202 std::string headers;
203 base::JSONWriter::Write(*header_list, &headers);
204 base::ReplaceChars(headers, "\"", "'", &headers);
205 return headers;
206 }
207
208 // Tests LoadTimingInfo in the case a socket is reused and no PAC script is
209 // used.
TestLoadTimingReused(const LoadTimingInfo & load_timing_info)210 void TestLoadTimingReused(const LoadTimingInfo& load_timing_info) {
211 EXPECT_TRUE(load_timing_info.socket_reused);
212 EXPECT_NE(NetLogSource::kInvalidId, load_timing_info.socket_log_id);
213
214 EXPECT_TRUE(load_timing_info.proxy_resolve_start.is_null());
215 EXPECT_TRUE(load_timing_info.proxy_resolve_end.is_null());
216
217 ExpectConnectTimingHasNoTimes(load_timing_info.connect_timing);
218 EXPECT_FALSE(load_timing_info.send_start.is_null());
219
220 EXPECT_LE(load_timing_info.send_start, load_timing_info.send_end);
221
222 // Set at a higher level.
223 EXPECT_TRUE(load_timing_info.request_start_time.is_null());
224 EXPECT_TRUE(load_timing_info.request_start.is_null());
225 EXPECT_TRUE(load_timing_info.receive_headers_end.is_null());
226 }
227
228 // Tests LoadTimingInfo in the case a new socket is used and no PAC script is
229 // used.
TestLoadTimingNotReused(const LoadTimingInfo & load_timing_info,int connect_timing_flags)230 void TestLoadTimingNotReused(const LoadTimingInfo& load_timing_info,
231 int connect_timing_flags) {
232 EXPECT_FALSE(load_timing_info.socket_reused);
233 EXPECT_NE(NetLogSource::kInvalidId, load_timing_info.socket_log_id);
234
235 EXPECT_TRUE(load_timing_info.proxy_resolve_start.is_null());
236 EXPECT_TRUE(load_timing_info.proxy_resolve_end.is_null());
237
238 ExpectConnectTimingHasTimes(load_timing_info.connect_timing,
239 connect_timing_flags);
240 EXPECT_LE(load_timing_info.connect_timing.connect_end,
241 load_timing_info.send_start);
242
243 EXPECT_LE(load_timing_info.send_start, load_timing_info.send_end);
244
245 // Set at a higher level.
246 EXPECT_TRUE(load_timing_info.request_start_time.is_null());
247 EXPECT_TRUE(load_timing_info.request_start.is_null());
248 EXPECT_TRUE(load_timing_info.receive_headers_end.is_null());
249 }
250
251 // Tests LoadTimingInfo in the case a socket is reused and a PAC script is
252 // used.
TestLoadTimingReusedWithPac(const LoadTimingInfo & load_timing_info)253 void TestLoadTimingReusedWithPac(const LoadTimingInfo& load_timing_info) {
254 EXPECT_TRUE(load_timing_info.socket_reused);
255 EXPECT_NE(NetLogSource::kInvalidId, load_timing_info.socket_log_id);
256
257 ExpectConnectTimingHasNoTimes(load_timing_info.connect_timing);
258
259 EXPECT_FALSE(load_timing_info.proxy_resolve_start.is_null());
260 EXPECT_LE(load_timing_info.proxy_resolve_start,
261 load_timing_info.proxy_resolve_end);
262 EXPECT_LE(load_timing_info.proxy_resolve_end, load_timing_info.send_start);
263 EXPECT_LE(load_timing_info.send_start, load_timing_info.send_end);
264
265 // Set at a higher level.
266 EXPECT_TRUE(load_timing_info.request_start_time.is_null());
267 EXPECT_TRUE(load_timing_info.request_start.is_null());
268 EXPECT_TRUE(load_timing_info.receive_headers_end.is_null());
269 }
270
271 // Tests LoadTimingInfo in the case a new socket is used and a PAC script is
272 // used.
TestLoadTimingNotReusedWithPac(const LoadTimingInfo & load_timing_info,int connect_timing_flags)273 void TestLoadTimingNotReusedWithPac(const LoadTimingInfo& load_timing_info,
274 int connect_timing_flags) {
275 EXPECT_FALSE(load_timing_info.socket_reused);
276 EXPECT_NE(NetLogSource::kInvalidId, load_timing_info.socket_log_id);
277
278 EXPECT_FALSE(load_timing_info.proxy_resolve_start.is_null());
279 EXPECT_LE(load_timing_info.proxy_resolve_start,
280 load_timing_info.proxy_resolve_end);
281 EXPECT_LE(load_timing_info.proxy_resolve_end,
282 load_timing_info.connect_timing.connect_start);
283 ExpectConnectTimingHasTimes(load_timing_info.connect_timing,
284 connect_timing_flags);
285 EXPECT_LE(load_timing_info.connect_timing.connect_end,
286 load_timing_info.send_start);
287
288 EXPECT_LE(load_timing_info.send_start, load_timing_info.send_end);
289
290 // Set at a higher level.
291 EXPECT_TRUE(load_timing_info.request_start_time.is_null());
292 EXPECT_TRUE(load_timing_info.request_start.is_null());
293 EXPECT_TRUE(load_timing_info.receive_headers_end.is_null());
294 }
295
296 // ProxyResolver that records URLs passed to it, and that can be told what
297 // result to return.
298 class CapturingProxyResolver : public ProxyResolver {
299 public:
300 struct LookupInfo {
301 GURL url;
302 NetworkAnonymizationKey network_anonymization_key;
303 };
304
CapturingProxyResolver()305 CapturingProxyResolver()
306 : proxy_chain_(ProxyServer::SCHEME_HTTP, HostPortPair("myproxy", 80)) {}
307
308 CapturingProxyResolver(const CapturingProxyResolver&) = delete;
309 CapturingProxyResolver& operator=(const CapturingProxyResolver&) = delete;
310
311 ~CapturingProxyResolver() override = default;
312
GetProxyForURL(const GURL & url,const NetworkAnonymizationKey & network_anonymization_key,ProxyInfo * results,CompletionOnceCallback callback,std::unique_ptr<Request> * request,const NetLogWithSource & net_log)313 int GetProxyForURL(const GURL& url,
314 const NetworkAnonymizationKey& network_anonymization_key,
315 ProxyInfo* results,
316 CompletionOnceCallback callback,
317 std::unique_ptr<Request>* request,
318 const NetLogWithSource& net_log) override {
319 results->UseProxyChain(proxy_chain_);
320 lookup_info_.push_back(LookupInfo{url, network_anonymization_key});
321 return OK;
322 }
323
324 // Sets whether the resolver should use direct connections, instead of a
325 // proxy.
set_proxy_chain(const ProxyChain & proxy_chain)326 void set_proxy_chain(const ProxyChain& proxy_chain) {
327 proxy_chain_ = proxy_chain;
328 }
329
lookup_info() const330 const std::vector<LookupInfo>& lookup_info() const { return lookup_info_; }
331
332 private:
333 std::vector<LookupInfo> lookup_info_;
334
335 ProxyChain proxy_chain_;
336 };
337
338 class CapturingProxyResolverFactory : public ProxyResolverFactory {
339 public:
CapturingProxyResolverFactory(CapturingProxyResolver * resolver)340 explicit CapturingProxyResolverFactory(CapturingProxyResolver* resolver)
341 : ProxyResolverFactory(false), resolver_(resolver) {}
342
CreateProxyResolver(const scoped_refptr<PacFileData> & pac_script,std::unique_ptr<ProxyResolver> * resolver,CompletionOnceCallback callback,std::unique_ptr<Request> * request)343 int CreateProxyResolver(const scoped_refptr<PacFileData>& pac_script,
344 std::unique_ptr<ProxyResolver>* resolver,
345 CompletionOnceCallback callback,
346 std::unique_ptr<Request>* request) override {
347 *resolver = std::make_unique<ForwardingProxyResolver>(resolver_);
348 return OK;
349 }
350
351 private:
352 raw_ptr<ProxyResolver> resolver_ = nullptr;
353 };
354
CreateSession(SpdySessionDependencies * session_deps)355 std::unique_ptr<HttpNetworkSession> CreateSession(
356 SpdySessionDependencies* session_deps) {
357 return SpdySessionDependencies::SpdyCreateSession(session_deps);
358 }
359
360 class FailingProxyResolverFactory : public ProxyResolverFactory {
361 public:
FailingProxyResolverFactory()362 FailingProxyResolverFactory() : ProxyResolverFactory(false) {}
363
364 // ProxyResolverFactory override.
CreateProxyResolver(const scoped_refptr<PacFileData> & script_data,std::unique_ptr<ProxyResolver> * result,CompletionOnceCallback callback,std::unique_ptr<Request> * request)365 int CreateProxyResolver(const scoped_refptr<PacFileData>& script_data,
366 std::unique_ptr<ProxyResolver>* result,
367 CompletionOnceCallback callback,
368 std::unique_ptr<Request>* request) override {
369 return ERR_PAC_SCRIPT_FAILED;
370 }
371 };
372
373 // A default minimal HttpRequestInfo for use in tests, targeting HTTP.
DefaultRequestInfo()374 HttpRequestInfo DefaultRequestInfo() {
375 HttpRequestInfo info;
376 info.method = "GET";
377 info.url = GURL("http://foo.test");
378 info.traffic_annotation =
379 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
380 return info;
381 }
382
383 // The default info for transports to the embedded HTTP server.
EmbeddedHttpServerTransportInfo()384 TransportInfo EmbeddedHttpServerTransportInfo() {
385 TransportInfo info;
386 info.endpoint = IPEndPoint(IPAddress::IPv4Localhost(), 80);
387 return info;
388 }
389
390 } // namespace
391
392 class HttpNetworkTransactionTestBase : public PlatformTest,
393 public WithTaskEnvironment {
394 public:
~HttpNetworkTransactionTestBase()395 ~HttpNetworkTransactionTestBase() override {
396 // Important to restore the per-pool limit first, since the pool limit must
397 // always be greater than group limit, and the tests reduce both limits.
398 ClientSocketPoolManager::set_max_sockets_per_pool(
399 HttpNetworkSession::NORMAL_SOCKET_POOL, old_max_pool_sockets_);
400 ClientSocketPoolManager::set_max_sockets_per_group(
401 HttpNetworkSession::NORMAL_SOCKET_POOL, old_max_group_sockets_);
402 }
403
404 protected:
HttpNetworkTransactionTestBase()405 HttpNetworkTransactionTestBase()
406 : WithTaskEnvironment(base::test::TaskEnvironment::TimeSource::MOCK_TIME),
407 dummy_connect_job_params_(
408 /*client_socket_factory=*/nullptr,
409 /*host_resolver=*/nullptr,
410 /*http_auth_cache=*/nullptr,
411 /*http_auth_handler_factory=*/nullptr,
412 /*spdy_session_pool=*/nullptr,
413 /*quic_supported_versions=*/nullptr,
414 /*quic_session_pool=*/nullptr,
415 /*proxy_delegate=*/nullptr,
416 /*http_user_agent_settings=*/nullptr,
417 /*ssl_client_context=*/nullptr,
418 /*socket_performance_watcher_factory=*/nullptr,
419 /*network_quality_estimator=*/nullptr,
420 /*net_log=*/nullptr,
421 /*websocket_endpoint_lock_manager=*/nullptr,
422 /*http_server_properties=*/nullptr,
423 /*alpn_protos=*/nullptr,
424 /*application_settings=*/nullptr,
425 /*ignore_certificate_errors=*/nullptr,
426 /*early_data_enabled=*/nullptr),
427 spdy_util_(/*use_priority_header=*/true),
428 ssl_(ASYNC, OK),
429 old_max_group_sockets_(ClientSocketPoolManager::max_sockets_per_group(
430 HttpNetworkSession::NORMAL_SOCKET_POOL)),
431 old_max_pool_sockets_(ClientSocketPoolManager::max_sockets_per_pool(
432 HttpNetworkSession::NORMAL_SOCKET_POOL)) {
433 session_deps_.enable_http2_alternative_service = true;
434 }
435
436 struct SimpleGetHelperResult {
437 int rv;
438 std::string status_line;
439 std::string response_data;
440 int64_t total_received_bytes;
441 int64_t total_sent_bytes;
442 LoadTimingInfo load_timing_info;
443 ConnectionAttempts connection_attempts;
444 IPEndPoint remote_endpoint_after_start;
445 };
446
SetUp()447 void SetUp() override {
448 NetworkChangeNotifier::NotifyObserversOfIPAddressChangeForTests();
449 base::RunLoop().RunUntilIdle();
450 // Set an initial delay to ensure that the first call to TimeTicks::Now()
451 // before incrementing the counter does not return a null value.
452 FastForwardBy(base::Seconds(1));
453 }
454
TearDown()455 void TearDown() override {
456 NetworkChangeNotifier::NotifyObserversOfIPAddressChangeForTests();
457 base::RunLoop().RunUntilIdle();
458 // Empty the current queue.
459 base::RunLoop().RunUntilIdle();
460 PlatformTest::TearDown();
461 NetworkChangeNotifier::NotifyObserversOfIPAddressChangeForTests();
462 base::RunLoop().RunUntilIdle();
463 }
464
465 void Check100ResponseTiming(bool use_spdy);
466
467 // Either |write_failure| specifies a write failure or |read_failure|
468 // specifies a read failure when using a reused socket. In either case, the
469 // failure should cause the network transaction to resend the request, and the
470 // other argument should be NULL.
471 void KeepAliveConnectionResendRequestTest(const MockWrite* write_failure,
472 const MockRead* read_failure);
473
474 // Either |write_failure| specifies a write failure or |read_failure|
475 // specifies a read failure when using a reused socket. In either case, the
476 // failure should cause the network transaction to resend the request, and the
477 // other argument should be NULL.
478 void PreconnectErrorResendRequestTest(const MockWrite* write_failure,
479 const MockRead* read_failure,
480 bool use_spdy,
481 bool upload = false);
482
SimpleGetHelperForData(base::span<StaticSocketDataProvider * > providers)483 SimpleGetHelperResult SimpleGetHelperForData(
484 base::span<StaticSocketDataProvider*> providers) {
485 SimpleGetHelperResult out;
486
487 HttpRequestInfo request;
488 request.method = "GET";
489 request.url = GURL("http://www.example.org/");
490 request.traffic_annotation =
491 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
492
493 RecordingNetLogObserver net_log_observer;
494 NetLogWithSource net_log_with_source =
495 NetLogWithSource::Make(NetLogSourceType::NONE);
496 session_deps_.net_log = NetLog::Get();
497 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
498 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
499
500 for (auto* provider : providers) {
501 session_deps_.socket_factory->AddSocketDataProvider(provider);
502 }
503
504 TestCompletionCallback callback;
505
506 EXPECT_TRUE(net_log_with_source.IsCapturing());
507 int rv = trans.Start(&request, callback.callback(), net_log_with_source);
508 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
509
510 out.rv = callback.WaitForResult();
511 out.total_received_bytes = trans.GetTotalReceivedBytes();
512 out.total_sent_bytes = trans.GetTotalSentBytes();
513
514 // Even in the failure cases that use this function, connections are always
515 // successfully established before the error.
516 EXPECT_TRUE(trans.GetLoadTimingInfo(&out.load_timing_info));
517 TestLoadTimingNotReused(out.load_timing_info, CONNECT_TIMING_HAS_DNS_TIMES);
518
519 if (out.rv != OK) {
520 return out;
521 }
522
523 const HttpResponseInfo* response = trans.GetResponseInfo();
524 // Can't use ASSERT_* inside helper functions like this, so
525 // return an error.
526 if (!response || !response->headers) {
527 out.rv = ERR_UNEXPECTED;
528 return out;
529 }
530 out.status_line = response->headers->GetStatusLine();
531
532 EXPECT_EQ("127.0.0.1", response->remote_endpoint.ToStringWithoutPort());
533 EXPECT_EQ(80, response->remote_endpoint.port());
534
535 bool got_endpoint =
536 trans.GetRemoteEndpoint(&out.remote_endpoint_after_start);
537 EXPECT_EQ(got_endpoint,
538 out.remote_endpoint_after_start.address().size() > 0);
539
540 rv = ReadTransaction(&trans, &out.response_data);
541 EXPECT_THAT(rv, IsOk());
542
543 auto entries = net_log_observer.GetEntries();
544 size_t pos = ExpectLogContainsSomewhere(
545 entries, 0, NetLogEventType::HTTP_TRANSACTION_SEND_REQUEST_HEADERS,
546 NetLogEventPhase::NONE);
547 ExpectLogContainsSomewhere(
548 entries, pos, NetLogEventType::HTTP_TRANSACTION_READ_RESPONSE_HEADERS,
549 NetLogEventPhase::NONE);
550
551 EXPECT_EQ("GET / HTTP/1.1\r\n",
552 GetStringValueFromParams(entries[pos], "line"));
553
554 EXPECT_EQ("['Host: www.example.org','Connection: keep-alive']",
555 GetHeaders(entries[pos].params));
556
557 out.total_received_bytes = trans.GetTotalReceivedBytes();
558 // The total number of sent bytes should not have changed.
559 EXPECT_EQ(out.total_sent_bytes, trans.GetTotalSentBytes());
560
561 out.connection_attempts = trans.GetConnectionAttempts();
562 return out;
563 }
564
SimpleGetHelper(base::span<const MockRead> data_reads)565 SimpleGetHelperResult SimpleGetHelper(base::span<const MockRead> data_reads) {
566 MockWrite data_writes[] = {
567 MockWrite("GET / HTTP/1.1\r\n"
568 "Host: www.example.org\r\n"
569 "Connection: keep-alive\r\n\r\n"),
570 };
571
572 StaticSocketDataProvider reads(data_reads, data_writes);
573 StaticSocketDataProvider* data[] = {&reads};
574 SimpleGetHelperResult out = SimpleGetHelperForData(data);
575
576 EXPECT_EQ(CountWriteBytes(data_writes), out.total_sent_bytes);
577 return out;
578 }
579
AddSSLSocketData()580 void AddSSLSocketData() {
581 ssl_.next_proto = kProtoHTTP2;
582 ssl_.ssl_info.cert =
583 ImportCertFromFile(GetTestCertsDirectory(), "spdy_pooling.pem");
584 ASSERT_TRUE(ssl_.ssl_info.cert);
585 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_);
586 }
587
588 void ConnectStatusHelperWithExpectedStatus(const MockRead& status,
589 int expected_status);
590
591 void ConnectStatusHelper(const MockRead& status);
592
593 void CheckErrorIsPassedBack(int error, IoMode mode);
594
FastForwardByCallback(base::TimeDelta delta)595 base::RepeatingClosure FastForwardByCallback(base::TimeDelta delta) {
596 return base::BindRepeating(&HttpNetworkTransactionTestBase::FastForwardBy,
597 base::Unretained(this), delta);
598 }
599
600 void HttpsNestedProxyNoSocketReuseHelper(const net::ProxyChain& chain1,
601 const net::ProxyChain& chain2);
602
603 const CommonConnectJobParams dummy_connect_job_params_;
604
605 const net::NetworkAnonymizationKey kNetworkAnonymizationKey =
606 NetworkAnonymizationKey::CreateCrossSite(
607 SchemefulSite(GURL("https://foo.test/")));
608
609 const net::NetworkIsolationKey kNetworkIsolationKey =
610 NetworkIsolationKey(SchemefulSite(GURL("https://foo.test/")),
611 SchemefulSite(GURL("https://bar.test/")));
612
613 // These clocks are defined here, even though they're only used in the
614 // Reporting tests below, since they need to be destroyed after
615 // |session_deps_|.
616 base::SimpleTestClock clock_;
617 base::SimpleTestTickClock tick_clock_;
618
619 SpdyTestUtil spdy_util_;
620 SpdySessionDependencies session_deps_;
621 SSLSocketDataProvider ssl_;
622
623 // Original socket limits. Some tests set these. Safest to always restore
624 // them once each test has been run.
625 int old_max_group_sockets_;
626 int old_max_pool_sockets_;
627 };
628
629 class HttpNetworkTransactionTest : public HttpNetworkTransactionTestBase,
630 public ::testing::WithParamInterface<bool> {
631 protected:
HttpNetworkTransactionTest()632 HttpNetworkTransactionTest() {
633 if (PriorityHeaderEnabled()) {
634 feature_list_.InitAndEnableFeature(net::features::kPriorityHeader);
635 } else {
636 feature_list_.InitAndDisableFeature(net::features::kPriorityHeader);
637 }
638 }
639
PriorityHeaderEnabled() const640 bool PriorityHeaderEnabled() const { return GetParam(); }
641
642 private:
643 base::test::ScopedFeatureList feature_list_;
644 };
645
646 INSTANTIATE_TEST_SUITE_P(All,
647 HttpNetworkTransactionTest,
648 testing::Values(true, false));
649
650 namespace {
651
652 // Fill |str| with a long header list that consumes >= |size| bytes.
FillLargeHeadersString(std::string * str,int size)653 void FillLargeHeadersString(std::string* str, int size) {
654 const char kRow[] =
655 "SomeHeaderName: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\r\n";
656 const int sizeof_row = strlen(kRow);
657 const int num_rows =
658 static_cast<int>(ceil(static_cast<float>(size) / sizeof_row));
659 const int sizeof_data = num_rows * sizeof_row;
660 DCHECK(sizeof_data >= size);
661 str->reserve(sizeof_data);
662
663 for (int i = 0; i < num_rows; ++i) {
664 str->append(kRow, sizeof_row);
665 }
666 }
667
668 #if defined(NTLM_PORTABLE)
MockGetMSTime()669 uint64_t MockGetMSTime() {
670 // Tue, 23 May 2017 20:13:07 +0000
671 return 131400439870000000;
672 }
673
674 // Alternative functions that eliminate randomness and dependency on the local
675 // host name so that the generated NTLM messages are reproducible.
MockGenerateRandom(uint8_t * output,size_t n)676 void MockGenerateRandom(uint8_t* output, size_t n) {
677 // This is set to 0xaa because the client challenge for testing in
678 // [MS-NLMP] Section 4.2.1 is 8 bytes of 0xaa.
679 memset(output, 0xaa, n);
680 }
681
MockGetHostName()682 std::string MockGetHostName() {
683 return ntlm::test::kHostnameAscii;
684 }
685 #endif // defined(NTLM_PORTABLE)
686
687 class CaptureGroupIdTransportSocketPool : public TransportClientSocketPool {
688 public:
CaptureGroupIdTransportSocketPool(const CommonConnectJobParams * common_connect_job_params)689 explicit CaptureGroupIdTransportSocketPool(
690 const CommonConnectJobParams* common_connect_job_params)
691 : TransportClientSocketPool(/*max_sockets=*/0,
692 /*max_sockets_per_group=*/0,
693 base::TimeDelta(),
694 ProxyChain::Direct(),
695 /*is_for_websockets=*/false,
696 common_connect_job_params) {}
697
last_group_id_received() const698 const ClientSocketPool::GroupId& last_group_id_received() const {
699 return last_group_id_;
700 }
701
socket_requested() const702 bool socket_requested() const { return socket_requested_; }
703
RequestSocket(const ClientSocketPool::GroupId & group_id,scoped_refptr<ClientSocketPool::SocketParams> socket_params,const std::optional<NetworkTrafficAnnotationTag> & proxy_annotation_tag,RequestPriority priority,const SocketTag & socket_tag,ClientSocketPool::RespectLimits respect_limits,ClientSocketHandle * handle,CompletionOnceCallback callback,const ClientSocketPool::ProxyAuthCallback & proxy_auth_callback,const NetLogWithSource & net_log)704 int RequestSocket(
705 const ClientSocketPool::GroupId& group_id,
706 scoped_refptr<ClientSocketPool::SocketParams> socket_params,
707 const std::optional<NetworkTrafficAnnotationTag>& proxy_annotation_tag,
708 RequestPriority priority,
709 const SocketTag& socket_tag,
710 ClientSocketPool::RespectLimits respect_limits,
711 ClientSocketHandle* handle,
712 CompletionOnceCallback callback,
713 const ClientSocketPool::ProxyAuthCallback& proxy_auth_callback,
714 const NetLogWithSource& net_log) override {
715 last_group_id_ = group_id;
716 socket_requested_ = true;
717 return ERR_IO_PENDING;
718 }
CancelRequest(const ClientSocketPool::GroupId & group_id,ClientSocketHandle * handle,bool cancel_connect_job)719 void CancelRequest(const ClientSocketPool::GroupId& group_id,
720 ClientSocketHandle* handle,
721 bool cancel_connect_job) override {}
ReleaseSocket(const ClientSocketPool::GroupId & group_id,std::unique_ptr<StreamSocket> socket,int64_t generation)722 void ReleaseSocket(const ClientSocketPool::GroupId& group_id,
723 std::unique_ptr<StreamSocket> socket,
724 int64_t generation) override {}
CloseIdleSockets(const char * net_log_reason_utf8)725 void CloseIdleSockets(const char* net_log_reason_utf8) override {}
CloseIdleSocketsInGroup(const ClientSocketPool::GroupId & group_id,const char * net_log_reason_utf8)726 void CloseIdleSocketsInGroup(const ClientSocketPool::GroupId& group_id,
727 const char* net_log_reason_utf8) override {}
IdleSocketCount() const728 int IdleSocketCount() const override { return 0; }
IdleSocketCountInGroup(const ClientSocketPool::GroupId & group_id) const729 size_t IdleSocketCountInGroup(
730 const ClientSocketPool::GroupId& group_id) const override {
731 return 0;
732 }
GetLoadState(const ClientSocketPool::GroupId & group_id,const ClientSocketHandle * handle) const733 LoadState GetLoadState(const ClientSocketPool::GroupId& group_id,
734 const ClientSocketHandle* handle) const override {
735 return LOAD_STATE_IDLE;
736 }
737
738 private:
739 ClientSocketPool::GroupId last_group_id_;
740 bool socket_requested_ = false;
741 };
742
743 //-----------------------------------------------------------------------------
744
745 // Helper functions for validating that AuthChallengeInfo's are correctly
746 // configured for common cases.
CheckBasicServerAuth(const std::optional<AuthChallengeInfo> & auth_challenge)747 bool CheckBasicServerAuth(
748 const std::optional<AuthChallengeInfo>& auth_challenge) {
749 if (!auth_challenge) {
750 return false;
751 }
752 EXPECT_FALSE(auth_challenge->is_proxy);
753 EXPECT_EQ("http://www.example.org", auth_challenge->challenger.Serialize());
754 EXPECT_EQ("MyRealm1", auth_challenge->realm);
755 EXPECT_EQ(kBasicAuthScheme, auth_challenge->scheme);
756 return true;
757 }
758
CheckBasicSecureServerAuth(const std::optional<AuthChallengeInfo> & auth_challenge)759 bool CheckBasicSecureServerAuth(
760 const std::optional<AuthChallengeInfo>& auth_challenge) {
761 if (!auth_challenge) {
762 return false;
763 }
764 EXPECT_FALSE(auth_challenge->is_proxy);
765 EXPECT_EQ("https://www.example.org", auth_challenge->challenger.Serialize());
766 EXPECT_EQ("MyRealm1", auth_challenge->realm);
767 EXPECT_EQ(kBasicAuthScheme, auth_challenge->scheme);
768 return true;
769 }
770
CheckBasicProxyAuth(const std::optional<AuthChallengeInfo> & auth_challenge)771 bool CheckBasicProxyAuth(
772 const std::optional<AuthChallengeInfo>& auth_challenge) {
773 if (!auth_challenge) {
774 return false;
775 }
776 EXPECT_TRUE(auth_challenge->is_proxy);
777 EXPECT_EQ("http://myproxy:70", auth_challenge->challenger.Serialize());
778 EXPECT_EQ("MyRealm1", auth_challenge->realm);
779 EXPECT_EQ(kBasicAuthScheme, auth_challenge->scheme);
780 return true;
781 }
782
CheckBasicSecureProxyAuth(const std::optional<AuthChallengeInfo> & auth_challenge)783 bool CheckBasicSecureProxyAuth(
784 const std::optional<AuthChallengeInfo>& auth_challenge) {
785 if (!auth_challenge) {
786 return false;
787 }
788 EXPECT_TRUE(auth_challenge->is_proxy);
789 EXPECT_EQ("https://myproxy:70", auth_challenge->challenger.Serialize());
790 EXPECT_EQ("MyRealm1", auth_challenge->realm);
791 EXPECT_EQ(kBasicAuthScheme, auth_challenge->scheme);
792 return true;
793 }
794
CheckDigestServerAuth(const std::optional<AuthChallengeInfo> & auth_challenge)795 bool CheckDigestServerAuth(
796 const std::optional<AuthChallengeInfo>& auth_challenge) {
797 if (!auth_challenge) {
798 return false;
799 }
800 EXPECT_FALSE(auth_challenge->is_proxy);
801 EXPECT_EQ("http://www.example.org", auth_challenge->challenger.Serialize());
802 EXPECT_EQ("digestive", auth_challenge->realm);
803 EXPECT_EQ(kDigestAuthScheme, auth_challenge->scheme);
804 return true;
805 }
806
807 #if defined(NTLM_PORTABLE)
CheckNTLMServerAuth(const std::optional<AuthChallengeInfo> & auth_challenge)808 bool CheckNTLMServerAuth(
809 const std::optional<AuthChallengeInfo>& auth_challenge) {
810 if (!auth_challenge) {
811 return false;
812 }
813 EXPECT_FALSE(auth_challenge->is_proxy);
814 EXPECT_EQ("https://server", auth_challenge->challenger.Serialize());
815 EXPECT_EQ(std::string(), auth_challenge->realm);
816 EXPECT_EQ(kNtlmAuthScheme, auth_challenge->scheme);
817 return true;
818 }
819
CheckNTLMProxyAuth(const std::optional<AuthChallengeInfo> & auth_challenge)820 bool CheckNTLMProxyAuth(
821 const std::optional<AuthChallengeInfo>& auth_challenge) {
822 if (!auth_challenge) {
823 return false;
824 }
825 EXPECT_TRUE(auth_challenge->is_proxy);
826 EXPECT_EQ("http://server", auth_challenge->challenger.Serialize());
827 EXPECT_EQ(std::string(), auth_challenge->realm);
828 EXPECT_EQ(kNtlmAuthScheme, auth_challenge->scheme);
829 return true;
830 }
831 #endif // defined(NTLM_PORTABLE)
832
833 } // namespace
834
TEST_P(HttpNetworkTransactionTest,Basic)835 TEST_P(HttpNetworkTransactionTest, Basic) {
836 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
837 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
838 }
839
TEST_P(HttpNetworkTransactionTest,SimpleGET)840 TEST_P(HttpNetworkTransactionTest, SimpleGET) {
841 MockRead data_reads[] = {
842 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
843 MockRead("hello world"),
844 MockRead(SYNCHRONOUS, OK),
845 };
846 SimpleGetHelperResult out = SimpleGetHelper(data_reads);
847 EXPECT_THAT(out.rv, IsOk());
848 EXPECT_EQ("HTTP/1.0 200 OK", out.status_line);
849 EXPECT_EQ("hello world", out.response_data);
850 int64_t reads_size = CountReadBytes(data_reads);
851 EXPECT_EQ(reads_size, out.total_received_bytes);
852 EXPECT_EQ(0u, out.connection_attempts.size());
853
854 EXPECT_FALSE(out.remote_endpoint_after_start.address().empty());
855 }
856
857 // Response with no status line.
TEST_P(HttpNetworkTransactionTest,SimpleGETNoHeaders)858 TEST_P(HttpNetworkTransactionTest, SimpleGETNoHeaders) {
859 MockRead data_reads[] = {
860 MockRead("hello world"),
861 MockRead(SYNCHRONOUS, OK),
862 };
863 SimpleGetHelperResult out = SimpleGetHelper(data_reads);
864 EXPECT_THAT(out.rv, IsOk());
865 EXPECT_EQ("HTTP/0.9 200 OK", out.status_line);
866 EXPECT_EQ("hello world", out.response_data);
867 int64_t reads_size = CountReadBytes(data_reads);
868 EXPECT_EQ(reads_size, out.total_received_bytes);
869 }
870
871 // Response with no status line, and a weird port. Should fail by default.
TEST_P(HttpNetworkTransactionTest,SimpleGETNoHeadersWeirdPort)872 TEST_P(HttpNetworkTransactionTest, SimpleGETNoHeadersWeirdPort) {
873 MockRead data_reads[] = {
874 MockRead("hello world"),
875 MockRead(SYNCHRONOUS, OK),
876 };
877
878 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
879 session_deps_.socket_factory->AddSocketDataProvider(&data);
880
881 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
882
883 HttpRequestInfo request;
884 auto trans =
885 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
886
887 request.method = "GET";
888 request.url = GURL("http://www.example.com:2000/");
889 request.traffic_annotation =
890 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
891
892 TestCompletionCallback callback;
893 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
894 EXPECT_THAT(callback.GetResult(rv), IsError(ERR_INVALID_HTTP_RESPONSE));
895 }
896
897 // Tests that request info can be destroyed after the headers phase is complete.
TEST_P(HttpNetworkTransactionTest,SimpleGETNoReadDestroyRequestInfo)898 TEST_P(HttpNetworkTransactionTest, SimpleGETNoReadDestroyRequestInfo) {
899 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
900 auto trans =
901 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
902
903 MockRead data_reads[] = {
904 MockRead("HTTP/1.0 200 OK\r\n"),
905 MockRead("Connection: keep-alive\r\n"),
906 MockRead("Content-Length: 100\r\n\r\n"),
907 MockRead(SYNCHRONOUS, 0),
908 };
909 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
910 session_deps_.socket_factory->AddSocketDataProvider(&data);
911
912 TestCompletionCallback callback;
913
914 {
915 auto request = std::make_unique<HttpRequestInfo>();
916 request->method = "GET";
917 request->url = GURL("http://www.example.org/");
918 request->traffic_annotation =
919 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
920
921 int rv =
922 trans->Start(request.get(), callback.callback(), NetLogWithSource());
923
924 EXPECT_THAT(callback.GetResult(rv), IsOk());
925 } // Let request info be destroyed.
926
927 trans.reset();
928 }
929
930 // Test that a failure in resolving the hostname is retrievable.
TEST_P(HttpNetworkTransactionTest,SimpleGETHostResolutionFailure)931 TEST_P(HttpNetworkTransactionTest, SimpleGETHostResolutionFailure) {
932 HttpRequestInfo request;
933 request.method = "GET";
934 request.url = GURL("http://www.example.org/");
935 request.traffic_annotation =
936 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
937
938 auto resolver = std::make_unique<MockHostResolver>();
939 resolver->rules()->AddSimulatedTimeoutFailure("www.example.org");
940 session_deps_.net_log = net::NetLog::Get();
941 session_deps_.host_resolver = std::move(resolver);
942 std::unique_ptr<HttpNetworkSession> session = CreateSession(&session_deps_);
943 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
944 TestCompletionCallback callback;
945
946 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
947 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
948 EXPECT_THAT(callback.WaitForResult(), IsError(ERR_NAME_NOT_RESOLVED));
949
950 const HttpResponseInfo* response = trans.GetResponseInfo();
951 ASSERT_TRUE(response);
952 EXPECT_THAT(response->resolve_error_info.error, IsError(ERR_DNS_TIMED_OUT));
953 }
954
955 // This test verifies that if the transaction fails before even connecting to a
956 // remote endpoint, the ConnectedCallback is never called.
TEST_P(HttpNetworkTransactionTest,ConnectedCallbackNeverCalled)957 TEST_P(HttpNetworkTransactionTest, ConnectedCallbackNeverCalled) {
958 auto resolver = std::make_unique<MockHostResolver>();
959 resolver->rules()->AddSimulatedTimeoutFailure("bar.test");
960 session_deps_.host_resolver = std::move(resolver);
961
962 ConnectedHandler connected_handler;
963 std::unique_ptr<HttpNetworkSession> session = CreateSession(&session_deps_);
964
965 auto request = DefaultRequestInfo();
966 request.url = GURL("http://bar.test");
967
968 HttpNetworkTransaction transaction(DEFAULT_PRIORITY, session.get());
969 transaction.SetConnectedCallback(connected_handler.Callback());
970
971 TestCompletionCallback callback;
972 transaction.Start(&request, callback.callback(), NetLogWithSource());
973 callback.WaitForResult();
974
975 EXPECT_THAT(connected_handler.transports(), IsEmpty());
976 }
977
978 // This test verifies that if the ConnectedCallback returns an error, the
979 // entire transaction fails with that error.
TEST_P(HttpNetworkTransactionTest,ConnectedCallbackFailure)980 TEST_P(HttpNetworkTransactionTest, ConnectedCallbackFailure) {
981 // The exact error code does not matter, as long as it is the same one
982 // returned by the transaction overall.
983 ConnectedHandler connected_handler;
984 connected_handler.set_result(ERR_NOT_IMPLEMENTED);
985
986 std::unique_ptr<HttpNetworkSession> session = CreateSession(&session_deps_);
987 auto request = DefaultRequestInfo();
988 HttpNetworkTransaction transaction(DEFAULT_PRIORITY, session.get());
989 transaction.SetConnectedCallback(connected_handler.Callback());
990
991 // We never get to writing any data, but we still need a socket.
992 StaticSocketDataProvider data;
993 session_deps_.socket_factory->AddSocketDataProvider(&data);
994
995 TestCompletionCallback callback;
996 EXPECT_THAT(
997 transaction.Start(&request, callback.callback(), NetLogWithSource()),
998 IsError(ERR_IO_PENDING));
999 EXPECT_THAT(callback.WaitForResult(), IsError(ERR_NOT_IMPLEMENTED));
1000
1001 EXPECT_THAT(connected_handler.transports(),
1002 ElementsAre(EmbeddedHttpServerTransportInfo()));
1003 }
1004
1005 // This test verifies that if the ConnectedCallback returns an error, the
1006 // underlying socket is not closed and can be reused by the next transaction.
TEST_P(HttpNetworkTransactionTest,ConnectedCallbackFailureAllowsSocketReuse)1007 TEST_P(HttpNetworkTransactionTest, ConnectedCallbackFailureAllowsSocketReuse) {
1008 ConnectedHandler connected_handler;
1009 connected_handler.set_result(ERR_NOT_IMPLEMENTED);
1010
1011 std::unique_ptr<HttpNetworkSession> session = CreateSession(&session_deps_);
1012 auto request = DefaultRequestInfo();
1013
1014 // A single socket should be opened and used for both transactions. Data
1015 // providers are matched to sockets at most once.
1016 MockRead data_reads[] = {
1017 MockRead("HTTP/1.0 200 OK\r\n"),
1018 MockRead("X-Test-Header: foo\r\n\r\n"),
1019 MockRead(SYNCHRONOUS, OK),
1020 };
1021 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
1022 session_deps_.socket_factory->AddSocketDataProvider(&data);
1023
1024 {
1025 HttpNetworkTransaction transaction(DEFAULT_PRIORITY, session.get());
1026 transaction.SetConnectedCallback(connected_handler.Callback());
1027
1028 TestCompletionCallback callback;
1029 EXPECT_THAT(
1030 transaction.Start(&request, callback.callback(), NetLogWithSource()),
1031 IsError(ERR_IO_PENDING));
1032 EXPECT_THAT(callback.WaitForResult(), IsError(ERR_NOT_IMPLEMENTED));
1033 }
1034
1035 // The data provider should still be linked to a socket.
1036 EXPECT_TRUE(data.socket());
1037 auto* socket = data.socket();
1038
1039 {
1040 HttpNetworkTransaction transaction(DEFAULT_PRIORITY, session.get());
1041
1042 TestCompletionCallback callback;
1043 EXPECT_THAT(
1044 transaction.Start(&request, callback.callback(), NetLogWithSource()),
1045 IsError(ERR_IO_PENDING));
1046 EXPECT_THAT(callback.WaitForResult(), IsOk());
1047
1048 EXPECT_TRUE(transaction.GetResponseInfo()->headers->HasHeaderValue(
1049 "X-Test-Header", "foo"));
1050
1051 // Still linked to the same socket.
1052 EXPECT_EQ(data.socket(), socket);
1053 }
1054 }
1055
1056 // This test verifies that the ConnectedCallback is called once in the case of
1057 // simple requests.
TEST_P(HttpNetworkTransactionTest,ConnectedCallbackCalledOnce)1058 TEST_P(HttpNetworkTransactionTest, ConnectedCallbackCalledOnce) {
1059 MockRead data_reads[] = {
1060 MockRead("HTTP/1.0 200 OK\r\n"),
1061 MockRead(SYNCHRONOUS, OK),
1062 };
1063 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
1064 session_deps_.socket_factory->AddSocketDataProvider(&data);
1065
1066 ConnectedHandler connected_handler;
1067 std::unique_ptr<HttpNetworkSession> session = CreateSession(&session_deps_);
1068 auto request = DefaultRequestInfo();
1069 HttpNetworkTransaction transaction(DEFAULT_PRIORITY, session.get());
1070 transaction.SetConnectedCallback(connected_handler.Callback());
1071
1072 TestCompletionCallback callback;
1073 EXPECT_THAT(
1074 transaction.Start(&request, callback.callback(), NetLogWithSource()),
1075 IsError(ERR_IO_PENDING));
1076 EXPECT_THAT(callback.WaitForResult(), IsOk());
1077
1078 EXPECT_THAT(connected_handler.transports(),
1079 ElementsAre(EmbeddedHttpServerTransportInfo()));
1080 }
1081
1082 // This test verifies that the ConnectedCallback is called once more per
1083 // authentication challenge.
TEST_P(HttpNetworkTransactionTest,ConnectedCallbackCalledOnEachAuthChallenge)1084 TEST_P(HttpNetworkTransactionTest, ConnectedCallbackCalledOnEachAuthChallenge) {
1085 ConnectedHandler connected_handler;
1086 std::unique_ptr<HttpNetworkSession> session = CreateSession(&session_deps_);
1087 auto request = DefaultRequestInfo();
1088 HttpNetworkTransaction transaction(DEFAULT_PRIORITY, session.get());
1089 transaction.SetConnectedCallback(connected_handler.Callback());
1090
1091 // First request receives an auth challenge.
1092 MockRead data_reads1[] = {
1093 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
1094 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n\r\n"),
1095 MockRead(SYNCHRONOUS, ERR_FAILED),
1096 };
1097 StaticSocketDataProvider data1(data_reads1, base::span<MockWrite>());
1098 session_deps_.socket_factory->AddSocketDataProvider(&data1);
1099
1100 // Second request is allowed through.
1101 MockRead data_reads2[] = {
1102 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
1103 MockRead(SYNCHRONOUS, OK),
1104 };
1105 StaticSocketDataProvider data2(data_reads2, base::span<MockWrite>());
1106 session_deps_.socket_factory->AddSocketDataProvider(&data2);
1107
1108 // First request, connects once.
1109 TestCompletionCallback callback1;
1110 EXPECT_THAT(
1111 transaction.Start(&request, callback1.callback(), NetLogWithSource()),
1112 IsError(ERR_IO_PENDING));
1113 EXPECT_THAT(callback1.WaitForResult(), IsOk());
1114
1115 EXPECT_THAT(connected_handler.transports(),
1116 ElementsAre(EmbeddedHttpServerTransportInfo()));
1117
1118 // Second request, connects again.
1119 TestCompletionCallback callback2;
1120 EXPECT_THAT(transaction.RestartWithAuth(AuthCredentials(kFoo, kBar),
1121 callback2.callback()),
1122 IsError(ERR_IO_PENDING));
1123 EXPECT_THAT(callback2.WaitForResult(), IsOk());
1124
1125 EXPECT_THAT(connected_handler.transports(),
1126 ElementsAre(EmbeddedHttpServerTransportInfo(),
1127 EmbeddedHttpServerTransportInfo()));
1128 }
1129
1130 // This test verifies that the ConnectedCallback is called once more per retry.
TEST_P(HttpNetworkTransactionTest,ConnectedCallbackCalledOnEachRetry)1131 TEST_P(HttpNetworkTransactionTest, ConnectedCallbackCalledOnEachRetry) {
1132 ConnectedHandler connected_handler;
1133 std::unique_ptr<HttpNetworkSession> session = CreateSession(&session_deps_);
1134 auto request = DefaultRequestInfo();
1135 HttpNetworkTransaction transaction(DEFAULT_PRIORITY, session.get());
1136 transaction.SetConnectedCallback(connected_handler.Callback());
1137
1138 // First request receives a retryable error.
1139 MockRead data_reads1[] = {
1140 MockRead(SYNCHRONOUS, ERR_HTTP2_SERVER_REFUSED_STREAM),
1141 };
1142 StaticSocketDataProvider data1(data_reads1, base::span<MockWrite>());
1143 session_deps_.socket_factory->AddSocketDataProvider(&data1);
1144
1145 // Second request is allowed through.
1146 MockRead data_reads2[] = {
1147 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
1148 MockRead(SYNCHRONOUS, OK),
1149 };
1150 StaticSocketDataProvider data2(data_reads2, base::span<MockWrite>());
1151 session_deps_.socket_factory->AddSocketDataProvider(&data2);
1152
1153 TestCompletionCallback callback1;
1154 EXPECT_THAT(
1155 transaction.Start(&request, callback1.callback(), NetLogWithSource()),
1156 IsError(ERR_IO_PENDING));
1157 EXPECT_THAT(callback1.WaitForResult(), IsOk());
1158
1159 EXPECT_THAT(connected_handler.transports(),
1160 ElementsAre(EmbeddedHttpServerTransportInfo(),
1161 EmbeddedHttpServerTransportInfo()));
1162 }
1163
TEST_P(HttpNetworkTransactionTest,ConnectedCallbackCalledAsync)1164 TEST_P(HttpNetworkTransactionTest, ConnectedCallbackCalledAsync) {
1165 MockRead data_reads[] = {
1166 MockRead("HTTP/1.0 200 OK\r\n"),
1167 MockRead(SYNCHRONOUS, OK),
1168 };
1169 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
1170 session_deps_.socket_factory->AddSocketDataProvider(&data);
1171
1172 ConnectedHandler connected_handler;
1173 connected_handler.set_run_callback(true);
1174 std::unique_ptr<HttpNetworkSession> session = CreateSession(&session_deps_);
1175 auto request = DefaultRequestInfo();
1176 HttpNetworkTransaction transaction(DEFAULT_PRIORITY, session.get());
1177 transaction.SetConnectedCallback(connected_handler.Callback());
1178
1179 TestCompletionCallback callback;
1180 EXPECT_THAT(
1181 transaction.Start(&request, callback.callback(), NetLogWithSource()),
1182 IsError(ERR_IO_PENDING));
1183 EXPECT_THAT(callback.WaitForResult(), IsOk());
1184
1185 EXPECT_THAT(connected_handler.transports(),
1186 ElementsAre(EmbeddedHttpServerTransportInfo()));
1187 }
1188
TEST_P(HttpNetworkTransactionTest,ConnectedCallbackCalledAsyncError)1189 TEST_P(HttpNetworkTransactionTest, ConnectedCallbackCalledAsyncError) {
1190 MockRead data_reads[] = {
1191 MockRead("HTTP/1.0 200 OK\r\n"),
1192 MockRead(SYNCHRONOUS, OK),
1193 };
1194 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
1195 session_deps_.socket_factory->AddSocketDataProvider(&data);
1196
1197 ConnectedHandler connected_handler;
1198 connected_handler.set_run_callback(true);
1199 connected_handler.set_result(ERR_FAILED);
1200 std::unique_ptr<HttpNetworkSession> session = CreateSession(&session_deps_);
1201 auto request = DefaultRequestInfo();
1202 HttpNetworkTransaction transaction(DEFAULT_PRIORITY, session.get());
1203 transaction.SetConnectedCallback(connected_handler.Callback());
1204
1205 TestCompletionCallback callback;
1206 EXPECT_THAT(
1207 transaction.Start(&request, callback.callback(), NetLogWithSource()),
1208 IsError(ERR_IO_PENDING));
1209 EXPECT_THAT(callback.WaitForResult(), IsError(ERR_FAILED));
1210
1211 EXPECT_THAT(connected_handler.transports(),
1212 ElementsAre(EmbeddedHttpServerTransportInfo()));
1213 }
1214
1215 // Allow up to 4 bytes of junk to precede status line.
TEST_P(HttpNetworkTransactionTest,StatusLineJunk3Bytes)1216 TEST_P(HttpNetworkTransactionTest, StatusLineJunk3Bytes) {
1217 MockRead data_reads[] = {
1218 MockRead("xxxHTTP/1.0 404 Not Found\nServer: blah\n\nDATA"),
1219 MockRead(SYNCHRONOUS, OK),
1220 };
1221 SimpleGetHelperResult out = SimpleGetHelper(data_reads);
1222 EXPECT_THAT(out.rv, IsOk());
1223 EXPECT_EQ("HTTP/1.0 404 Not Found", out.status_line);
1224 EXPECT_EQ("DATA", out.response_data);
1225 int64_t reads_size = CountReadBytes(data_reads);
1226 EXPECT_EQ(reads_size, out.total_received_bytes);
1227 }
1228
1229 // Allow up to 4 bytes of junk to precede status line.
TEST_P(HttpNetworkTransactionTest,StatusLineJunk4Bytes)1230 TEST_P(HttpNetworkTransactionTest, StatusLineJunk4Bytes) {
1231 MockRead data_reads[] = {
1232 MockRead("\n\nQJHTTP/1.0 404 Not Found\nServer: blah\n\nDATA"),
1233 MockRead(SYNCHRONOUS, OK),
1234 };
1235 SimpleGetHelperResult out = SimpleGetHelper(data_reads);
1236 EXPECT_THAT(out.rv, IsOk());
1237 EXPECT_EQ("HTTP/1.0 404 Not Found", out.status_line);
1238 EXPECT_EQ("DATA", out.response_data);
1239 int64_t reads_size = CountReadBytes(data_reads);
1240 EXPECT_EQ(reads_size, out.total_received_bytes);
1241 }
1242
1243 // Beyond 4 bytes of slop and it should fail to find a status line.
TEST_P(HttpNetworkTransactionTest,StatusLineJunk5Bytes)1244 TEST_P(HttpNetworkTransactionTest, StatusLineJunk5Bytes) {
1245 MockRead data_reads[] = {
1246 MockRead("xxxxxHTTP/1.1 404 Not Found\nServer: blah"),
1247 MockRead(SYNCHRONOUS, OK),
1248 };
1249 SimpleGetHelperResult out = SimpleGetHelper(data_reads);
1250 EXPECT_THAT(out.rv, IsOk());
1251 EXPECT_EQ("HTTP/0.9 200 OK", out.status_line);
1252 EXPECT_EQ("xxxxxHTTP/1.1 404 Not Found\nServer: blah", out.response_data);
1253 int64_t reads_size = CountReadBytes(data_reads);
1254 EXPECT_EQ(reads_size, out.total_received_bytes);
1255 }
1256
1257 // Same as StatusLineJunk4Bytes, except the read chunks are smaller.
TEST_P(HttpNetworkTransactionTest,StatusLineJunk4Bytes_Slow)1258 TEST_P(HttpNetworkTransactionTest, StatusLineJunk4Bytes_Slow) {
1259 MockRead data_reads[] = {
1260 MockRead("\n"),
1261 MockRead("\n"),
1262 MockRead("Q"),
1263 MockRead("J"),
1264 MockRead("HTTP/1.0 404 Not Found\nServer: blah\n\nDATA"),
1265 MockRead(SYNCHRONOUS, OK),
1266 };
1267 SimpleGetHelperResult out = SimpleGetHelper(data_reads);
1268 EXPECT_THAT(out.rv, IsOk());
1269 EXPECT_EQ("HTTP/1.0 404 Not Found", out.status_line);
1270 EXPECT_EQ("DATA", out.response_data);
1271 int64_t reads_size = CountReadBytes(data_reads);
1272 EXPECT_EQ(reads_size, out.total_received_bytes);
1273 }
1274
1275 // Close the connection before enough bytes to have a status line.
TEST_P(HttpNetworkTransactionTest,StatusLinePartial)1276 TEST_P(HttpNetworkTransactionTest, StatusLinePartial) {
1277 MockRead data_reads[] = {
1278 MockRead("HTT"),
1279 MockRead(SYNCHRONOUS, OK),
1280 };
1281 SimpleGetHelperResult out = SimpleGetHelper(data_reads);
1282 EXPECT_THAT(out.rv, IsOk());
1283 EXPECT_EQ("HTTP/0.9 200 OK", out.status_line);
1284 EXPECT_EQ("HTT", out.response_data);
1285 int64_t reads_size = CountReadBytes(data_reads);
1286 EXPECT_EQ(reads_size, out.total_received_bytes);
1287 }
1288
1289 // Simulate a 204 response, lacking a Content-Length header, sent over a
1290 // persistent connection. The response should still terminate since a 204
1291 // cannot have a response body.
TEST_P(HttpNetworkTransactionTest,StopsReading204)1292 TEST_P(HttpNetworkTransactionTest, StopsReading204) {
1293 char junk[] = "junk";
1294 MockRead data_reads[] = {
1295 MockRead("HTTP/1.1 204 No Content\r\n\r\n"),
1296 MockRead(junk), // Should not be read!!
1297 MockRead(SYNCHRONOUS, OK),
1298 };
1299 SimpleGetHelperResult out = SimpleGetHelper(data_reads);
1300 EXPECT_THAT(out.rv, IsOk());
1301 EXPECT_EQ("HTTP/1.1 204 No Content", out.status_line);
1302 EXPECT_EQ("", out.response_data);
1303 int64_t reads_size = CountReadBytes(data_reads);
1304 int64_t response_size = reads_size - strlen(junk);
1305 EXPECT_EQ(response_size, out.total_received_bytes);
1306 }
1307
1308 // A simple request using chunked encoding with some extra data after.
TEST_P(HttpNetworkTransactionTest,ChunkedEncoding)1309 TEST_P(HttpNetworkTransactionTest, ChunkedEncoding) {
1310 std::string final_chunk = "0\r\n\r\n";
1311 std::string extra_data = "HTTP/1.1 200 OK\r\n";
1312 std::string last_read = final_chunk + extra_data;
1313 MockRead data_reads[] = {
1314 MockRead("HTTP/1.1 200 OK\r\nTransfer-Encoding: chunked\r\n\r\n"),
1315 MockRead("5\r\nHello\r\n"),
1316 MockRead("1\r\n"),
1317 MockRead(" \r\n"),
1318 MockRead("5\r\nworld\r\n"),
1319 MockRead(last_read.data()),
1320 MockRead(SYNCHRONOUS, OK),
1321 };
1322 SimpleGetHelperResult out = SimpleGetHelper(data_reads);
1323 EXPECT_THAT(out.rv, IsOk());
1324 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
1325 EXPECT_EQ("Hello world", out.response_data);
1326 int64_t reads_size = CountReadBytes(data_reads);
1327 int64_t response_size = reads_size - extra_data.size();
1328 EXPECT_EQ(response_size, out.total_received_bytes);
1329 }
1330
1331 // Next tests deal with http://crbug.com/56344.
1332
TEST_P(HttpNetworkTransactionTest,MultipleContentLengthHeadersNoTransferEncoding)1333 TEST_P(HttpNetworkTransactionTest,
1334 MultipleContentLengthHeadersNoTransferEncoding) {
1335 MockRead data_reads[] = {
1336 MockRead("HTTP/1.1 200 OK\r\n"),
1337 MockRead("Content-Length: 10\r\n"),
1338 MockRead("Content-Length: 5\r\n\r\n"),
1339 };
1340 SimpleGetHelperResult out = SimpleGetHelper(data_reads);
1341 EXPECT_THAT(out.rv, IsError(ERR_RESPONSE_HEADERS_MULTIPLE_CONTENT_LENGTH));
1342 }
1343
TEST_P(HttpNetworkTransactionTest,DuplicateContentLengthHeadersNoTransferEncoding)1344 TEST_P(HttpNetworkTransactionTest,
1345 DuplicateContentLengthHeadersNoTransferEncoding) {
1346 MockRead data_reads[] = {
1347 MockRead("HTTP/1.1 200 OK\r\n"),
1348 MockRead("Content-Length: 5\r\n"),
1349 MockRead("Content-Length: 5\r\n\r\n"),
1350 MockRead("Hello"),
1351 };
1352 SimpleGetHelperResult out = SimpleGetHelper(data_reads);
1353 EXPECT_THAT(out.rv, IsOk());
1354 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
1355 EXPECT_EQ("Hello", out.response_data);
1356 }
1357
TEST_P(HttpNetworkTransactionTest,ComplexContentLengthHeadersNoTransferEncoding)1358 TEST_P(HttpNetworkTransactionTest,
1359 ComplexContentLengthHeadersNoTransferEncoding) {
1360 // More than 2 dupes.
1361 {
1362 MockRead data_reads[] = {
1363 MockRead("HTTP/1.1 200 OK\r\n"),
1364 MockRead("Content-Length: 5\r\n"),
1365 MockRead("Content-Length: 5\r\n"),
1366 MockRead("Content-Length: 5\r\n\r\n"),
1367 MockRead("Hello"),
1368 };
1369 SimpleGetHelperResult out = SimpleGetHelper(data_reads);
1370 EXPECT_THAT(out.rv, IsOk());
1371 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
1372 EXPECT_EQ("Hello", out.response_data);
1373 }
1374 // HTTP/1.0
1375 {
1376 MockRead data_reads[] = {
1377 MockRead("HTTP/1.0 200 OK\r\n"),
1378 MockRead("Content-Length: 5\r\n"),
1379 MockRead("Content-Length: 5\r\n"),
1380 MockRead("Content-Length: 5\r\n\r\n"),
1381 MockRead("Hello"),
1382 };
1383 SimpleGetHelperResult out = SimpleGetHelper(data_reads);
1384 EXPECT_THAT(out.rv, IsOk());
1385 EXPECT_EQ("HTTP/1.0 200 OK", out.status_line);
1386 EXPECT_EQ("Hello", out.response_data);
1387 }
1388 // 2 dupes and one mismatched.
1389 {
1390 MockRead data_reads[] = {
1391 MockRead("HTTP/1.1 200 OK\r\n"),
1392 MockRead("Content-Length: 10\r\n"),
1393 MockRead("Content-Length: 10\r\n"),
1394 MockRead("Content-Length: 5\r\n\r\n"),
1395 };
1396 SimpleGetHelperResult out = SimpleGetHelper(data_reads);
1397 EXPECT_THAT(out.rv, IsError(ERR_RESPONSE_HEADERS_MULTIPLE_CONTENT_LENGTH));
1398 }
1399 }
1400
TEST_P(HttpNetworkTransactionTest,MultipleContentLengthHeadersTransferEncoding)1401 TEST_P(HttpNetworkTransactionTest,
1402 MultipleContentLengthHeadersTransferEncoding) {
1403 MockRead data_reads[] = {
1404 MockRead("HTTP/1.1 200 OK\r\n"),
1405 MockRead("Content-Length: 666\r\n"),
1406 MockRead("Content-Length: 1337\r\n"),
1407 MockRead("Transfer-Encoding: chunked\r\n\r\n"),
1408 MockRead("5\r\nHello\r\n"),
1409 MockRead("1\r\n"),
1410 MockRead(" \r\n"),
1411 MockRead("5\r\nworld\r\n"),
1412 MockRead("0\r\n\r\nHTTP/1.1 200 OK\r\n"),
1413 MockRead(SYNCHRONOUS, OK),
1414 };
1415 SimpleGetHelperResult out = SimpleGetHelper(data_reads);
1416 EXPECT_THAT(out.rv, IsOk());
1417 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
1418 EXPECT_EQ("Hello world", out.response_data);
1419 }
1420
1421 // Next tests deal with http://crbug.com/98895.
1422
1423 // Checks that a single Content-Disposition header results in no error.
TEST_P(HttpNetworkTransactionTest,SingleContentDispositionHeader)1424 TEST_P(HttpNetworkTransactionTest, SingleContentDispositionHeader) {
1425 MockRead data_reads[] = {
1426 MockRead("HTTP/1.1 200 OK\r\n"),
1427 MockRead(
1428 "Content-Disposition: attachment;filename=\"salutations.txt\"r\n"),
1429 MockRead("Content-Length: 5\r\n\r\n"),
1430 MockRead("Hello"),
1431 };
1432 SimpleGetHelperResult out = SimpleGetHelper(data_reads);
1433 EXPECT_THAT(out.rv, IsOk());
1434 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
1435 EXPECT_EQ("Hello", out.response_data);
1436 }
1437
1438 // Checks that two identical Content-Disposition headers result in no error.
TEST_P(HttpNetworkTransactionTest,TwoIdenticalContentDispositionHeaders)1439 TEST_P(HttpNetworkTransactionTest, TwoIdenticalContentDispositionHeaders) {
1440 MockRead data_reads[] = {
1441 MockRead("HTTP/1.1 200 OK\r\n"),
1442 MockRead("Content-Disposition: attachment;filename=\"greetings.txt\"r\n"),
1443 MockRead("Content-Disposition: attachment;filename=\"greetings.txt\"r\n"),
1444 MockRead("Content-Length: 5\r\n\r\n"),
1445 MockRead("Hello"),
1446 };
1447 SimpleGetHelperResult out = SimpleGetHelper(data_reads);
1448 EXPECT_THAT(out.rv, IsOk());
1449 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
1450 EXPECT_EQ("Hello", out.response_data);
1451 }
1452
1453 // Checks that two distinct Content-Disposition headers result in an error.
TEST_P(HttpNetworkTransactionTest,TwoDistinctContentDispositionHeaders)1454 TEST_P(HttpNetworkTransactionTest, TwoDistinctContentDispositionHeaders) {
1455 MockRead data_reads[] = {
1456 MockRead("HTTP/1.1 200 OK\r\n"),
1457 MockRead("Content-Disposition: attachment;filename=\"greetings.txt\"r\n"),
1458 MockRead("Content-Disposition: attachment;filename=\"hi.txt\"r\n"),
1459 MockRead("Content-Length: 5\r\n\r\n"),
1460 MockRead("Hello"),
1461 };
1462 SimpleGetHelperResult out = SimpleGetHelper(data_reads);
1463 EXPECT_THAT(out.rv,
1464 IsError(ERR_RESPONSE_HEADERS_MULTIPLE_CONTENT_DISPOSITION));
1465 }
1466
1467 // Checks that two identical Location headers result in no error.
1468 // Also tests Location header behavior.
TEST_P(HttpNetworkTransactionTest,TwoIdenticalLocationHeaders)1469 TEST_P(HttpNetworkTransactionTest, TwoIdenticalLocationHeaders) {
1470 MockRead data_reads[] = {
1471 MockRead("HTTP/1.1 302 Redirect\r\n"),
1472 MockRead("Location: http://good.com/\r\n"),
1473 MockRead("Location: http://good.com/\r\n"),
1474 MockRead("Content-Length: 0\r\n\r\n"),
1475 MockRead(SYNCHRONOUS, OK),
1476 };
1477
1478 HttpRequestInfo request;
1479 request.method = "GET";
1480 request.url = GURL("http://redirect.com/");
1481 request.traffic_annotation =
1482 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
1483
1484 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
1485 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
1486
1487 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
1488 session_deps_.socket_factory->AddSocketDataProvider(&data);
1489
1490 TestCompletionCallback callback;
1491
1492 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
1493 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
1494
1495 EXPECT_THAT(callback.WaitForResult(), IsOk());
1496
1497 const HttpResponseInfo* response = trans.GetResponseInfo();
1498 ASSERT_TRUE(response);
1499 ASSERT_TRUE(response->headers);
1500 EXPECT_EQ("HTTP/1.1 302 Redirect", response->headers->GetStatusLine());
1501 std::string url;
1502 EXPECT_TRUE(response->headers->IsRedirect(&url));
1503 EXPECT_EQ("http://good.com/", url);
1504 EXPECT_TRUE(response->proxy_chain.is_direct());
1505 }
1506
1507 // Checks that two distinct Location headers result in an error.
TEST_P(HttpNetworkTransactionTest,TwoDistinctLocationHeaders)1508 TEST_P(HttpNetworkTransactionTest, TwoDistinctLocationHeaders) {
1509 MockRead data_reads[] = {
1510 MockRead("HTTP/1.1 302 Redirect\r\n"),
1511 MockRead("Location: http://good.com/\r\n"),
1512 MockRead("Location: http://evil.com/\r\n"),
1513 MockRead("Content-Length: 0\r\n\r\n"),
1514 MockRead(SYNCHRONOUS, OK),
1515 };
1516 SimpleGetHelperResult out = SimpleGetHelper(data_reads);
1517 EXPECT_THAT(out.rv, IsError(ERR_RESPONSE_HEADERS_MULTIPLE_LOCATION));
1518 }
1519
1520 // Do a request using the HEAD method. Verify that we don't try to read the
1521 // message body (since HEAD has none).
TEST_P(HttpNetworkTransactionTest,Head)1522 TEST_P(HttpNetworkTransactionTest, Head) {
1523 HttpRequestInfo request;
1524 request.method = "HEAD";
1525 request.url = GURL("http://www.example.org/");
1526 request.traffic_annotation =
1527 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
1528
1529 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
1530 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
1531 ConnectedHandler connected_handler;
1532 trans.SetConnectedCallback(connected_handler.Callback());
1533
1534 MockWrite data_writes1[] = {
1535 MockWrite("HEAD / HTTP/1.1\r\n"
1536 "Host: www.example.org\r\n"
1537 "Connection: keep-alive\r\n\r\n"),
1538 };
1539 MockRead data_reads1[] = {
1540 MockRead("HTTP/1.1 404 Not Found\r\n"),
1541 MockRead("Server: Blah\r\n"),
1542 MockRead("Content-Length: 1234\r\n\r\n"),
1543
1544 // No response body because the test stops reading here.
1545 MockRead(SYNCHRONOUS, ERR_UNEXPECTED),
1546 };
1547
1548 StaticSocketDataProvider data1(data_reads1, data_writes1);
1549 session_deps_.socket_factory->AddSocketDataProvider(&data1);
1550
1551 TestCompletionCallback callback1;
1552
1553 int rv = trans.Start(&request, callback1.callback(), NetLogWithSource());
1554 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
1555
1556 rv = callback1.WaitForResult();
1557 EXPECT_THAT(rv, IsOk());
1558
1559 const HttpResponseInfo* response = trans.GetResponseInfo();
1560 ASSERT_TRUE(response);
1561
1562 // Check that the headers got parsed.
1563 EXPECT_TRUE(response->headers);
1564 EXPECT_EQ(1234, response->headers->GetContentLength());
1565 EXPECT_EQ("HTTP/1.1 404 Not Found", response->headers->GetStatusLine());
1566 EXPECT_TRUE(response->proxy_chain.is_direct());
1567 EXPECT_THAT(connected_handler.transports(),
1568 ElementsAre(EmbeddedHttpServerTransportInfo()));
1569
1570 std::string server_header;
1571 size_t iter = 0;
1572 bool has_server_header =
1573 response->headers->EnumerateHeader(&iter, "Server", &server_header);
1574 EXPECT_TRUE(has_server_header);
1575 EXPECT_EQ("Blah", server_header);
1576
1577 // Reading should give EOF right away, since there is no message body
1578 // (despite non-zero content-length).
1579 std::string response_data;
1580 rv = ReadTransaction(&trans, &response_data);
1581 EXPECT_THAT(rv, IsOk());
1582 EXPECT_EQ("", response_data);
1583 }
1584
TEST_P(HttpNetworkTransactionTest,ReuseConnection)1585 TEST_P(HttpNetworkTransactionTest, ReuseConnection) {
1586 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
1587
1588 MockRead data_reads[] = {
1589 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
1590 MockRead("hello"),
1591 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
1592 MockRead("world"),
1593 MockRead(SYNCHRONOUS, OK),
1594 };
1595 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
1596 session_deps_.socket_factory->AddSocketDataProvider(&data);
1597
1598 const char* const kExpectedResponseData[] = {"hello", "world"};
1599
1600 for (const auto* expected_response_data : kExpectedResponseData) {
1601 HttpRequestInfo request;
1602 request.method = "GET";
1603 request.url = GURL("http://www.example.org/");
1604 request.traffic_annotation =
1605 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
1606
1607 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
1608
1609 TestCompletionCallback callback;
1610
1611 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
1612 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
1613
1614 rv = callback.WaitForResult();
1615 EXPECT_THAT(rv, IsOk());
1616
1617 const HttpResponseInfo* response = trans.GetResponseInfo();
1618 ASSERT_TRUE(response);
1619
1620 EXPECT_TRUE(response->headers);
1621 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
1622 EXPECT_TRUE(response->proxy_chain.is_direct());
1623
1624 std::string response_data;
1625 rv = ReadTransaction(&trans, &response_data);
1626 EXPECT_THAT(rv, IsOk());
1627 EXPECT_EQ(expected_response_data, response_data);
1628 }
1629 }
1630
TEST_P(HttpNetworkTransactionTest,Ignores100)1631 TEST_P(HttpNetworkTransactionTest, Ignores100) {
1632 std::vector<std::unique_ptr<UploadElementReader>> element_readers;
1633 element_readers.push_back(
1634 std::make_unique<UploadBytesElementReader>("foo", 3));
1635 ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0);
1636
1637 HttpRequestInfo request;
1638 request.method = "POST";
1639 request.url = GURL("http://www.foo.com/");
1640 request.upload_data_stream = &upload_data_stream;
1641 request.traffic_annotation =
1642 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
1643
1644 // Check the upload progress returned before initialization is correct.
1645 UploadProgress progress = request.upload_data_stream->GetUploadProgress();
1646 EXPECT_EQ(0u, progress.size());
1647 EXPECT_EQ(0u, progress.position());
1648
1649 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
1650 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
1651
1652 MockRead data_reads[] = {
1653 MockRead("HTTP/1.0 100 Continue\r\n\r\n"),
1654 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
1655 MockRead("hello world"),
1656 MockRead(SYNCHRONOUS, OK),
1657 };
1658 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
1659 session_deps_.socket_factory->AddSocketDataProvider(&data);
1660
1661 TestCompletionCallback callback;
1662
1663 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
1664 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
1665
1666 rv = callback.WaitForResult();
1667 EXPECT_THAT(rv, IsOk());
1668
1669 const HttpResponseInfo* response = trans.GetResponseInfo();
1670 ASSERT_TRUE(response);
1671
1672 EXPECT_TRUE(response->headers);
1673 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
1674
1675 std::string response_data;
1676 rv = ReadTransaction(&trans, &response_data);
1677 EXPECT_THAT(rv, IsOk());
1678 EXPECT_EQ("hello world", response_data);
1679 }
1680
1681 // This test is almost the same as Ignores100 above, but the response contains
1682 // a 102 instead of a 100. Also, instead of HTTP/1.0 the response is
1683 // HTTP/1.1 and the two status headers are read in one read.
TEST_P(HttpNetworkTransactionTest,Ignores1xx)1684 TEST_P(HttpNetworkTransactionTest, Ignores1xx) {
1685 HttpRequestInfo request;
1686 request.method = "GET";
1687 request.url = GURL("http://www.foo.com/");
1688 request.traffic_annotation =
1689 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
1690
1691 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
1692 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
1693
1694 MockRead data_reads[] = {
1695 MockRead("HTTP/1.1 102 Unspecified status code\r\n\r\n"
1696 "HTTP/1.1 200 OK\r\n\r\n"),
1697 MockRead("hello world"),
1698 MockRead(SYNCHRONOUS, OK),
1699 };
1700 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
1701 session_deps_.socket_factory->AddSocketDataProvider(&data);
1702
1703 TestCompletionCallback callback;
1704
1705 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
1706 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
1707
1708 rv = callback.WaitForResult();
1709 EXPECT_THAT(rv, IsOk());
1710
1711 const HttpResponseInfo* response = trans.GetResponseInfo();
1712 ASSERT_TRUE(response);
1713
1714 EXPECT_TRUE(response->headers);
1715 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
1716
1717 std::string response_data;
1718 rv = ReadTransaction(&trans, &response_data);
1719 EXPECT_THAT(rv, IsOk());
1720 EXPECT_EQ("hello world", response_data);
1721 }
1722
TEST_P(HttpNetworkTransactionTest,LoadTimingMeasuresTimeToFirstByteForHttp)1723 TEST_P(HttpNetworkTransactionTest, LoadTimingMeasuresTimeToFirstByteForHttp) {
1724 static const base::TimeDelta kDelayAfterFirstByte = base::Milliseconds(10);
1725
1726 HttpRequestInfo request;
1727 request.method = "GET";
1728 request.url = GURL("http://www.foo.com/");
1729 request.traffic_annotation =
1730 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
1731
1732 std::vector<MockWrite> data_writes = {
1733 MockWrite(ASYNC, 0,
1734 "GET / HTTP/1.1\r\n"
1735 "Host: www.foo.com\r\n"
1736 "Connection: keep-alive\r\n\r\n"),
1737 };
1738
1739 std::vector<MockRead> data_reads = {
1740 // Write one byte of the status line, followed by a pause.
1741 MockRead(ASYNC, 1, "H"),
1742 MockRead(ASYNC, ERR_IO_PENDING, 2),
1743 MockRead(ASYNC, 3, "TTP/1.1 200 OK\r\n\r\n"),
1744 MockRead(ASYNC, 4, "hello world"),
1745 MockRead(SYNCHRONOUS, OK, 5),
1746 };
1747
1748 SequencedSocketData data(data_reads, data_writes);
1749 session_deps_.socket_factory->AddSocketDataProvider(&data);
1750
1751 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
1752
1753 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
1754
1755 TestCompletionCallback callback;
1756
1757 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
1758 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
1759
1760 data.RunUntilPaused();
1761 ASSERT_TRUE(data.IsPaused());
1762 FastForwardBy(kDelayAfterFirstByte);
1763 data.Resume();
1764
1765 rv = callback.WaitForResult();
1766 EXPECT_THAT(rv, IsOk());
1767
1768 const HttpResponseInfo* response = trans.GetResponseInfo();
1769 ASSERT_TRUE(response);
1770
1771 EXPECT_TRUE(response->headers);
1772 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
1773
1774 LoadTimingInfo load_timing_info;
1775 EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info));
1776 EXPECT_FALSE(load_timing_info.receive_headers_start.is_null());
1777 EXPECT_FALSE(load_timing_info.connect_timing.connect_end.is_null());
1778 // Ensure we didn't include the delay in the TTFB time.
1779 EXPECT_EQ(load_timing_info.receive_headers_start,
1780 load_timing_info.connect_timing.connect_end);
1781 // Ensure that the mock clock advanced at all.
1782 EXPECT_EQ(base::TimeTicks::Now() - load_timing_info.receive_headers_start,
1783 kDelayAfterFirstByte);
1784
1785 std::string response_data;
1786 rv = ReadTransaction(&trans, &response_data);
1787 EXPECT_THAT(rv, IsOk());
1788 EXPECT_EQ("hello world", response_data);
1789 }
1790
1791 // Tests that the time-to-first-byte reported in a transaction's load timing
1792 // info uses the first response, even if 1XX/informational.
Check100ResponseTiming(bool use_spdy)1793 void HttpNetworkTransactionTestBase::Check100ResponseTiming(bool use_spdy) {
1794 static const base::TimeDelta kDelayAfter100Response = base::Milliseconds(10);
1795
1796 HttpRequestInfo request;
1797 request.method = "GET";
1798 request.url = GURL("https://www.foo.com/");
1799 request.traffic_annotation =
1800 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
1801
1802 SSLSocketDataProvider ssl(ASYNC, OK);
1803 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
1804
1805 std::vector<MockWrite> data_writes;
1806 std::vector<MockRead> data_reads;
1807
1808 spdy::SpdySerializedFrame spdy_req(
1809 spdy_util_.ConstructSpdyGet(request.url.spec().c_str(), 1, LOWEST));
1810
1811 spdy::Http2HeaderBlock spdy_resp1_headers;
1812 spdy_resp1_headers[spdy::kHttp2StatusHeader] = "100";
1813 spdy::SpdySerializedFrame spdy_resp1(
1814 spdy_util_.ConstructSpdyReply(1, spdy_resp1_headers.Clone()));
1815 spdy::SpdySerializedFrame spdy_resp2(
1816 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
1817 spdy::SpdySerializedFrame spdy_data(
1818 spdy_util_.ConstructSpdyDataFrame(1, "hello world", true));
1819
1820 if (use_spdy) {
1821 ssl.next_proto = kProtoHTTP2;
1822
1823 data_writes = {CreateMockWrite(spdy_req, 0)};
1824
1825 data_reads = {
1826 CreateMockRead(spdy_resp1, 1), MockRead(ASYNC, ERR_IO_PENDING, 2),
1827 CreateMockRead(spdy_resp2, 3), CreateMockRead(spdy_data, 4),
1828 MockRead(SYNCHRONOUS, OK, 5),
1829 };
1830 } else {
1831 data_writes = {
1832 MockWrite(ASYNC, 0,
1833 "GET / HTTP/1.1\r\n"
1834 "Host: www.foo.com\r\n"
1835 "Connection: keep-alive\r\n\r\n"),
1836 };
1837
1838 data_reads = {
1839 MockRead(ASYNC, 1, "HTTP/1.1 100 Continue\r\n\r\n"),
1840 MockRead(ASYNC, ERR_IO_PENDING, 2),
1841
1842 MockRead(ASYNC, 3, "HTTP/1.1 200 OK\r\n\r\n"),
1843 MockRead(ASYNC, 4, "hello world"),
1844 MockRead(SYNCHRONOUS, OK, 5),
1845 };
1846 }
1847
1848 SequencedSocketData data(data_reads, data_writes);
1849 session_deps_.socket_factory->AddSocketDataProvider(&data);
1850
1851 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
1852
1853 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
1854
1855 TestCompletionCallback callback;
1856
1857 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
1858 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
1859
1860 data.RunUntilPaused();
1861 // We should now have parsed the 100 response and hit ERR_IO_PENDING. Insert
1862 // the delay before parsing the 200 response.
1863 ASSERT_TRUE(data.IsPaused());
1864 FastForwardBy(kDelayAfter100Response);
1865 data.Resume();
1866
1867 rv = callback.WaitForResult();
1868 EXPECT_THAT(rv, IsOk());
1869
1870 const HttpResponseInfo* response = trans.GetResponseInfo();
1871 ASSERT_TRUE(response);
1872
1873 LoadTimingInfo load_timing_info;
1874 EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info));
1875 EXPECT_FALSE(load_timing_info.receive_headers_start.is_null());
1876 EXPECT_FALSE(load_timing_info.connect_timing.connect_end.is_null());
1877 // Ensure we didn't include the delay in the TTFB time.
1878 EXPECT_EQ(load_timing_info.receive_headers_start,
1879 load_timing_info.connect_timing.connect_end);
1880 // Ensure that the mock clock advanced at all.
1881 EXPECT_EQ(base::TimeTicks::Now() - load_timing_info.receive_headers_start,
1882 kDelayAfter100Response);
1883
1884 std::string response_data;
1885 rv = ReadTransaction(&trans, &response_data);
1886 EXPECT_THAT(rv, IsOk());
1887 EXPECT_EQ("hello world", response_data);
1888 }
1889
TEST_P(HttpNetworkTransactionTest,MeasuresTimeToFirst100ResponseForHttp)1890 TEST_P(HttpNetworkTransactionTest, MeasuresTimeToFirst100ResponseForHttp) {
1891 Check100ResponseTiming(false /* use_spdy */);
1892 }
1893
TEST_P(HttpNetworkTransactionTest,MeasuresTimeToFirst100ResponseForSpdy)1894 TEST_P(HttpNetworkTransactionTest, MeasuresTimeToFirst100ResponseForSpdy) {
1895 Check100ResponseTiming(true /* use_spdy */);
1896 }
1897
TEST_P(HttpNetworkTransactionTest,Incomplete100ThenEOF)1898 TEST_P(HttpNetworkTransactionTest, Incomplete100ThenEOF) {
1899 HttpRequestInfo request;
1900 request.method = "POST";
1901 request.url = GURL("http://www.foo.com/");
1902 request.traffic_annotation =
1903 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
1904
1905 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
1906 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
1907
1908 MockRead data_reads[] = {
1909 MockRead(SYNCHRONOUS, "HTTP/1.0 100 Continue\r\n"),
1910 MockRead(ASYNC, 0),
1911 };
1912 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
1913 session_deps_.socket_factory->AddSocketDataProvider(&data);
1914
1915 TestCompletionCallback callback;
1916
1917 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
1918 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
1919
1920 rv = callback.WaitForResult();
1921 EXPECT_THAT(rv, IsOk());
1922
1923 std::string response_data;
1924 rv = ReadTransaction(&trans, &response_data);
1925 EXPECT_THAT(rv, IsOk());
1926 EXPECT_EQ("", response_data);
1927 }
1928
TEST_P(HttpNetworkTransactionTest,EmptyResponse)1929 TEST_P(HttpNetworkTransactionTest, EmptyResponse) {
1930 HttpRequestInfo request;
1931 request.method = "POST";
1932 request.url = GURL("http://www.foo.com/");
1933 request.traffic_annotation =
1934 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
1935
1936 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
1937 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
1938
1939 MockRead data_reads[] = {
1940 MockRead(ASYNC, 0),
1941 };
1942 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
1943 session_deps_.socket_factory->AddSocketDataProvider(&data);
1944
1945 TestCompletionCallback callback;
1946
1947 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
1948 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
1949
1950 rv = callback.WaitForResult();
1951 EXPECT_THAT(rv, IsError(ERR_EMPTY_RESPONSE));
1952 }
1953
KeepAliveConnectionResendRequestTest(const MockWrite * write_failure,const MockRead * read_failure)1954 void HttpNetworkTransactionTestBase::KeepAliveConnectionResendRequestTest(
1955 const MockWrite* write_failure,
1956 const MockRead* read_failure) {
1957 HttpRequestInfo request;
1958 request.method = "GET";
1959 request.url = GURL("http://www.foo.com/");
1960 request.traffic_annotation =
1961 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
1962
1963 session_deps_.net_log = net::NetLog::Get();
1964 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
1965
1966 // Written data for successfully sending both requests.
1967 MockWrite data1_writes[] = {MockWrite("GET / HTTP/1.1\r\n"
1968 "Host: www.foo.com\r\n"
1969 "Connection: keep-alive\r\n\r\n"),
1970 MockWrite("GET / HTTP/1.1\r\n"
1971 "Host: www.foo.com\r\n"
1972 "Connection: keep-alive\r\n\r\n")};
1973
1974 // Read results for the first request.
1975 MockRead data1_reads[] = {
1976 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
1977 MockRead("hello"),
1978 MockRead(ASYNC, OK),
1979 };
1980
1981 if (write_failure) {
1982 ASSERT_FALSE(read_failure);
1983 data1_writes[1] = *write_failure;
1984 } else {
1985 ASSERT_TRUE(read_failure);
1986 data1_reads[2] = *read_failure;
1987 }
1988
1989 StaticSocketDataProvider data1(data1_reads, data1_writes);
1990 session_deps_.socket_factory->AddSocketDataProvider(&data1);
1991
1992 MockRead data2_reads[] = {
1993 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
1994 MockRead("world"),
1995 MockRead(ASYNC, OK),
1996 };
1997 StaticSocketDataProvider data2(data2_reads, base::span<MockWrite>());
1998 session_deps_.socket_factory->AddSocketDataProvider(&data2);
1999
2000 const char* const kExpectedResponseData[] = {"hello", "world"};
2001
2002 uint32_t first_socket_log_id = NetLogSource::kInvalidId;
2003 for (int i = 0; i < 2; ++i) {
2004 TestCompletionCallback callback;
2005
2006 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
2007
2008 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
2009 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
2010
2011 rv = callback.WaitForResult();
2012 EXPECT_THAT(rv, IsOk());
2013
2014 LoadTimingInfo load_timing_info;
2015 EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info));
2016 TestLoadTimingNotReused(load_timing_info, CONNECT_TIMING_HAS_DNS_TIMES);
2017 if (i == 0) {
2018 first_socket_log_id = load_timing_info.socket_log_id;
2019 } else {
2020 // The second request should be using a new socket.
2021 EXPECT_NE(first_socket_log_id, load_timing_info.socket_log_id);
2022 }
2023
2024 const HttpResponseInfo* response = trans.GetResponseInfo();
2025 ASSERT_TRUE(response);
2026
2027 EXPECT_TRUE(response->headers);
2028 EXPECT_TRUE(response->proxy_chain.is_direct());
2029 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
2030
2031 std::string response_data;
2032 rv = ReadTransaction(&trans, &response_data);
2033 EXPECT_THAT(rv, IsOk());
2034 EXPECT_EQ(kExpectedResponseData[i], response_data);
2035 }
2036 }
2037
PreconnectErrorResendRequestTest(const MockWrite * write_failure,const MockRead * read_failure,bool use_spdy,bool chunked_upload)2038 void HttpNetworkTransactionTestBase::PreconnectErrorResendRequestTest(
2039 const MockWrite* write_failure,
2040 const MockRead* read_failure,
2041 bool use_spdy,
2042 bool chunked_upload) {
2043 SpdyTestUtil spdy_util(/*use_priority_header=*/true);
2044 HttpRequestInfo request;
2045 request.method = "GET";
2046 request.url = GURL("https://www.foo.com/");
2047 request.traffic_annotation =
2048 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
2049
2050 const char upload_data[] = "foobar";
2051 ChunkedUploadDataStream upload_data_stream(0);
2052 if (chunked_upload) {
2053 request.method = "POST";
2054 upload_data_stream.AppendData(upload_data, std::size(upload_data) - 1,
2055 true);
2056 request.upload_data_stream = &upload_data_stream;
2057 }
2058
2059 session_deps_.net_log = net::NetLog::Get();
2060 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
2061
2062 SSLSocketDataProvider ssl1(ASYNC, OK);
2063 SSLSocketDataProvider ssl2(ASYNC, OK);
2064 if (use_spdy) {
2065 ssl1.next_proto = kProtoHTTP2;
2066 ssl2.next_proto = kProtoHTTP2;
2067 }
2068 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl1);
2069 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
2070
2071 // SPDY versions of the request and response.
2072
2073 spdy::Http2HeaderBlock spdy_post_header_block;
2074 spdy_post_header_block[spdy::kHttp2MethodHeader] = "POST";
2075 spdy_util.AddUrlToHeaderBlock(request.url.spec(), &spdy_post_header_block);
2076 spdy::SpdySerializedFrame spdy_request(
2077 chunked_upload
2078 ? spdy_util.ConstructSpdyHeaders(1, std::move(spdy_post_header_block),
2079 DEFAULT_PRIORITY, false)
2080 : spdy_util.ConstructSpdyGet(request.url.spec().c_str(), 1,
2081 DEFAULT_PRIORITY));
2082
2083 spdy::SpdySerializedFrame spdy_request_body(
2084 spdy_util.ConstructSpdyDataFrame(1, "foobar", true));
2085 spdy::SpdySerializedFrame spdy_response(
2086 spdy_util.ConstructSpdyGetReply(nullptr, 0, 1));
2087 spdy::SpdySerializedFrame spdy_data(
2088 spdy_util.ConstructSpdyDataFrame(1, "hello", true));
2089
2090 // HTTP/1.1 versions of the request and response.
2091 const std::string http_request =
2092 std::string(chunked_upload ? "POST" : "GET") +
2093 " / HTTP/1.1\r\n"
2094 "Host: www.foo.com\r\n"
2095 "Connection: keep-alive\r\n" +
2096 (chunked_upload ? "Transfer-Encoding: chunked\r\n\r\n" : "\r\n");
2097 const char* kHttpRequest = http_request.c_str();
2098 const char kHttpResponse[] = "HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n";
2099 const char kHttpData[] = "hello";
2100
2101 std::vector<MockRead> data1_reads;
2102 std::vector<MockWrite> data1_writes;
2103 if (write_failure) {
2104 ASSERT_FALSE(read_failure);
2105 data1_writes.push_back(*write_failure);
2106 data1_reads.emplace_back(ASYNC, OK);
2107 } else {
2108 ASSERT_TRUE(read_failure);
2109 if (use_spdy) {
2110 data1_writes.push_back(CreateMockWrite(spdy_request));
2111 if (chunked_upload) {
2112 data1_writes.push_back(CreateMockWrite(spdy_request_body));
2113 }
2114 } else {
2115 data1_writes.emplace_back(kHttpRequest);
2116 if (chunked_upload) {
2117 data1_writes.emplace_back("6\r\nfoobar\r\n");
2118 data1_writes.emplace_back("0\r\n\r\n");
2119 }
2120 }
2121 data1_reads.push_back(*read_failure);
2122 }
2123
2124 StaticSocketDataProvider data1(data1_reads, data1_writes);
2125 session_deps_.socket_factory->AddSocketDataProvider(&data1);
2126
2127 std::vector<MockRead> data2_reads;
2128 std::vector<MockWrite> data2_writes;
2129
2130 if (use_spdy) {
2131 int seq = 0;
2132 data2_writes.push_back(CreateMockWrite(spdy_request, seq++, ASYNC));
2133 if (chunked_upload) {
2134 data2_writes.push_back(CreateMockWrite(spdy_request_body, seq++, ASYNC));
2135 }
2136 data2_reads.push_back(CreateMockRead(spdy_response, seq++, ASYNC));
2137 data2_reads.push_back(CreateMockRead(spdy_data, seq++, ASYNC));
2138 data2_reads.emplace_back(ASYNC, OK, seq++);
2139 } else {
2140 int seq = 0;
2141 data2_writes.emplace_back(ASYNC, kHttpRequest, strlen(kHttpRequest), seq++);
2142 if (chunked_upload) {
2143 data2_writes.emplace_back(ASYNC, "6\r\nfoobar\r\n", 11, seq++);
2144 data2_writes.emplace_back(ASYNC, "0\r\n\r\n", 5, seq++);
2145 }
2146 data2_reads.emplace_back(ASYNC, kHttpResponse, strlen(kHttpResponse),
2147 seq++);
2148 data2_reads.emplace_back(ASYNC, kHttpData, strlen(kHttpData), seq++);
2149 data2_reads.emplace_back(ASYNC, OK, seq++);
2150 }
2151 SequencedSocketData data2(data2_reads, data2_writes);
2152 session_deps_.socket_factory->AddSocketDataProvider(&data2);
2153
2154 // Preconnect a socket.
2155 session->http_stream_factory()->PreconnectStreams(1, request);
2156 // Wait for the preconnect to complete.
2157 // TODO(davidben): Some way to wait for an idle socket count might be handy.
2158 base::RunLoop().RunUntilIdle();
2159 EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session.get()));
2160
2161 // Make the request.
2162 TestCompletionCallback callback;
2163
2164 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
2165
2166 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
2167 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
2168
2169 rv = callback.WaitForResult();
2170 EXPECT_THAT(rv, IsOk());
2171
2172 LoadTimingInfo load_timing_info;
2173 EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info));
2174 TestLoadTimingNotReused(load_timing_info, CONNECT_TIMING_HAS_DNS_TIMES |
2175 CONNECT_TIMING_HAS_SSL_TIMES);
2176
2177 const HttpResponseInfo* response = trans.GetResponseInfo();
2178 ASSERT_TRUE(response);
2179
2180 EXPECT_TRUE(response->headers);
2181 if (response->was_fetched_via_spdy) {
2182 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
2183 } else {
2184 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
2185 }
2186
2187 std::string response_data;
2188 rv = ReadTransaction(&trans, &response_data);
2189 EXPECT_THAT(rv, IsOk());
2190 EXPECT_EQ(kHttpData, response_data);
2191 }
2192
2193 // Test that we do not retry indefinitely when a server sends an error like
2194 // ERR_HTTP2_PING_FAILED, ERR_HTTP2_SERVER_REFUSED_STREAM,
2195 // ERR_QUIC_HANDSHAKE_FAILED or ERR_QUIC_PROTOCOL_ERROR.
TEST_P(HttpNetworkTransactionTest,FiniteRetriesOnIOError)2196 TEST_P(HttpNetworkTransactionTest, FiniteRetriesOnIOError) {
2197 HttpRequestInfo request;
2198 request.method = "GET";
2199 request.url = GURL("https://www.foo.com/");
2200 request.traffic_annotation =
2201 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
2202
2203 // Check whether we give up after the third try.
2204
2205 // Construct an HTTP2 request and a "Go away" response.
2206 spdy::SpdySerializedFrame spdy_request(spdy_util_.ConstructSpdyGet(
2207 request.url.spec().c_str(), 1, DEFAULT_PRIORITY));
2208 spdy::SpdySerializedFrame spdy_response_go_away(
2209 spdy_util_.ConstructSpdyGoAway(0));
2210 MockRead data_read1[] = {CreateMockRead(spdy_response_go_away)};
2211 MockWrite data_write[] = {CreateMockWrite(spdy_request, 0)};
2212
2213 // Three go away responses.
2214 StaticSocketDataProvider data1(data_read1, data_write);
2215 StaticSocketDataProvider data2(data_read1, data_write);
2216 StaticSocketDataProvider data3(data_read1, data_write);
2217
2218 session_deps_.socket_factory->AddSocketDataProvider(&data1);
2219 AddSSLSocketData();
2220 session_deps_.socket_factory->AddSocketDataProvider(&data2);
2221 AddSSLSocketData();
2222 session_deps_.socket_factory->AddSocketDataProvider(&data3);
2223 AddSSLSocketData();
2224
2225 TestCompletionCallback callback;
2226 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
2227 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
2228
2229 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
2230 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
2231
2232 rv = callback.WaitForResult();
2233 EXPECT_THAT(rv, IsError(ERR_HTTP2_SERVER_REFUSED_STREAM));
2234 }
2235
TEST_P(HttpNetworkTransactionTest,RetryTwiceOnIOError)2236 TEST_P(HttpNetworkTransactionTest, RetryTwiceOnIOError) {
2237 HttpRequestInfo request;
2238 request.method = "GET";
2239 request.url = GURL("https://www.foo.com/");
2240 request.traffic_annotation =
2241 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
2242
2243 // Check whether we try atleast thrice before giving up.
2244
2245 // Construct an HTTP2 request and a "Go away" response.
2246 spdy::SpdySerializedFrame spdy_request(spdy_util_.ConstructSpdyGet(
2247 request.url.spec().c_str(), 1, DEFAULT_PRIORITY));
2248 spdy::SpdySerializedFrame spdy_response_go_away(
2249 spdy_util_.ConstructSpdyGoAway(0));
2250 MockRead data_read1[] = {CreateMockRead(spdy_response_go_away)};
2251 MockWrite data_write[] = {CreateMockWrite(spdy_request, 0)};
2252
2253 // Construct a non error HTTP2 response.
2254 spdy::SpdySerializedFrame spdy_response_no_error(
2255 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
2256 spdy::SpdySerializedFrame spdy_data(
2257 spdy_util_.ConstructSpdyDataFrame(1, true));
2258 MockRead data_read2[] = {CreateMockRead(spdy_response_no_error, 1),
2259 CreateMockRead(spdy_data, 2)};
2260
2261 // Two error responses.
2262 StaticSocketDataProvider data1(data_read1, data_write);
2263 StaticSocketDataProvider data2(data_read1, data_write);
2264 // Followed by a success response.
2265 SequencedSocketData data3(data_read2, data_write);
2266
2267 session_deps_.socket_factory->AddSocketDataProvider(&data1);
2268 AddSSLSocketData();
2269 session_deps_.socket_factory->AddSocketDataProvider(&data2);
2270 AddSSLSocketData();
2271 session_deps_.socket_factory->AddSocketDataProvider(&data3);
2272 AddSSLSocketData();
2273
2274 TestCompletionCallback callback;
2275 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
2276 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
2277
2278 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
2279 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
2280
2281 rv = callback.WaitForResult();
2282 EXPECT_THAT(rv, IsOk());
2283 }
2284
TEST_P(HttpNetworkTransactionTest,KeepAliveConnectionNotConnectedOnWrite)2285 TEST_P(HttpNetworkTransactionTest, KeepAliveConnectionNotConnectedOnWrite) {
2286 MockWrite write_failure(ASYNC, ERR_SOCKET_NOT_CONNECTED);
2287 KeepAliveConnectionResendRequestTest(&write_failure, nullptr);
2288 }
2289
TEST_P(HttpNetworkTransactionTest,KeepAliveConnectionReset)2290 TEST_P(HttpNetworkTransactionTest, KeepAliveConnectionReset) {
2291 MockRead read_failure(ASYNC, ERR_CONNECTION_RESET);
2292 KeepAliveConnectionResendRequestTest(nullptr, &read_failure);
2293 }
2294
TEST_P(HttpNetworkTransactionTest,KeepAliveConnectionEOF)2295 TEST_P(HttpNetworkTransactionTest, KeepAliveConnectionEOF) {
2296 MockRead read_failure(SYNCHRONOUS, OK); // EOF
2297 KeepAliveConnectionResendRequestTest(nullptr, &read_failure);
2298 }
2299
2300 // Make sure that on a 408 response (Request Timeout), the request is retried,
2301 // if the socket was a reused keep alive socket.
TEST_P(HttpNetworkTransactionTest,KeepAlive408)2302 TEST_P(HttpNetworkTransactionTest, KeepAlive408) {
2303 MockRead read_failure(SYNCHRONOUS,
2304 "HTTP/1.1 408 Request Timeout\r\n"
2305 "Connection: Keep-Alive\r\n"
2306 "Content-Length: 6\r\n\r\n"
2307 "Pickle");
2308 KeepAliveConnectionResendRequestTest(nullptr, &read_failure);
2309 }
2310
TEST_P(HttpNetworkTransactionTest,PreconnectErrorNotConnectedOnWrite)2311 TEST_P(HttpNetworkTransactionTest, PreconnectErrorNotConnectedOnWrite) {
2312 MockWrite write_failure(ASYNC, ERR_SOCKET_NOT_CONNECTED);
2313 PreconnectErrorResendRequestTest(&write_failure, nullptr,
2314 false /* use_spdy */);
2315 PreconnectErrorResendRequestTest(
2316 &write_failure, nullptr, false /* use_spdy */, true /* chunked_upload */);
2317 }
2318
TEST_P(HttpNetworkTransactionTest,PreconnectErrorReset)2319 TEST_P(HttpNetworkTransactionTest, PreconnectErrorReset) {
2320 MockRead read_failure(ASYNC, ERR_CONNECTION_RESET);
2321 PreconnectErrorResendRequestTest(nullptr, &read_failure,
2322 false /* use_spdy */);
2323 PreconnectErrorResendRequestTest(nullptr, &read_failure, false /* use_spdy */,
2324 true /* chunked_upload */);
2325 }
2326
TEST_P(HttpNetworkTransactionTest,PreconnectErrorEOF)2327 TEST_P(HttpNetworkTransactionTest, PreconnectErrorEOF) {
2328 MockRead read_failure(SYNCHRONOUS, OK); // EOF
2329 PreconnectErrorResendRequestTest(nullptr, &read_failure,
2330 false /* use_spdy */);
2331 PreconnectErrorResendRequestTest(nullptr, &read_failure, false /* use_spdy */,
2332 true /* chunked_upload */);
2333 }
2334
TEST_P(HttpNetworkTransactionTest,PreconnectErrorAsyncEOF)2335 TEST_P(HttpNetworkTransactionTest, PreconnectErrorAsyncEOF) {
2336 MockRead read_failure(ASYNC, OK); // EOF
2337 PreconnectErrorResendRequestTest(nullptr, &read_failure,
2338 false /* use_spdy */);
2339 PreconnectErrorResendRequestTest(nullptr, &read_failure, false /* use_spdy */,
2340 true /* chunked_upload */);
2341 }
2342
2343 // Make sure that on a 408 response (Request Timeout), the request is retried,
2344 // if the socket was a preconnected (UNUSED_IDLE) socket.
TEST_P(HttpNetworkTransactionTest,RetryOnIdle408)2345 TEST_P(HttpNetworkTransactionTest, RetryOnIdle408) {
2346 MockRead read_failure(SYNCHRONOUS,
2347 "HTTP/1.1 408 Request Timeout\r\n"
2348 "Connection: Keep-Alive\r\n"
2349 "Content-Length: 6\r\n\r\n"
2350 "Pickle");
2351 KeepAliveConnectionResendRequestTest(nullptr, &read_failure);
2352 PreconnectErrorResendRequestTest(nullptr, &read_failure,
2353 false /* use_spdy */);
2354 PreconnectErrorResendRequestTest(nullptr, &read_failure, false /* use_spdy */,
2355 true /* chunked_upload */);
2356 }
2357
TEST_P(HttpNetworkTransactionTest,SpdyPreconnectErrorNotConnectedOnWrite)2358 TEST_P(HttpNetworkTransactionTest, SpdyPreconnectErrorNotConnectedOnWrite) {
2359 MockWrite write_failure(ASYNC, ERR_SOCKET_NOT_CONNECTED);
2360 PreconnectErrorResendRequestTest(&write_failure, nullptr,
2361 true /* use_spdy */);
2362 PreconnectErrorResendRequestTest(&write_failure, nullptr, true /* use_spdy */,
2363 true /* chunked_upload */);
2364 }
2365
TEST_P(HttpNetworkTransactionTest,SpdyPreconnectErrorReset)2366 TEST_P(HttpNetworkTransactionTest, SpdyPreconnectErrorReset) {
2367 MockRead read_failure(ASYNC, ERR_CONNECTION_RESET);
2368 PreconnectErrorResendRequestTest(nullptr, &read_failure, true /* use_spdy */);
2369 PreconnectErrorResendRequestTest(nullptr, &read_failure, true /* use_spdy */,
2370 true /* chunked_upload */);
2371 }
2372
TEST_P(HttpNetworkTransactionTest,SpdyPreconnectErrorEOF)2373 TEST_P(HttpNetworkTransactionTest, SpdyPreconnectErrorEOF) {
2374 MockRead read_failure(SYNCHRONOUS, OK); // EOF
2375 PreconnectErrorResendRequestTest(nullptr, &read_failure, true /* use_spdy */);
2376 PreconnectErrorResendRequestTest(nullptr, &read_failure, true /* use_spdy */,
2377 true /* chunked_upload */);
2378 }
2379
TEST_P(HttpNetworkTransactionTest,SpdyPreconnectErrorAsyncEOF)2380 TEST_P(HttpNetworkTransactionTest, SpdyPreconnectErrorAsyncEOF) {
2381 MockRead read_failure(ASYNC, OK); // EOF
2382 PreconnectErrorResendRequestTest(nullptr, &read_failure, true /* use_spdy */);
2383 PreconnectErrorResendRequestTest(nullptr, &read_failure, true /* use_spdy */,
2384 true /* chunked_upload */);
2385 }
2386
TEST_P(HttpNetworkTransactionTest,NonKeepAliveConnectionReset)2387 TEST_P(HttpNetworkTransactionTest, NonKeepAliveConnectionReset) {
2388 HttpRequestInfo request;
2389 request.method = "GET";
2390 request.url = GURL("http://www.example.org/");
2391 request.traffic_annotation =
2392 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
2393
2394 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
2395 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
2396
2397 MockRead data_reads[] = {
2398 MockRead(ASYNC, ERR_CONNECTION_RESET),
2399 MockRead("HTTP/1.0 200 OK\r\n\r\n"), // Should not be used
2400 MockRead("hello world"),
2401 MockRead(SYNCHRONOUS, OK),
2402 };
2403 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
2404 session_deps_.socket_factory->AddSocketDataProvider(&data);
2405
2406 TestCompletionCallback callback;
2407
2408 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
2409 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
2410
2411 rv = callback.WaitForResult();
2412 EXPECT_THAT(rv, IsError(ERR_CONNECTION_RESET));
2413
2414 IPEndPoint endpoint;
2415 EXPECT_TRUE(trans.GetRemoteEndpoint(&endpoint));
2416 EXPECT_LT(0u, endpoint.address().size());
2417 }
2418
2419 // What do various browsers do when the server closes a non-keepalive
2420 // connection without sending any response header or body?
2421 //
2422 // IE7: error page
2423 // Safari 3.1.2 (Windows): error page
2424 // Firefox 3.0.1: blank page
2425 // Opera 9.52: after five attempts, blank page
2426 // Us with WinHTTP: error page (ERR_INVALID_RESPONSE)
2427 // Us: error page (EMPTY_RESPONSE)
TEST_P(HttpNetworkTransactionTest,NonKeepAliveConnectionEOF)2428 TEST_P(HttpNetworkTransactionTest, NonKeepAliveConnectionEOF) {
2429 MockRead data_reads[] = {
2430 MockRead(SYNCHRONOUS, OK), // EOF
2431 MockRead("HTTP/1.0 200 OK\r\n\r\n"), // Should not be used
2432 MockRead("hello world"),
2433 MockRead(SYNCHRONOUS, OK),
2434 };
2435 SimpleGetHelperResult out = SimpleGetHelper(data_reads);
2436 EXPECT_THAT(out.rv, IsError(ERR_EMPTY_RESPONSE));
2437 }
2438
2439 // Next 2 cases (KeepAliveEarlyClose and KeepAliveEarlyClose2) are regression
2440 // tests. There was a bug causing HttpNetworkTransaction to hang in the
2441 // destructor in such situations.
2442 // See http://crbug.com/154712 and http://crbug.com/156609.
TEST_P(HttpNetworkTransactionTest,KeepAliveEarlyClose)2443 TEST_P(HttpNetworkTransactionTest, KeepAliveEarlyClose) {
2444 HttpRequestInfo request;
2445 request.method = "GET";
2446 request.url = GURL("http://www.example.org/");
2447 request.traffic_annotation =
2448 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
2449
2450 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
2451 auto trans =
2452 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
2453
2454 MockRead data_reads[] = {
2455 MockRead("HTTP/1.0 200 OK\r\n"),
2456 MockRead("Connection: keep-alive\r\n"),
2457 MockRead("Content-Length: 100\r\n\r\n"),
2458 MockRead("hello"),
2459 MockRead(SYNCHRONOUS, 0),
2460 };
2461 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
2462 session_deps_.socket_factory->AddSocketDataProvider(&data);
2463
2464 TestCompletionCallback callback;
2465
2466 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
2467 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
2468
2469 rv = callback.WaitForResult();
2470 EXPECT_THAT(rv, IsOk());
2471
2472 scoped_refptr<IOBufferWithSize> io_buf =
2473 base::MakeRefCounted<IOBufferWithSize>(100);
2474 rv = trans->Read(io_buf.get(), io_buf->size(), callback.callback());
2475 if (rv == ERR_IO_PENDING) {
2476 rv = callback.WaitForResult();
2477 }
2478 EXPECT_EQ(5, rv);
2479 rv = trans->Read(io_buf.get(), io_buf->size(), callback.callback());
2480 EXPECT_THAT(rv, IsError(ERR_CONTENT_LENGTH_MISMATCH));
2481
2482 trans.reset();
2483 base::RunLoop().RunUntilIdle();
2484 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
2485 }
2486
TEST_P(HttpNetworkTransactionTest,KeepAliveEarlyClose2)2487 TEST_P(HttpNetworkTransactionTest, KeepAliveEarlyClose2) {
2488 HttpRequestInfo request;
2489 request.method = "GET";
2490 request.url = GURL("http://www.example.org/");
2491 request.traffic_annotation =
2492 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
2493
2494 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
2495 auto trans =
2496 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
2497
2498 MockRead data_reads[] = {
2499 MockRead("HTTP/1.0 200 OK\r\n"),
2500 MockRead("Connection: keep-alive\r\n"),
2501 MockRead("Content-Length: 100\r\n\r\n"),
2502 MockRead(SYNCHRONOUS, 0),
2503 };
2504 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
2505 session_deps_.socket_factory->AddSocketDataProvider(&data);
2506
2507 TestCompletionCallback callback;
2508
2509 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
2510 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
2511
2512 rv = callback.WaitForResult();
2513 EXPECT_THAT(rv, IsOk());
2514
2515 scoped_refptr<IOBufferWithSize> io_buf(
2516 base::MakeRefCounted<IOBufferWithSize>(100));
2517 rv = trans->Read(io_buf.get(), io_buf->size(), callback.callback());
2518 if (rv == ERR_IO_PENDING) {
2519 rv = callback.WaitForResult();
2520 }
2521 EXPECT_THAT(rv, IsError(ERR_CONTENT_LENGTH_MISMATCH));
2522
2523 trans.reset();
2524 base::RunLoop().RunUntilIdle();
2525 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
2526 }
2527
2528 // Test that we correctly reuse a keep-alive connection after not explicitly
2529 // reading the body.
TEST_P(HttpNetworkTransactionTest,KeepAliveAfterUnreadBody)2530 TEST_P(HttpNetworkTransactionTest, KeepAliveAfterUnreadBody) {
2531 HttpRequestInfo request;
2532 request.method = "GET";
2533 request.url = GURL("http://www.foo.com/");
2534 request.traffic_annotation =
2535 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
2536
2537 session_deps_.net_log = net::NetLog::Get();
2538 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
2539
2540 const char kRequestData[] =
2541 "GET / HTTP/1.1\r\n"
2542 "Host: www.foo.com\r\n"
2543 "Connection: keep-alive\r\n\r\n";
2544 MockWrite data_writes[] = {
2545 MockWrite(ASYNC, 0, kRequestData), MockWrite(ASYNC, 2, kRequestData),
2546 MockWrite(ASYNC, 4, kRequestData), MockWrite(ASYNC, 6, kRequestData),
2547 MockWrite(ASYNC, 8, kRequestData), MockWrite(ASYNC, 10, kRequestData),
2548 MockWrite(ASYNC, 12, kRequestData), MockWrite(ASYNC, 14, kRequestData),
2549 MockWrite(ASYNC, 17, kRequestData), MockWrite(ASYNC, 20, kRequestData),
2550 };
2551
2552 // Note that because all these reads happen in the same
2553 // StaticSocketDataProvider, it shows that the same socket is being reused for
2554 // all transactions.
2555 MockRead data_reads[] = {
2556 MockRead(ASYNC, 1, "HTTP/1.1 204 No Content\r\n\r\n"),
2557 MockRead(ASYNC, 3, "HTTP/1.1 205 Reset Content\r\n\r\n"),
2558 MockRead(ASYNC, 5, "HTTP/1.1 304 Not Modified\r\n\r\n"),
2559 MockRead(ASYNC, 7,
2560 "HTTP/1.1 302 Found\r\n"
2561 "Content-Length: 0\r\n\r\n"),
2562 MockRead(ASYNC, 9,
2563 "HTTP/1.1 302 Found\r\n"
2564 "Content-Length: 5\r\n\r\n"
2565 "hello"),
2566 MockRead(ASYNC, 11,
2567 "HTTP/1.1 301 Moved Permanently\r\n"
2568 "Content-Length: 0\r\n\r\n"),
2569 MockRead(ASYNC, 13,
2570 "HTTP/1.1 301 Moved Permanently\r\n"
2571 "Content-Length: 5\r\n\r\n"
2572 "hello"),
2573
2574 // In the next two rounds, IsConnectedAndIdle returns false, due to
2575 // the set_busy_before_sync_reads(true) call, while the
2576 // HttpNetworkTransaction is being shut down, but the socket is still
2577 // reuseable. See http://crbug.com/544255.
2578 MockRead(ASYNC, 15,
2579 "HTTP/1.1 200 Hunky-Dory\r\n"
2580 "Content-Length: 5\r\n\r\n"),
2581 MockRead(SYNCHRONOUS, 16, "hello"),
2582
2583 MockRead(ASYNC, 18,
2584 "HTTP/1.1 200 Hunky-Dory\r\n"
2585 "Content-Length: 5\r\n\r\n"
2586 "he"),
2587 MockRead(SYNCHRONOUS, 19, "llo"),
2588
2589 // The body of the final request is actually read.
2590 MockRead(ASYNC, 21, "HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
2591 MockRead(ASYNC, 22, "hello"),
2592 };
2593 SequencedSocketData data(data_reads, data_writes);
2594 data.set_busy_before_sync_reads(true);
2595 session_deps_.socket_factory->AddSocketDataProvider(&data);
2596
2597 const int kNumUnreadBodies = std::size(data_writes) - 1;
2598 std::string response_lines[kNumUnreadBodies];
2599
2600 uint32_t first_socket_log_id = NetLogSource::kInvalidId;
2601 for (size_t i = 0; i < kNumUnreadBodies; ++i) {
2602 TestCompletionCallback callback;
2603
2604 auto trans = std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY,
2605 session.get());
2606
2607 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
2608 EXPECT_THAT(callback.GetResult(rv), IsOk());
2609
2610 LoadTimingInfo load_timing_info;
2611 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
2612 if (i == 0) {
2613 TestLoadTimingNotReused(load_timing_info, CONNECT_TIMING_HAS_DNS_TIMES);
2614 first_socket_log_id = load_timing_info.socket_log_id;
2615 } else {
2616 TestLoadTimingReused(load_timing_info);
2617 EXPECT_EQ(first_socket_log_id, load_timing_info.socket_log_id);
2618 }
2619
2620 const HttpResponseInfo* response = trans->GetResponseInfo();
2621 ASSERT_TRUE(response);
2622
2623 ASSERT_TRUE(response->headers);
2624 response_lines[i] = response->headers->GetStatusLine();
2625
2626 // Delete the transaction without reading the response bodies. Then spin
2627 // the message loop, so the response bodies are drained.
2628 trans.reset();
2629 base::RunLoop().RunUntilIdle();
2630 }
2631
2632 const char* const kStatusLines[] = {
2633 "HTTP/1.1 204 No Content",
2634 "HTTP/1.1 205 Reset Content",
2635 "HTTP/1.1 304 Not Modified",
2636 "HTTP/1.1 302 Found",
2637 "HTTP/1.1 302 Found",
2638 "HTTP/1.1 301 Moved Permanently",
2639 "HTTP/1.1 301 Moved Permanently",
2640 "HTTP/1.1 200 Hunky-Dory",
2641 "HTTP/1.1 200 Hunky-Dory",
2642 };
2643
2644 static_assert(kNumUnreadBodies == std::size(kStatusLines),
2645 "forgot to update kStatusLines");
2646
2647 for (int i = 0; i < kNumUnreadBodies; ++i) {
2648 EXPECT_EQ(kStatusLines[i], response_lines[i]);
2649 }
2650
2651 TestCompletionCallback callback;
2652 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
2653 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
2654 EXPECT_THAT(callback.GetResult(rv), IsOk());
2655 const HttpResponseInfo* response = trans.GetResponseInfo();
2656 ASSERT_TRUE(response);
2657 ASSERT_TRUE(response->headers);
2658 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
2659 std::string response_data;
2660 rv = ReadTransaction(&trans, &response_data);
2661 EXPECT_THAT(rv, IsOk());
2662 EXPECT_EQ("hello", response_data);
2663 }
2664
2665 // Sockets that receive extra data after a response is complete should not be
2666 // reused.
TEST_P(HttpNetworkTransactionTest,KeepAliveWithUnusedData1)2667 TEST_P(HttpNetworkTransactionTest, KeepAliveWithUnusedData1) {
2668 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
2669 MockWrite data_writes1[] = {
2670 MockWrite("HEAD / HTTP/1.1\r\n"
2671 "Host: www.borked.com\r\n"
2672 "Connection: keep-alive\r\n\r\n"),
2673 };
2674
2675 MockRead data_reads1[] = {
2676 MockRead("HTTP/1.1 200 OK\r\n"
2677 "Connection: keep-alive\r\n"
2678 "Content-Length: 22\r\n\r\n"
2679 "This server is borked."),
2680 };
2681
2682 MockWrite data_writes2[] = {
2683 MockWrite("GET /foo HTTP/1.1\r\n"
2684 "Host: www.borked.com\r\n"
2685 "Connection: keep-alive\r\n\r\n"),
2686 };
2687
2688 MockRead data_reads2[] = {
2689 MockRead("HTTP/1.1 200 OK\r\n"
2690 "Content-Length: 3\r\n\r\n"
2691 "foo"),
2692 };
2693 StaticSocketDataProvider data1(data_reads1, data_writes1);
2694 session_deps_.socket_factory->AddSocketDataProvider(&data1);
2695 StaticSocketDataProvider data2(data_reads2, data_writes2);
2696 session_deps_.socket_factory->AddSocketDataProvider(&data2);
2697
2698 TestCompletionCallback callback;
2699 HttpRequestInfo request1;
2700 request1.method = "HEAD";
2701 request1.url = GURL("http://www.borked.com/");
2702 request1.traffic_annotation =
2703 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
2704
2705 auto trans1 =
2706 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
2707 int rv = trans1->Start(&request1, callback.callback(), NetLogWithSource());
2708 EXPECT_THAT(callback.GetResult(rv), IsOk());
2709
2710 const HttpResponseInfo* response1 = trans1->GetResponseInfo();
2711 ASSERT_TRUE(response1);
2712 ASSERT_TRUE(response1->headers);
2713 EXPECT_EQ(200, response1->headers->response_code());
2714 EXPECT_TRUE(response1->headers->IsKeepAlive());
2715
2716 std::string response_data1;
2717 EXPECT_THAT(ReadTransaction(trans1.get(), &response_data1), IsOk());
2718 EXPECT_EQ("", response_data1);
2719 // Deleting the transaction attempts to release the socket back into the
2720 // socket pool.
2721 trans1.reset();
2722
2723 HttpRequestInfo request2;
2724 request2.method = "GET";
2725 request2.url = GURL("http://www.borked.com/foo");
2726 request2.traffic_annotation =
2727 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
2728
2729 auto trans2 =
2730 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
2731 rv = trans2->Start(&request2, callback.callback(), NetLogWithSource());
2732 EXPECT_THAT(callback.GetResult(rv), IsOk());
2733
2734 const HttpResponseInfo* response2 = trans2->GetResponseInfo();
2735 ASSERT_TRUE(response2);
2736 ASSERT_TRUE(response2->headers);
2737 EXPECT_EQ(200, response2->headers->response_code());
2738
2739 std::string response_data2;
2740 EXPECT_THAT(ReadTransaction(trans2.get(), &response_data2), IsOk());
2741 EXPECT_EQ("foo", response_data2);
2742 }
2743
TEST_P(HttpNetworkTransactionTest,KeepAliveWithUnusedData2)2744 TEST_P(HttpNetworkTransactionTest, KeepAliveWithUnusedData2) {
2745 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
2746 MockWrite data_writes1[] = {
2747 MockWrite("GET / HTTP/1.1\r\n"
2748 "Host: www.borked.com\r\n"
2749 "Connection: keep-alive\r\n\r\n"),
2750 };
2751
2752 MockRead data_reads1[] = {
2753 MockRead("HTTP/1.1 200 OK\r\n"
2754 "Connection: keep-alive\r\n"
2755 "Content-Length: 22\r\n\r\n"
2756 "This server is borked."
2757 "Bonus data!"),
2758 };
2759
2760 MockWrite data_writes2[] = {
2761 MockWrite("GET /foo HTTP/1.1\r\n"
2762 "Host: www.borked.com\r\n"
2763 "Connection: keep-alive\r\n\r\n"),
2764 };
2765
2766 MockRead data_reads2[] = {
2767 MockRead("HTTP/1.1 200 OK\r\n"
2768 "Content-Length: 3\r\n\r\n"
2769 "foo"),
2770 };
2771 StaticSocketDataProvider data1(data_reads1, data_writes1);
2772 session_deps_.socket_factory->AddSocketDataProvider(&data1);
2773 StaticSocketDataProvider data2(data_reads2, data_writes2);
2774 session_deps_.socket_factory->AddSocketDataProvider(&data2);
2775
2776 TestCompletionCallback callback;
2777 HttpRequestInfo request1;
2778 request1.method = "GET";
2779 request1.url = GURL("http://www.borked.com/");
2780 request1.traffic_annotation =
2781 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
2782
2783 auto trans1 =
2784 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
2785 int rv = trans1->Start(&request1, callback.callback(), NetLogWithSource());
2786 EXPECT_THAT(callback.GetResult(rv), IsOk());
2787
2788 const HttpResponseInfo* response1 = trans1->GetResponseInfo();
2789 ASSERT_TRUE(response1);
2790 ASSERT_TRUE(response1->headers);
2791 EXPECT_EQ(200, response1->headers->response_code());
2792 EXPECT_TRUE(response1->headers->IsKeepAlive());
2793
2794 std::string response_data1;
2795 EXPECT_THAT(ReadTransaction(trans1.get(), &response_data1), IsOk());
2796 EXPECT_EQ("This server is borked.", response_data1);
2797 // Deleting the transaction attempts to release the socket back into the
2798 // socket pool.
2799 trans1.reset();
2800
2801 HttpRequestInfo request2;
2802 request2.method = "GET";
2803 request2.url = GURL("http://www.borked.com/foo");
2804 request2.traffic_annotation =
2805 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
2806
2807 auto trans2 =
2808 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
2809 rv = trans2->Start(&request2, callback.callback(), NetLogWithSource());
2810 EXPECT_THAT(callback.GetResult(rv), IsOk());
2811
2812 const HttpResponseInfo* response2 = trans2->GetResponseInfo();
2813 ASSERT_TRUE(response2);
2814 ASSERT_TRUE(response2->headers);
2815 EXPECT_EQ(200, response2->headers->response_code());
2816
2817 std::string response_data2;
2818 EXPECT_THAT(ReadTransaction(trans2.get(), &response_data2), IsOk());
2819 EXPECT_EQ("foo", response_data2);
2820 }
2821
TEST_P(HttpNetworkTransactionTest,KeepAliveWithUnusedData3)2822 TEST_P(HttpNetworkTransactionTest, KeepAliveWithUnusedData3) {
2823 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
2824 MockWrite data_writes1[] = {
2825 MockWrite("GET / HTTP/1.1\r\n"
2826 "Host: www.borked.com\r\n"
2827 "Connection: keep-alive\r\n\r\n"),
2828 };
2829
2830 MockRead data_reads1[] = {
2831 MockRead("HTTP/1.1 200 OK\r\n"
2832 "Connection: keep-alive\r\n"
2833 "Transfer-Encoding: chunked\r\n\r\n"),
2834 MockRead("16\r\nThis server is borked.\r\n"),
2835 MockRead("0\r\n\r\nBonus data!"),
2836 };
2837
2838 MockWrite data_writes2[] = {
2839 MockWrite("GET /foo HTTP/1.1\r\n"
2840 "Host: www.borked.com\r\n"
2841 "Connection: keep-alive\r\n\r\n"),
2842 };
2843
2844 MockRead data_reads2[] = {
2845 MockRead("HTTP/1.1 200 OK\r\n"
2846 "Content-Length: 3\r\n\r\n"
2847 "foo"),
2848 };
2849 StaticSocketDataProvider data1(data_reads1, data_writes1);
2850 session_deps_.socket_factory->AddSocketDataProvider(&data1);
2851 StaticSocketDataProvider data2(data_reads2, data_writes2);
2852 session_deps_.socket_factory->AddSocketDataProvider(&data2);
2853
2854 TestCompletionCallback callback;
2855 HttpRequestInfo request1;
2856 request1.method = "GET";
2857 request1.url = GURL("http://www.borked.com/");
2858 request1.traffic_annotation =
2859 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
2860
2861 auto trans1 =
2862 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
2863 int rv = trans1->Start(&request1, callback.callback(), NetLogWithSource());
2864 EXPECT_THAT(callback.GetResult(rv), IsOk());
2865
2866 const HttpResponseInfo* response1 = trans1->GetResponseInfo();
2867 ASSERT_TRUE(response1);
2868 ASSERT_TRUE(response1->headers);
2869 EXPECT_EQ(200, response1->headers->response_code());
2870 EXPECT_TRUE(response1->headers->IsKeepAlive());
2871
2872 std::string response_data1;
2873 EXPECT_THAT(ReadTransaction(trans1.get(), &response_data1), IsOk());
2874 EXPECT_EQ("This server is borked.", response_data1);
2875 // Deleting the transaction attempts to release the socket back into the
2876 // socket pool.
2877 trans1.reset();
2878
2879 HttpRequestInfo request2;
2880 request2.method = "GET";
2881 request2.url = GURL("http://www.borked.com/foo");
2882 request2.traffic_annotation =
2883 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
2884
2885 auto trans2 =
2886 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
2887 rv = trans2->Start(&request2, callback.callback(), NetLogWithSource());
2888 EXPECT_THAT(callback.GetResult(rv), IsOk());
2889
2890 const HttpResponseInfo* response2 = trans2->GetResponseInfo();
2891 ASSERT_TRUE(response2);
2892 ASSERT_TRUE(response2->headers);
2893 EXPECT_EQ(200, response2->headers->response_code());
2894
2895 std::string response_data2;
2896 EXPECT_THAT(ReadTransaction(trans2.get(), &response_data2), IsOk());
2897 EXPECT_EQ("foo", response_data2);
2898 }
2899
2900 // This is a little different from the others - it tests the case that the
2901 // HttpStreamParser doesn't know if there's extra data on a socket or not when
2902 // the HttpNetworkTransaction is torn down, because the response body hasn't
2903 // been read from yet, but the request goes through the HttpResponseBodyDrainer.
TEST_P(HttpNetworkTransactionTest,KeepAliveWithUnusedData4)2904 TEST_P(HttpNetworkTransactionTest, KeepAliveWithUnusedData4) {
2905 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
2906 MockWrite data_writes1[] = {
2907 MockWrite("GET / HTTP/1.1\r\n"
2908 "Host: www.borked.com\r\n"
2909 "Connection: keep-alive\r\n\r\n"),
2910 };
2911
2912 MockRead data_reads1[] = {
2913 MockRead("HTTP/1.1 200 OK\r\n"
2914 "Connection: keep-alive\r\n"
2915 "Transfer-Encoding: chunked\r\n\r\n"),
2916 MockRead("16\r\nThis server is borked.\r\n"),
2917 MockRead("0\r\n\r\nBonus data!"),
2918 };
2919 StaticSocketDataProvider data1(data_reads1, data_writes1);
2920 session_deps_.socket_factory->AddSocketDataProvider(&data1);
2921
2922 TestCompletionCallback callback;
2923 HttpRequestInfo request1;
2924 request1.method = "GET";
2925 request1.url = GURL("http://www.borked.com/");
2926 request1.traffic_annotation =
2927 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
2928
2929 auto trans =
2930 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
2931 int rv = trans->Start(&request1, callback.callback(), NetLogWithSource());
2932 EXPECT_THAT(callback.GetResult(rv), IsOk());
2933
2934 const HttpResponseInfo* response1 = trans->GetResponseInfo();
2935 ASSERT_TRUE(response1);
2936 ASSERT_TRUE(response1->headers);
2937 EXPECT_EQ(200, response1->headers->response_code());
2938 EXPECT_TRUE(response1->headers->IsKeepAlive());
2939
2940 // Deleting the transaction creates an HttpResponseBodyDrainer to read the
2941 // response body.
2942 trans.reset();
2943
2944 // Let the HttpResponseBodyDrainer drain the socket. It should determine the
2945 // socket can't be reused, rather than returning it to the socket pool.
2946 base::RunLoop().RunUntilIdle();
2947
2948 // There should be no idle sockets in the pool.
2949 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
2950 }
2951
2952 // Test the request-challenge-retry sequence for basic auth.
2953 // (basic auth is the easiest to mock, because it has no randomness).
TEST_P(HttpNetworkTransactionTest,BasicAuth)2954 TEST_P(HttpNetworkTransactionTest, BasicAuth) {
2955 HttpRequestInfo request;
2956 request.method = "GET";
2957 request.url = GURL("http://www.example.org/");
2958 request.traffic_annotation =
2959 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
2960
2961 session_deps_.net_log = net::NetLog::Get();
2962 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
2963 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
2964
2965 MockWrite data_writes1[] = {
2966 MockWrite("GET / HTTP/1.1\r\n"
2967 "Host: www.example.org\r\n"
2968 "Connection: keep-alive\r\n\r\n"),
2969 };
2970
2971 MockRead data_reads1[] = {
2972 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
2973 // Give a couple authenticate options (only the middle one is actually
2974 // supported).
2975 MockRead("WWW-Authenticate: Basic invalid\r\n"), // Malformed.
2976 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2977 MockRead("WWW-Authenticate: UNSUPPORTED realm=\"FOO\"\r\n"),
2978 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2979 // Large content-length -- won't matter, as connection will be reset.
2980 MockRead("Content-Length: 10000\r\n\r\n"),
2981 MockRead(SYNCHRONOUS, ERR_FAILED),
2982 };
2983
2984 // After calling trans->RestartWithAuth(), this is the request we should
2985 // be issuing -- the final header line contains the credentials.
2986 MockWrite data_writes2[] = {
2987 MockWrite("GET / HTTP/1.1\r\n"
2988 "Host: www.example.org\r\n"
2989 "Connection: keep-alive\r\n"
2990 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2991 };
2992
2993 // Lastly, the server responds with the actual content.
2994 MockRead data_reads2[] = {
2995 MockRead("HTTP/1.0 200 OK\r\n"),
2996 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2997 MockRead("Content-Length: 100\r\n\r\n"),
2998 MockRead(SYNCHRONOUS, OK),
2999 };
3000
3001 StaticSocketDataProvider data1(data_reads1, data_writes1);
3002 StaticSocketDataProvider data2(data_reads2, data_writes2);
3003 session_deps_.socket_factory->AddSocketDataProvider(&data1);
3004 session_deps_.socket_factory->AddSocketDataProvider(&data2);
3005
3006 TestCompletionCallback callback1;
3007
3008 int rv = trans.Start(&request, callback1.callback(), NetLogWithSource());
3009 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
3010
3011 rv = callback1.WaitForResult();
3012 EXPECT_THAT(rv, IsOk());
3013
3014 LoadTimingInfo load_timing_info1;
3015 EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info1));
3016 TestLoadTimingNotReused(load_timing_info1, CONNECT_TIMING_HAS_DNS_TIMES);
3017
3018 int64_t writes_size1 = CountWriteBytes(data_writes1);
3019 EXPECT_EQ(writes_size1, trans.GetTotalSentBytes());
3020 int64_t reads_size1 = CountReadBytes(data_reads1);
3021 EXPECT_EQ(reads_size1, trans.GetTotalReceivedBytes());
3022
3023 const HttpResponseInfo* response = trans.GetResponseInfo();
3024 ASSERT_TRUE(response);
3025 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge));
3026
3027 TestCompletionCallback callback2;
3028
3029 rv = trans.RestartWithAuth(AuthCredentials(kFoo, kBar), callback2.callback());
3030 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
3031
3032 rv = callback2.WaitForResult();
3033 EXPECT_THAT(rv, IsOk());
3034
3035 LoadTimingInfo load_timing_info2;
3036 EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info2));
3037 TestLoadTimingNotReused(load_timing_info2, CONNECT_TIMING_HAS_DNS_TIMES);
3038 // The load timing after restart should have a new socket ID, and times after
3039 // those of the first load timing.
3040 EXPECT_LE(load_timing_info1.receive_headers_end,
3041 load_timing_info2.connect_timing.connect_start);
3042 EXPECT_NE(load_timing_info1.socket_log_id, load_timing_info2.socket_log_id);
3043
3044 int64_t writes_size2 = CountWriteBytes(data_writes2);
3045 EXPECT_EQ(writes_size1 + writes_size2, trans.GetTotalSentBytes());
3046 int64_t reads_size2 = CountReadBytes(data_reads2);
3047 EXPECT_EQ(reads_size1 + reads_size2, trans.GetTotalReceivedBytes());
3048
3049 response = trans.GetResponseInfo();
3050 ASSERT_TRUE(response);
3051 EXPECT_FALSE(response->auth_challenge.has_value());
3052 EXPECT_EQ(100, response->headers->GetContentLength());
3053 }
3054
3055 // Test the request-challenge-retry sequence for basic auth.
3056 // (basic auth is the easiest to mock, because it has no randomness).
TEST_P(HttpNetworkTransactionTest,BasicAuthWithAddressChange)3057 TEST_P(HttpNetworkTransactionTest, BasicAuthWithAddressChange) {
3058 HttpRequestInfo request;
3059 request.method = "GET";
3060 request.url = GURL("http://www.example.org/");
3061 request.traffic_annotation =
3062 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
3063
3064 auto resolver = std::make_unique<MockHostResolver>();
3065 auto* resolver_ptr = resolver.get();
3066 session_deps_.net_log = net::NetLog::Get();
3067 session_deps_.host_resolver = std::move(resolver);
3068 std::unique_ptr<HttpNetworkSession> session = CreateSession(&session_deps_);
3069 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
3070
3071 resolver_ptr->rules()->ClearRules();
3072 resolver_ptr->rules()->AddRule("www.example.org", "127.0.0.1");
3073
3074 MockWrite data_writes1[] = {
3075 MockWrite("GET / HTTP/1.1\r\n"
3076 "Host: www.example.org\r\n"
3077 "Connection: keep-alive\r\n\r\n"),
3078 };
3079
3080 MockRead data_reads1[] = {
3081 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
3082 // Give a couple authenticate options (only the middle one is actually
3083 // supported).
3084 MockRead("WWW-Authenticate: Basic invalid\r\n"), // Malformed.
3085 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
3086 MockRead("WWW-Authenticate: UNSUPPORTED realm=\"FOO\"\r\n"),
3087 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3088 // Large content-length -- won't matter, as connection will be reset.
3089 MockRead("Content-Length: 10000\r\n\r\n"),
3090 MockRead(SYNCHRONOUS, ERR_FAILED),
3091 };
3092
3093 // After calling trans->RestartWithAuth(), this is the request we should
3094 // be issuing -- the final header line contains the credentials.
3095 MockWrite data_writes2[] = {
3096 MockWrite("GET / HTTP/1.1\r\n"
3097 "Host: www.example.org\r\n"
3098 "Connection: keep-alive\r\n"
3099 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
3100 };
3101
3102 // Lastly, the server responds with the actual content.
3103 MockRead data_reads2[] = {
3104 MockRead("HTTP/1.0 200 OK\r\n"),
3105 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3106 MockRead("Content-Length: 100\r\n\r\n"),
3107 MockRead(SYNCHRONOUS, OK),
3108 };
3109
3110 StaticSocketDataProvider data1(data_reads1, data_writes1);
3111 StaticSocketDataProvider data2(data_reads2, data_writes2);
3112 session_deps_.socket_factory->AddSocketDataProvider(&data1);
3113 session_deps_.socket_factory->AddSocketDataProvider(&data2);
3114
3115 TestCompletionCallback callback1;
3116
3117 EXPECT_EQ(OK, callback1.GetResult(trans.Start(&request, callback1.callback(),
3118 NetLogWithSource())));
3119
3120 LoadTimingInfo load_timing_info1;
3121 EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info1));
3122 TestLoadTimingNotReused(load_timing_info1, CONNECT_TIMING_HAS_DNS_TIMES);
3123
3124 int64_t writes_size1 = CountWriteBytes(data_writes1);
3125 EXPECT_EQ(writes_size1, trans.GetTotalSentBytes());
3126 int64_t reads_size1 = CountReadBytes(data_reads1);
3127 EXPECT_EQ(reads_size1, trans.GetTotalReceivedBytes());
3128
3129 const HttpResponseInfo* response = trans.GetResponseInfo();
3130 ASSERT_TRUE(response);
3131 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge));
3132
3133 IPEndPoint endpoint;
3134 EXPECT_TRUE(trans.GetRemoteEndpoint(&endpoint));
3135 ASSERT_FALSE(endpoint.address().empty());
3136 EXPECT_EQ("127.0.0.1:80", endpoint.ToString());
3137
3138 resolver_ptr->rules()->ClearRules();
3139 resolver_ptr->rules()->AddRule("www.example.org", "127.0.0.2");
3140
3141 TestCompletionCallback callback2;
3142
3143 EXPECT_EQ(OK, callback2.GetResult(trans.RestartWithAuth(
3144 AuthCredentials(kFoo, kBar), callback2.callback())));
3145
3146 LoadTimingInfo load_timing_info2;
3147 EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info2));
3148 TestLoadTimingNotReused(load_timing_info2, CONNECT_TIMING_HAS_DNS_TIMES);
3149 // The load timing after restart should have a new socket ID, and times after
3150 // those of the first load timing.
3151 EXPECT_LE(load_timing_info1.receive_headers_end,
3152 load_timing_info2.connect_timing.connect_start);
3153 EXPECT_NE(load_timing_info1.socket_log_id, load_timing_info2.socket_log_id);
3154
3155 int64_t writes_size2 = CountWriteBytes(data_writes2);
3156 EXPECT_EQ(writes_size1 + writes_size2, trans.GetTotalSentBytes());
3157 int64_t reads_size2 = CountReadBytes(data_reads2);
3158 EXPECT_EQ(reads_size1 + reads_size2, trans.GetTotalReceivedBytes());
3159
3160 response = trans.GetResponseInfo();
3161 ASSERT_TRUE(response);
3162 EXPECT_FALSE(response->auth_challenge.has_value());
3163 EXPECT_EQ(100, response->headers->GetContentLength());
3164
3165 EXPECT_TRUE(trans.GetRemoteEndpoint(&endpoint));
3166 ASSERT_FALSE(endpoint.address().empty());
3167 EXPECT_EQ("127.0.0.2:80", endpoint.ToString());
3168 }
3169
3170 // Test that, if the server requests auth indefinitely, HttpNetworkTransaction
3171 // will eventually give up.
TEST_P(HttpNetworkTransactionTest,BasicAuthForever)3172 TEST_P(HttpNetworkTransactionTest, BasicAuthForever) {
3173 HttpRequestInfo request;
3174 request.method = "GET";
3175 request.url = GURL("http://www.example.org/");
3176 request.traffic_annotation =
3177 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
3178
3179 session_deps_.net_log = net::NetLog::Get();
3180 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
3181 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
3182
3183 MockWrite data_writes[] = {
3184 MockWrite("GET / HTTP/1.1\r\n"
3185 "Host: www.example.org\r\n"
3186 "Connection: keep-alive\r\n\r\n"),
3187 };
3188
3189 MockRead data_reads[] = {
3190 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
3191 // Give a couple authenticate options (only the middle one is actually
3192 // supported).
3193 MockRead("WWW-Authenticate: Basic invalid\r\n"), // Malformed.
3194 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
3195 MockRead("WWW-Authenticate: UNSUPPORTED realm=\"FOO\"\r\n"),
3196 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3197 // Large content-length -- won't matter, as connection will be reset.
3198 MockRead("Content-Length: 10000\r\n\r\n"),
3199 MockRead(SYNCHRONOUS, ERR_FAILED),
3200 };
3201
3202 // After calling trans->RestartWithAuth(), this is the request we should
3203 // be issuing -- the final header line contains the credentials.
3204 MockWrite data_writes_restart[] = {
3205 MockWrite("GET / HTTP/1.1\r\n"
3206 "Host: www.example.org\r\n"
3207 "Connection: keep-alive\r\n"
3208 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
3209 };
3210
3211 StaticSocketDataProvider data(data_reads, data_writes);
3212 session_deps_.socket_factory->AddSocketDataProvider(&data);
3213
3214 TestCompletionCallback callback;
3215 int rv = callback.GetResult(
3216 trans.Start(&request, callback.callback(), NetLogWithSource()));
3217
3218 std::vector<std::unique_ptr<StaticSocketDataProvider>> data_restarts;
3219 for (int i = 0; i < 32; i++) {
3220 // Check the previous response was a 401.
3221 EXPECT_THAT(rv, IsOk());
3222 const HttpResponseInfo* response = trans.GetResponseInfo();
3223 ASSERT_TRUE(response);
3224 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge));
3225
3226 data_restarts.push_back(std::make_unique<StaticSocketDataProvider>(
3227 data_reads, data_writes_restart));
3228 session_deps_.socket_factory->AddSocketDataProvider(
3229 data_restarts.back().get());
3230 rv = callback.GetResult(trans.RestartWithAuth(AuthCredentials(kFoo, kBar),
3231 callback.callback()));
3232 }
3233
3234 // After too many tries, the transaction should have given up.
3235 EXPECT_THAT(rv, IsError(ERR_TOO_MANY_RETRIES));
3236 }
3237
TEST_P(HttpNetworkTransactionTest,DoNotSendAuth)3238 TEST_P(HttpNetworkTransactionTest, DoNotSendAuth) {
3239 HttpRequestInfo request;
3240 request.method = "GET";
3241 request.url = GURL("http://www.example.org/");
3242 request.privacy_mode = PRIVACY_MODE_ENABLED;
3243 request.traffic_annotation =
3244 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
3245
3246 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
3247 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
3248
3249 MockWrite data_writes[] = {
3250 MockWrite("GET / HTTP/1.1\r\n"
3251 "Host: www.example.org\r\n"
3252 "Connection: keep-alive\r\n\r\n"),
3253 };
3254
3255 MockRead data_reads[] = {
3256 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
3257 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
3258 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3259 // Large content-length -- won't matter, as connection will be reset.
3260 MockRead("Content-Length: 10000\r\n\r\n"),
3261 MockRead(SYNCHRONOUS, ERR_FAILED),
3262 };
3263
3264 StaticSocketDataProvider data(data_reads, data_writes);
3265 session_deps_.socket_factory->AddSocketDataProvider(&data);
3266 TestCompletionCallback callback;
3267
3268 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
3269 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
3270
3271 rv = callback.WaitForResult();
3272 EXPECT_EQ(0, rv);
3273
3274 int64_t writes_size = CountWriteBytes(data_writes);
3275 EXPECT_EQ(writes_size, trans.GetTotalSentBytes());
3276 int64_t reads_size = CountReadBytes(data_reads);
3277 EXPECT_EQ(reads_size, trans.GetTotalReceivedBytes());
3278
3279 const HttpResponseInfo* response = trans.GetResponseInfo();
3280 ASSERT_TRUE(response);
3281 EXPECT_FALSE(response->auth_challenge.has_value());
3282 }
3283
3284 // Test the request-challenge-retry sequence for basic auth, over a keep-alive
3285 // connection.
TEST_P(HttpNetworkTransactionTest,BasicAuthKeepAlive)3286 TEST_P(HttpNetworkTransactionTest, BasicAuthKeepAlive) {
3287 // On the second pass, the body read of the auth challenge is synchronous, so
3288 // IsConnectedAndIdle returns false. The socket should still be drained and
3289 // reused. See http://crbug.com/544255.
3290 for (int i = 0; i < 2; ++i) {
3291 HttpRequestInfo request;
3292 request.method = "GET";
3293 request.url = GURL("http://www.example.org/");
3294 request.traffic_annotation =
3295 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
3296
3297 session_deps_.net_log = net::NetLog::Get();
3298 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
3299
3300 MockWrite data_writes[] = {
3301 MockWrite(ASYNC, 0,
3302 "GET / HTTP/1.1\r\n"
3303 "Host: www.example.org\r\n"
3304 "Connection: keep-alive\r\n\r\n"),
3305
3306 // After calling trans.RestartWithAuth(), this is the request we should
3307 // be issuing -- the final header line contains the credentials.
3308 MockWrite(ASYNC, 6,
3309 "GET / HTTP/1.1\r\n"
3310 "Host: www.example.org\r\n"
3311 "Connection: keep-alive\r\n"
3312 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
3313 };
3314
3315 MockRead data_reads[] = {
3316 MockRead(ASYNC, 1, "HTTP/1.1 401 Unauthorized\r\n"),
3317 MockRead(ASYNC, 2, "WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
3318 MockRead(ASYNC, 3, "Content-Type: text/html; charset=iso-8859-1\r\n"),
3319 MockRead(ASYNC, 4, "Content-Length: 14\r\n\r\n"),
3320 MockRead(i == 0 ? ASYNC : SYNCHRONOUS, 5, "Unauthorized\r\n"),
3321
3322 // Lastly, the server responds with the actual content.
3323 MockRead(ASYNC, 7, "HTTP/1.1 200 OK\r\n"),
3324 MockRead(ASYNC, 8, "Content-Type: text/html; charset=iso-8859-1\r\n"),
3325 MockRead(ASYNC, 9, "Content-Length: 5\r\n\r\n"),
3326 MockRead(ASYNC, 10, "Hello"),
3327 };
3328
3329 SequencedSocketData data(data_reads, data_writes);
3330 data.set_busy_before_sync_reads(true);
3331 session_deps_.socket_factory->AddSocketDataProvider(&data);
3332
3333 TestCompletionCallback callback1;
3334
3335 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
3336 int rv = trans.Start(&request, callback1.callback(), NetLogWithSource());
3337 ASSERT_THAT(callback1.GetResult(rv), IsOk());
3338
3339 LoadTimingInfo load_timing_info1;
3340 EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info1));
3341 TestLoadTimingNotReused(load_timing_info1, CONNECT_TIMING_HAS_DNS_TIMES);
3342
3343 const HttpResponseInfo* response = trans.GetResponseInfo();
3344 ASSERT_TRUE(response);
3345 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge));
3346
3347 TestCompletionCallback callback2;
3348
3349 rv = trans.RestartWithAuth(AuthCredentials(kFoo, kBar),
3350 callback2.callback());
3351 ASSERT_THAT(callback2.GetResult(rv), IsOk());
3352
3353 LoadTimingInfo load_timing_info2;
3354 EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info2));
3355 TestLoadTimingReused(load_timing_info2);
3356 // The load timing after restart should have the same socket ID, and times
3357 // those of the first load timing.
3358 EXPECT_LE(load_timing_info1.receive_headers_end,
3359 load_timing_info2.send_start);
3360 EXPECT_EQ(load_timing_info1.socket_log_id, load_timing_info2.socket_log_id);
3361
3362 response = trans.GetResponseInfo();
3363 ASSERT_TRUE(response);
3364 EXPECT_FALSE(response->auth_challenge.has_value());
3365 EXPECT_EQ(5, response->headers->GetContentLength());
3366
3367 std::string response_data;
3368 EXPECT_THAT(ReadTransaction(&trans, &response_data), IsOk());
3369
3370 int64_t writes_size = CountWriteBytes(data_writes);
3371 EXPECT_EQ(writes_size, trans.GetTotalSentBytes());
3372 int64_t reads_size = CountReadBytes(data_reads);
3373 EXPECT_EQ(reads_size, trans.GetTotalReceivedBytes());
3374 }
3375 }
3376
3377 // Test the request-challenge-retry sequence for basic auth, over a keep-alive
3378 // connection and with no response body to drain.
TEST_P(HttpNetworkTransactionTest,BasicAuthKeepAliveNoBody)3379 TEST_P(HttpNetworkTransactionTest, BasicAuthKeepAliveNoBody) {
3380 HttpRequestInfo request;
3381 request.method = "GET";
3382 request.url = GURL("http://www.example.org/");
3383 request.traffic_annotation =
3384 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
3385
3386 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
3387
3388 MockWrite data_writes1[] = {
3389 MockWrite("GET / HTTP/1.1\r\n"
3390 "Host: www.example.org\r\n"
3391 "Connection: keep-alive\r\n\r\n"),
3392
3393 // After calling trans.RestartWithAuth(), this is the request we should
3394 // be issuing -- the final header line contains the credentials.
3395 MockWrite("GET / HTTP/1.1\r\n"
3396 "Host: www.example.org\r\n"
3397 "Connection: keep-alive\r\n"
3398 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
3399 };
3400
3401 MockRead data_reads1[] = {
3402 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
3403 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
3404 MockRead("Content-Length: 0\r\n\r\n"), // No response body.
3405
3406 // Lastly, the server responds with the actual content.
3407 MockRead("HTTP/1.1 200 OK\r\n"),
3408 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3409 MockRead("Content-Length: 5\r\n\r\n"),
3410 MockRead("hello"),
3411 };
3412
3413 // An incorrect reconnect would cause this to be read.
3414 MockRead data_reads2[] = {
3415 MockRead(SYNCHRONOUS, ERR_FAILED),
3416 };
3417
3418 StaticSocketDataProvider data1(data_reads1, data_writes1);
3419 StaticSocketDataProvider data2(data_reads2, base::span<MockWrite>());
3420 session_deps_.socket_factory->AddSocketDataProvider(&data1);
3421 session_deps_.socket_factory->AddSocketDataProvider(&data2);
3422
3423 TestCompletionCallback callback1;
3424
3425 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
3426 int rv = trans.Start(&request, callback1.callback(), NetLogWithSource());
3427 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
3428
3429 rv = callback1.WaitForResult();
3430 EXPECT_THAT(rv, IsOk());
3431
3432 const HttpResponseInfo* response = trans.GetResponseInfo();
3433 ASSERT_TRUE(response);
3434 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge));
3435
3436 TestCompletionCallback callback2;
3437
3438 rv = trans.RestartWithAuth(AuthCredentials(kFoo, kBar), callback2.callback());
3439 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
3440
3441 rv = callback2.WaitForResult();
3442 EXPECT_THAT(rv, IsOk());
3443
3444 response = trans.GetResponseInfo();
3445 ASSERT_TRUE(response);
3446 EXPECT_FALSE(response->auth_challenge.has_value());
3447 EXPECT_EQ(5, response->headers->GetContentLength());
3448 }
3449
3450 // Test the request-challenge-retry sequence for basic auth, over a keep-alive
3451 // connection and with a large response body to drain.
TEST_P(HttpNetworkTransactionTest,BasicAuthKeepAliveLargeBody)3452 TEST_P(HttpNetworkTransactionTest, BasicAuthKeepAliveLargeBody) {
3453 HttpRequestInfo request;
3454 request.method = "GET";
3455 request.url = GURL("http://www.example.org/");
3456 request.traffic_annotation =
3457 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
3458
3459 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
3460
3461 MockWrite data_writes1[] = {
3462 MockWrite("GET / HTTP/1.1\r\n"
3463 "Host: www.example.org\r\n"
3464 "Connection: keep-alive\r\n\r\n"),
3465
3466 // After calling trans.RestartWithAuth(), this is the request we should
3467 // be issuing -- the final header line contains the credentials.
3468 MockWrite("GET / HTTP/1.1\r\n"
3469 "Host: www.example.org\r\n"
3470 "Connection: keep-alive\r\n"
3471 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
3472 };
3473
3474 // Respond with 5 kb of response body.
3475 std::string large_body_string("Unauthorized");
3476 large_body_string.append(5 * 1024, ' ');
3477 large_body_string.append("\r\n");
3478
3479 MockRead data_reads1[] = {
3480 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
3481 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
3482 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3483 // 5134 = 12 + 5 * 1024 + 2
3484 MockRead("Content-Length: 5134\r\n\r\n"),
3485 MockRead(ASYNC, large_body_string.data(), large_body_string.size()),
3486
3487 // Lastly, the server responds with the actual content.
3488 MockRead("HTTP/1.1 200 OK\r\n"),
3489 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3490 MockRead("Content-Length: 5\r\n\r\n"),
3491 MockRead("hello"),
3492 };
3493
3494 // An incorrect reconnect would cause this to be read.
3495 MockRead data_reads2[] = {
3496 MockRead(SYNCHRONOUS, ERR_FAILED),
3497 };
3498
3499 StaticSocketDataProvider data1(data_reads1, data_writes1);
3500 StaticSocketDataProvider data2(data_reads2, base::span<MockWrite>());
3501 session_deps_.socket_factory->AddSocketDataProvider(&data1);
3502 session_deps_.socket_factory->AddSocketDataProvider(&data2);
3503
3504 TestCompletionCallback callback1;
3505
3506 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
3507 int rv = trans.Start(&request, callback1.callback(), NetLogWithSource());
3508 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
3509
3510 rv = callback1.WaitForResult();
3511 EXPECT_THAT(rv, IsOk());
3512
3513 const HttpResponseInfo* response = trans.GetResponseInfo();
3514 ASSERT_TRUE(response);
3515 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge));
3516
3517 TestCompletionCallback callback2;
3518
3519 rv = trans.RestartWithAuth(AuthCredentials(kFoo, kBar), callback2.callback());
3520 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
3521
3522 rv = callback2.WaitForResult();
3523 EXPECT_THAT(rv, IsOk());
3524
3525 response = trans.GetResponseInfo();
3526 ASSERT_TRUE(response);
3527 EXPECT_FALSE(response->auth_challenge.has_value());
3528 EXPECT_EQ(5, response->headers->GetContentLength());
3529 }
3530
3531 // Test the request-challenge-retry sequence for basic auth, over a keep-alive
3532 // connection, but the server gets impatient and closes the connection.
TEST_P(HttpNetworkTransactionTest,BasicAuthKeepAliveImpatientServer)3533 TEST_P(HttpNetworkTransactionTest, BasicAuthKeepAliveImpatientServer) {
3534 HttpRequestInfo request;
3535 request.method = "GET";
3536 request.url = GURL("http://www.example.org/");
3537 request.traffic_annotation =
3538 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
3539
3540 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
3541
3542 MockWrite data_writes1[] = {
3543 MockWrite("GET / HTTP/1.1\r\n"
3544 "Host: www.example.org\r\n"
3545 "Connection: keep-alive\r\n\r\n"),
3546 // This simulates the seemingly successful write to a closed connection
3547 // if the bug is not fixed.
3548 MockWrite("GET / HTTP/1.1\r\n"
3549 "Host: www.example.org\r\n"
3550 "Connection: keep-alive\r\n"
3551 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
3552 };
3553
3554 MockRead data_reads1[] = {
3555 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
3556 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
3557 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3558 MockRead("Content-Length: 14\r\n\r\n"),
3559 // Tell MockTCPClientSocket to simulate the server closing the connection.
3560 MockRead(SYNCHRONOUS, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
3561 MockRead("Unauthorized\r\n"),
3562 MockRead(SYNCHRONOUS, OK), // The server closes the connection.
3563 };
3564
3565 // After calling trans.RestartWithAuth(), this is the request we should
3566 // be issuing -- the final header line contains the credentials.
3567 MockWrite data_writes2[] = {
3568 MockWrite("GET / HTTP/1.1\r\n"
3569 "Host: www.example.org\r\n"
3570 "Connection: keep-alive\r\n"
3571 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
3572 };
3573
3574 // Lastly, the server responds with the actual content.
3575 MockRead data_reads2[] = {
3576 MockRead("HTTP/1.1 200 OK\r\n"),
3577 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3578 MockRead("Content-Length: 5\r\n\r\n"),
3579 MockRead("hello"),
3580 };
3581
3582 StaticSocketDataProvider data1(data_reads1, data_writes1);
3583 StaticSocketDataProvider data2(data_reads2, data_writes2);
3584 session_deps_.socket_factory->AddSocketDataProvider(&data1);
3585 session_deps_.socket_factory->AddSocketDataProvider(&data2);
3586
3587 TestCompletionCallback callback1;
3588
3589 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
3590 int rv = trans.Start(&request, callback1.callback(), NetLogWithSource());
3591 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
3592
3593 rv = callback1.WaitForResult();
3594 EXPECT_THAT(rv, IsOk());
3595
3596 const HttpResponseInfo* response = trans.GetResponseInfo();
3597 ASSERT_TRUE(response);
3598 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge));
3599
3600 TestCompletionCallback callback2;
3601
3602 rv = trans.RestartWithAuth(AuthCredentials(kFoo, kBar), callback2.callback());
3603 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
3604
3605 rv = callback2.WaitForResult();
3606 EXPECT_THAT(rv, IsOk());
3607
3608 response = trans.GetResponseInfo();
3609 ASSERT_TRUE(response);
3610 EXPECT_FALSE(response->auth_challenge.has_value());
3611 EXPECT_EQ(5, response->headers->GetContentLength());
3612 }
3613
3614 // Test the request-challenge-retry sequence for basic auth, over a connection
3615 // that requires a restart when setting up an SSL tunnel.
TEST_P(HttpNetworkTransactionTest,BasicAuthProxyNoKeepAliveHttp10)3616 TEST_P(HttpNetworkTransactionTest, BasicAuthProxyNoKeepAliveHttp10) {
3617 HttpRequestInfo request;
3618 request.method = "GET";
3619 request.url = GURL("https://www.example.org/");
3620 // when the no authentication data flag is set.
3621 request.privacy_mode = PRIVACY_MODE_ENABLED;
3622 request.traffic_annotation =
3623 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
3624
3625 // Configure against proxy server "myproxy:70".
3626 session_deps_.proxy_resolution_service =
3627 ConfiguredProxyResolutionService::CreateFixedFromPacResultForTest(
3628 "PROXY myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
3629 RecordingNetLogObserver net_log_observer;
3630 NetLogWithSource net_log_with_source =
3631 NetLogWithSource::Make(NetLogSourceType::NONE);
3632 session_deps_.net_log = NetLog::Get();
3633 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
3634
3635 // Since we have proxy, should try to establish tunnel.
3636 MockWrite data_writes1[] = {
3637 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
3638 "Host: www.example.org:443\r\n"
3639 "Proxy-Connection: keep-alive\r\n\r\n"),
3640 };
3641
3642 // The proxy responds to the connect with a 407, using a non-persistent
3643 // connection.
3644 MockRead data_reads1[] = {
3645 // No credentials.
3646 MockRead("HTTP/1.0 407 Proxy Authentication Required\r\n"),
3647 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n\r\n"),
3648 };
3649
3650 // Since the first connection couldn't be reused, need to establish another
3651 // once given credentials.
3652 MockWrite data_writes2[] = {
3653 // After calling trans->RestartWithAuth(), this is the request we should
3654 // be issuing -- the final header line contains the credentials.
3655 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
3656 "Host: www.example.org:443\r\n"
3657 "Proxy-Connection: keep-alive\r\n"
3658 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
3659
3660 MockWrite("GET / HTTP/1.1\r\n"
3661 "Host: www.example.org\r\n"
3662 "Connection: keep-alive\r\n\r\n"),
3663 };
3664
3665 MockRead data_reads2[] = {
3666 MockRead("HTTP/1.0 200 Connection Established\r\n\r\n"),
3667
3668 MockRead("HTTP/1.1 200 OK\r\n"),
3669 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3670 MockRead("Content-Length: 5\r\n\r\n"),
3671 MockRead(SYNCHRONOUS, "hello"),
3672 };
3673
3674 StaticSocketDataProvider data1(data_reads1, data_writes1);
3675 session_deps_.socket_factory->AddSocketDataProvider(&data1);
3676 StaticSocketDataProvider data2(data_reads2, data_writes2);
3677 session_deps_.socket_factory->AddSocketDataProvider(&data2);
3678 SSLSocketDataProvider ssl(ASYNC, OK);
3679 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
3680
3681 TestCompletionCallback callback1;
3682 ConnectedHandler connected_handler;
3683
3684 auto trans =
3685 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
3686
3687 trans->SetConnectedCallback(connected_handler.Callback());
3688
3689 int rv = trans->Start(&request, callback1.callback(), net_log_with_source);
3690 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
3691
3692 rv = callback1.WaitForResult();
3693 EXPECT_THAT(rv, IsOk());
3694 auto entries = net_log_observer.GetEntries();
3695 size_t pos = ExpectLogContainsSomewhere(
3696 entries, 0, NetLogEventType::HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
3697 NetLogEventPhase::NONE);
3698 ExpectLogContainsSomewhere(
3699 entries, pos,
3700 NetLogEventType::HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
3701 NetLogEventPhase::NONE);
3702
3703 // TODO(crbug.com/986744): Fix handling of OnConnected() when proxy
3704 // authentication is required. We should notify the callback that a connection
3705 // was established, even though the stream might not be ready for us to send
3706 // data through it.
3707 EXPECT_THAT(connected_handler.transports(), IsEmpty());
3708
3709 const HttpResponseInfo* response = trans->GetResponseInfo();
3710 ASSERT_TRUE(response);
3711 EXPECT_FALSE(response->headers->IsKeepAlive());
3712 ASSERT_TRUE(response->headers);
3713 EXPECT_EQ(407, response->headers->response_code());
3714 EXPECT_TRUE(HttpVersion(1, 0) == response->headers->GetHttpVersion());
3715 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge));
3716
3717 LoadTimingInfo load_timing_info;
3718 // CONNECT requests and responses are handled at the connect job level, so
3719 // the transaction does not yet have a connection.
3720 EXPECT_FALSE(trans->GetLoadTimingInfo(&load_timing_info));
3721
3722 TestCompletionCallback callback2;
3723
3724 rv =
3725 trans->RestartWithAuth(AuthCredentials(kFoo, kBar), callback2.callback());
3726 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
3727
3728 rv = callback2.WaitForResult();
3729 EXPECT_THAT(rv, IsOk());
3730
3731 response = trans->GetResponseInfo();
3732 ASSERT_TRUE(response);
3733
3734 EXPECT_TRUE(response->headers->IsKeepAlive());
3735 EXPECT_EQ(200, response->headers->response_code());
3736 EXPECT_EQ(5, response->headers->GetContentLength());
3737 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
3738
3739 TransportInfo expected_transport;
3740 expected_transport.type = TransportType::kProxied;
3741 expected_transport.endpoint = IPEndPoint(IPAddress::IPv4Localhost(), 70);
3742 expected_transport.negotiated_protocol = kProtoUnknown;
3743 EXPECT_THAT(connected_handler.transports(), ElementsAre(expected_transport));
3744
3745 // Check that credentials were successfully cached, with the right target.
3746 HttpAuthCache::Entry* entry = session->http_auth_cache()->Lookup(
3747 url::SchemeHostPort(url::SchemeHostPort(GURL("http://myproxy:70"))),
3748 HttpAuth::AUTH_PROXY, "MyRealm1", HttpAuth::AUTH_SCHEME_BASIC,
3749 NetworkAnonymizationKey());
3750 ASSERT_TRUE(entry);
3751 ASSERT_EQ(kFoo, entry->credentials().username());
3752 ASSERT_EQ(kBar, entry->credentials().password());
3753
3754 // The password prompt info should not be set.
3755 EXPECT_FALSE(response->auth_challenge.has_value());
3756
3757 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
3758 TestLoadTimingNotReusedWithPac(load_timing_info,
3759 CONNECT_TIMING_HAS_SSL_TIMES);
3760
3761 trans.reset();
3762 session->CloseAllConnections(ERR_FAILED, "Very good reason");
3763 }
3764
3765 // Test the request-challenge-retry sequence for basic auth, over a connection
3766 // that requires a restart when setting up an SSL tunnel.
TEST_P(HttpNetworkTransactionTest,BasicAuthProxyNoKeepAliveHttp11)3767 TEST_P(HttpNetworkTransactionTest, BasicAuthProxyNoKeepAliveHttp11) {
3768 HttpRequestInfo request;
3769 request.method = "GET";
3770 request.url = GURL("https://www.example.org/");
3771 // when the no authentication data flag is set.
3772 request.privacy_mode = PRIVACY_MODE_ENABLED;
3773 request.traffic_annotation =
3774 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
3775
3776 // Configure against proxy server "myproxy:70".
3777 session_deps_.proxy_resolution_service =
3778 ConfiguredProxyResolutionService::CreateFixedFromPacResultForTest(
3779 "PROXY myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
3780 RecordingNetLogObserver net_log_observer;
3781 session_deps_.net_log = NetLog::Get();
3782 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
3783
3784 // Since we have proxy, should try to establish tunnel.
3785 MockWrite data_writes1[] = {
3786 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
3787 "Host: www.example.org:443\r\n"
3788 "Proxy-Connection: keep-alive\r\n\r\n"),
3789 };
3790
3791 // The proxy responds to the connect with a 407, using a non-persistent
3792 // connection.
3793 MockRead data_reads1[] = {
3794 // No credentials.
3795 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
3796 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
3797 MockRead("Proxy-Connection: close\r\n\r\n"),
3798 };
3799
3800 MockWrite data_writes2[] = {
3801 // After calling trans->RestartWithAuth(), this is the request we should
3802 // be issuing -- the final header line contains the credentials.
3803 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
3804 "Host: www.example.org:443\r\n"
3805 "Proxy-Connection: keep-alive\r\n"
3806 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
3807
3808 MockWrite("GET / HTTP/1.1\r\n"
3809 "Host: www.example.org\r\n"
3810 "Connection: keep-alive\r\n\r\n"),
3811 };
3812
3813 MockRead data_reads2[] = {
3814 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
3815
3816 MockRead("HTTP/1.1 200 OK\r\n"),
3817 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3818 MockRead("Content-Length: 5\r\n\r\n"),
3819 MockRead(SYNCHRONOUS, "hello"),
3820 };
3821
3822 StaticSocketDataProvider data1(data_reads1, data_writes1);
3823 session_deps_.socket_factory->AddSocketDataProvider(&data1);
3824 StaticSocketDataProvider data2(data_reads2, data_writes2);
3825 session_deps_.socket_factory->AddSocketDataProvider(&data2);
3826 SSLSocketDataProvider ssl(ASYNC, OK);
3827 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
3828
3829 ConnectedHandler connected_handler;
3830 TestCompletionCallback callback1;
3831
3832 auto trans =
3833 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
3834
3835 trans->SetConnectedCallback(connected_handler.Callback());
3836
3837 int rv = trans->Start(&request, callback1.callback(),
3838 NetLogWithSource::Make(NetLogSourceType::NONE));
3839 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
3840
3841 rv = callback1.WaitForResult();
3842 EXPECT_THAT(rv, IsOk());
3843 auto entries = net_log_observer.GetEntries();
3844 size_t pos = ExpectLogContainsSomewhere(
3845 entries, 0, NetLogEventType::HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
3846 NetLogEventPhase::NONE);
3847 ExpectLogContainsSomewhere(
3848 entries, pos,
3849 NetLogEventType::HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
3850 NetLogEventPhase::NONE);
3851
3852 const HttpResponseInfo* response = trans->GetResponseInfo();
3853 ASSERT_TRUE(response);
3854 EXPECT_FALSE(response->headers->IsKeepAlive());
3855 ASSERT_TRUE(response->headers);
3856 EXPECT_EQ(407, response->headers->response_code());
3857 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
3858 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge));
3859 EXPECT_EQ(PacResultElementToProxyChain("PROXY myproxy:70"),
3860 response->proxy_chain);
3861
3862 // TODO(crbug.com/986744): Fix handling of OnConnected() when proxy
3863 // authentication is required. We should notify the callback that a connection
3864 // was established, even though the stream might not be ready for us to send
3865 // data through it.
3866 EXPECT_THAT(connected_handler.transports(), IsEmpty());
3867
3868 LoadTimingInfo load_timing_info;
3869 // CONNECT requests and responses are handled at the connect job level, so
3870 // the transaction does not yet have a connection.
3871 EXPECT_FALSE(trans->GetLoadTimingInfo(&load_timing_info));
3872
3873 TestCompletionCallback callback2;
3874
3875 rv =
3876 trans->RestartWithAuth(AuthCredentials(kFoo, kBar), callback2.callback());
3877 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
3878
3879 rv = callback2.WaitForResult();
3880 EXPECT_THAT(rv, IsOk());
3881
3882 response = trans->GetResponseInfo();
3883 ASSERT_TRUE(response);
3884
3885 EXPECT_TRUE(response->headers->IsKeepAlive());
3886 EXPECT_EQ(200, response->headers->response_code());
3887 EXPECT_EQ(5, response->headers->GetContentLength());
3888 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
3889 EXPECT_EQ(PacResultElementToProxyChain("PROXY myproxy:70"),
3890 response->proxy_chain);
3891
3892 TransportInfo expected_transport;
3893 expected_transport.type = TransportType::kProxied;
3894 expected_transport.endpoint = IPEndPoint(IPAddress::IPv4Localhost(), 70);
3895 expected_transport.negotiated_protocol = kProtoUnknown;
3896 EXPECT_THAT(connected_handler.transports(), ElementsAre(expected_transport));
3897
3898 // The password prompt info should not be set.
3899 EXPECT_FALSE(response->auth_challenge.has_value());
3900
3901 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
3902 TestLoadTimingNotReusedWithPac(load_timing_info,
3903 CONNECT_TIMING_HAS_SSL_TIMES);
3904
3905 trans.reset();
3906 session->CloseAllConnections(ERR_FAILED, "Very good reason");
3907 }
3908
3909 // Test the request-challenge-retry sequence for basic auth, over a keep-alive
3910 // proxy connection with HTTP/1.0 responses, when setting up an SSL tunnel.
TEST_P(HttpNetworkTransactionTest,BasicAuthProxyKeepAliveHttp10)3911 TEST_P(HttpNetworkTransactionTest, BasicAuthProxyKeepAliveHttp10) {
3912 // On the second pass, the body read of the auth challenge is synchronous, so
3913 // IsConnectedAndIdle returns false. The socket should still be drained and
3914 // reused. See http://crbug.com/544255.
3915 for (int i = 0; i < 2; ++i) {
3916 HttpRequestInfo request;
3917 request.method = "GET";
3918 request.url = GURL("https://www.example.org/");
3919 // Ensure that proxy authentication is attempted even
3920 // when the no authentication data flag is set.
3921 request.privacy_mode = PRIVACY_MODE_ENABLED;
3922 request.traffic_annotation =
3923 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
3924
3925 // Configure against proxy server "myproxy:70".
3926 session_deps_.proxy_resolution_service =
3927 ConfiguredProxyResolutionService::CreateFixedForTest(
3928 "myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
3929 RecordingNetLogObserver net_log_observer;
3930 session_deps_.net_log = NetLog::Get();
3931 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
3932
3933 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
3934
3935 // Since we have proxy, should try to establish tunnel.
3936 MockWrite data_writes1[] = {
3937 MockWrite(ASYNC, 0,
3938 "CONNECT www.example.org:443 HTTP/1.1\r\n"
3939 "Host: www.example.org:443\r\n"
3940 "Proxy-Connection: keep-alive\r\n\r\n"),
3941
3942 // After calling trans.RestartWithAuth(), this is the request we should
3943 // be issuing -- the final header line contains the credentials.
3944 MockWrite(ASYNC, 3,
3945 "CONNECT www.example.org:443 HTTP/1.1\r\n"
3946 "Host: www.example.org:443\r\n"
3947 "Proxy-Connection: keep-alive\r\n"
3948 "Proxy-Authorization: Basic Zm9vOmJheg==\r\n\r\n"),
3949 };
3950
3951 // The proxy responds to the connect with a 407, using a persistent
3952 // connection. (Since it's HTTP/1.0, keep-alive has to be explicit.)
3953 MockRead data_reads1[] = {
3954 // No credentials.
3955 MockRead(ASYNC, 1,
3956 "HTTP/1.0 407 Proxy Authentication Required\r\n"
3957 "Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"
3958 "Proxy-Connection: keep-alive\r\n"
3959 "Content-Length: 10\r\n\r\n"),
3960 MockRead(i == 0 ? ASYNC : SYNCHRONOUS, 2, "0123456789"),
3961
3962 // Wrong credentials (wrong password).
3963 MockRead(ASYNC, 4,
3964 "HTTP/1.0 407 Proxy Authentication Required\r\n"
3965 "Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"
3966 "Proxy-Connection: keep-alive\r\n"
3967 "Content-Length: 10\r\n\r\n"),
3968 // No response body because the test stops reading here.
3969 MockRead(SYNCHRONOUS, ERR_UNEXPECTED, 5),
3970 };
3971
3972 SequencedSocketData data1(data_reads1, data_writes1);
3973 data1.set_busy_before_sync_reads(true);
3974 session_deps_.socket_factory->AddSocketDataProvider(&data1);
3975
3976 TestCompletionCallback callback1;
3977
3978 int rv = trans.Start(&request, callback1.callback(),
3979 NetLogWithSource::Make(NetLogSourceType::NONE));
3980 EXPECT_THAT(callback1.GetResult(rv), IsOk());
3981
3982 auto entries = net_log_observer.GetEntries();
3983 size_t pos = ExpectLogContainsSomewhere(
3984 entries, 0, NetLogEventType::HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
3985 NetLogEventPhase::NONE);
3986 ExpectLogContainsSomewhere(
3987 entries, pos,
3988 NetLogEventType::HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
3989 NetLogEventPhase::NONE);
3990
3991 const HttpResponseInfo* response = trans.GetResponseInfo();
3992 ASSERT_TRUE(response);
3993 ASSERT_TRUE(response->headers);
3994 EXPECT_TRUE(response->headers->IsKeepAlive());
3995 EXPECT_EQ(407, response->headers->response_code());
3996 EXPECT_EQ(10, response->headers->GetContentLength());
3997 EXPECT_TRUE(HttpVersion(1, 0) == response->headers->GetHttpVersion());
3998 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge));
3999
4000 TestCompletionCallback callback2;
4001
4002 // Wrong password (should be "bar").
4003 rv = trans.RestartWithAuth(AuthCredentials(kFoo, kBaz),
4004 callback2.callback());
4005 EXPECT_THAT(callback2.GetResult(rv), IsOk());
4006
4007 response = trans.GetResponseInfo();
4008 ASSERT_TRUE(response);
4009 ASSERT_TRUE(response->headers);
4010 EXPECT_TRUE(response->headers->IsKeepAlive());
4011 EXPECT_EQ(407, response->headers->response_code());
4012 EXPECT_EQ(10, response->headers->GetContentLength());
4013 EXPECT_TRUE(HttpVersion(1, 0) == response->headers->GetHttpVersion());
4014 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge));
4015
4016 // Flush the idle socket before the NetLog and HttpNetworkTransaction go
4017 // out of scope.
4018 session->CloseAllConnections(ERR_FAILED, "Very good reason");
4019 }
4020 }
4021
4022 // Test the request-challenge-retry sequence for basic auth, over a keep-alive
4023 // proxy connection with HTTP/1.1 responses, when setting up an SSL tunnel.
TEST_P(HttpNetworkTransactionTest,BasicAuthProxyKeepAliveHttp11)4024 TEST_P(HttpNetworkTransactionTest, BasicAuthProxyKeepAliveHttp11) {
4025 // On the second pass, the body read of the auth challenge is synchronous, so
4026 // IsConnectedAndIdle returns false. The socket should still be drained and
4027 // reused. See http://crbug.com/544255.
4028 for (int i = 0; i < 2; ++i) {
4029 HttpRequestInfo request;
4030 request.method = "GET";
4031 request.url = GURL("https://www.example.org/");
4032 // Ensure that proxy authentication is attempted even
4033 // when the no authentication data flag is set.
4034 request.privacy_mode = PRIVACY_MODE_ENABLED;
4035 request.traffic_annotation =
4036 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
4037
4038 // Configure against proxy server "myproxy:70".
4039 session_deps_.proxy_resolution_service =
4040 ConfiguredProxyResolutionService::CreateFixedForTest(
4041 "myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
4042 RecordingNetLogObserver net_log_observer;
4043 session_deps_.net_log = NetLog::Get();
4044 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
4045
4046 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
4047
4048 // Since we have proxy, should try to establish tunnel.
4049 MockWrite data_writes1[] = {
4050 MockWrite(ASYNC, 0,
4051 "CONNECT www.example.org:443 HTTP/1.1\r\n"
4052 "Host: www.example.org:443\r\n"
4053 "Proxy-Connection: keep-alive\r\n\r\n"),
4054
4055 // After calling trans.RestartWithAuth(), this is the request we should
4056 // be issuing -- the final header line contains the credentials.
4057 MockWrite(ASYNC, 3,
4058 "CONNECT www.example.org:443 HTTP/1.1\r\n"
4059 "Host: www.example.org:443\r\n"
4060 "Proxy-Connection: keep-alive\r\n"
4061 "Proxy-Authorization: Basic Zm9vOmJheg==\r\n\r\n"),
4062 };
4063
4064 // The proxy responds to the connect with a 407, using a persistent
4065 // connection. (Since it's HTTP/1.0, keep-alive has to be explicit.)
4066 MockRead data_reads1[] = {
4067 // No credentials.
4068 MockRead(ASYNC, 1,
4069 "HTTP/1.1 407 Proxy Authentication Required\r\n"
4070 "Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"
4071 "Content-Length: 10\r\n\r\n"),
4072 MockRead(i == 0 ? ASYNC : SYNCHRONOUS, 2, "0123456789"),
4073
4074 // Wrong credentials (wrong password).
4075 MockRead(ASYNC, 4,
4076 "HTTP/1.1 407 Proxy Authentication Required\r\n"
4077 "Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"
4078 "Content-Length: 10\r\n\r\n"),
4079 // No response body because the test stops reading here.
4080 MockRead(SYNCHRONOUS, ERR_UNEXPECTED, 5),
4081 };
4082
4083 SequencedSocketData data1(data_reads1, data_writes1);
4084 data1.set_busy_before_sync_reads(true);
4085 session_deps_.socket_factory->AddSocketDataProvider(&data1);
4086
4087 TestCompletionCallback callback1;
4088
4089 int rv = trans.Start(&request, callback1.callback(),
4090 NetLogWithSource::Make(NetLogSourceType::NONE));
4091 EXPECT_THAT(callback1.GetResult(rv), IsOk());
4092
4093 auto entries = net_log_observer.GetEntries();
4094 size_t pos = ExpectLogContainsSomewhere(
4095 entries, 0, NetLogEventType::HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
4096 NetLogEventPhase::NONE);
4097 ExpectLogContainsSomewhere(
4098 entries, pos,
4099 NetLogEventType::HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
4100 NetLogEventPhase::NONE);
4101
4102 const HttpResponseInfo* response = trans.GetResponseInfo();
4103 ASSERT_TRUE(response);
4104 ASSERT_TRUE(response->headers);
4105 EXPECT_TRUE(response->headers->IsKeepAlive());
4106 EXPECT_EQ(407, response->headers->response_code());
4107 EXPECT_EQ(10, response->headers->GetContentLength());
4108 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
4109 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge));
4110 EXPECT_FALSE(response->did_use_http_auth);
4111 EXPECT_EQ(PacResultElementToProxyChain("PROXY myproxy:70"),
4112 response->proxy_chain);
4113
4114 TestCompletionCallback callback2;
4115
4116 // Wrong password (should be "bar").
4117 rv = trans.RestartWithAuth(AuthCredentials(kFoo, kBaz),
4118 callback2.callback());
4119 EXPECT_THAT(callback2.GetResult(rv), IsOk());
4120
4121 response = trans.GetResponseInfo();
4122 ASSERT_TRUE(response);
4123 ASSERT_TRUE(response->headers);
4124 EXPECT_TRUE(response->headers->IsKeepAlive());
4125 EXPECT_EQ(407, response->headers->response_code());
4126 EXPECT_EQ(10, response->headers->GetContentLength());
4127 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
4128 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge));
4129 EXPECT_TRUE(response->did_use_http_auth);
4130 EXPECT_EQ(PacResultElementToProxyChain("PROXY myproxy:70"),
4131 response->proxy_chain);
4132
4133 // Flush the idle socket before the NetLog and HttpNetworkTransaction go
4134 // out of scope.
4135 session->CloseAllConnections(ERR_FAILED, "Very good reason");
4136 }
4137 }
4138
4139 // Test the request-challenge-retry sequence for basic auth, over a keep-alive
4140 // proxy connection with HTTP/1.1 responses, when setting up an SSL tunnel, in
4141 // the case the server sends extra data on the original socket, so it can't be
4142 // reused.
TEST_P(HttpNetworkTransactionTest,BasicAuthProxyKeepAliveExtraData)4143 TEST_P(HttpNetworkTransactionTest, BasicAuthProxyKeepAliveExtraData) {
4144 HttpRequestInfo request;
4145 request.method = "GET";
4146 request.url = GURL("https://www.example.org/");
4147 // when the no authentication data flag is set.
4148 request.privacy_mode = PRIVACY_MODE_ENABLED;
4149 request.traffic_annotation =
4150 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
4151
4152 // Configure against proxy server "myproxy:70".
4153 session_deps_.proxy_resolution_service =
4154 ConfiguredProxyResolutionService::CreateFixedFromPacResultForTest(
4155 "PROXY myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
4156 RecordingNetLogObserver net_log_observer;
4157 session_deps_.net_log = NetLog::Get();
4158 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
4159
4160 // Since we have proxy, should try to establish tunnel.
4161 MockWrite data_writes1[] = {
4162 MockWrite(ASYNC, 0,
4163 "CONNECT www.example.org:443 HTTP/1.1\r\n"
4164 "Host: www.example.org:443\r\n"
4165 "Proxy-Connection: keep-alive\r\n\r\n"),
4166 };
4167
4168 // The proxy responds to the connect with a 407, using a persistent, but sends
4169 // extra data, so the socket cannot be reused.
4170 MockRead data_reads1[] = {
4171 // No credentials.
4172 MockRead(ASYNC, 1,
4173 "HTTP/1.1 407 Proxy Authentication Required\r\n"
4174 "Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"
4175 "Content-Length: 10\r\n\r\n"),
4176 MockRead(SYNCHRONOUS, 2, "0123456789"),
4177 MockRead(SYNCHRONOUS, 3, "I'm broken!"),
4178 };
4179
4180 MockWrite data_writes2[] = {
4181 // After calling trans->RestartWithAuth(), this is the request we should
4182 // be issuing -- the final header line contains the credentials.
4183 MockWrite(ASYNC, 0,
4184 "CONNECT www.example.org:443 HTTP/1.1\r\n"
4185 "Host: www.example.org:443\r\n"
4186 "Proxy-Connection: keep-alive\r\n"
4187 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
4188
4189 MockWrite(ASYNC, 2,
4190 "GET / HTTP/1.1\r\n"
4191 "Host: www.example.org\r\n"
4192 "Connection: keep-alive\r\n\r\n"),
4193 };
4194
4195 MockRead data_reads2[] = {
4196 MockRead(ASYNC, 1, "HTTP/1.1 200 Connection Established\r\n\r\n"),
4197
4198 MockRead(ASYNC, 3,
4199 "HTTP/1.1 200 OK\r\n"
4200 "Content-Type: text/html; charset=iso-8859-1\r\n"
4201 "Content-Length: 5\r\n\r\n"),
4202 // No response body because the test stops reading here.
4203 MockRead(SYNCHRONOUS, ERR_UNEXPECTED, 4),
4204 };
4205
4206 SequencedSocketData data1(data_reads1, data_writes1);
4207 data1.set_busy_before_sync_reads(true);
4208 session_deps_.socket_factory->AddSocketDataProvider(&data1);
4209 SequencedSocketData data2(data_reads2, data_writes2);
4210 session_deps_.socket_factory->AddSocketDataProvider(&data2);
4211 SSLSocketDataProvider ssl(ASYNC, OK);
4212 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
4213
4214 TestCompletionCallback callback1;
4215
4216 auto trans =
4217 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
4218
4219 int rv = trans->Start(&request, callback1.callback(),
4220 NetLogWithSource::Make(NetLogSourceType::NONE));
4221 EXPECT_THAT(callback1.GetResult(rv), IsOk());
4222
4223 auto entries = net_log_observer.GetEntries();
4224 size_t pos = ExpectLogContainsSomewhere(
4225 entries, 0, NetLogEventType::HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
4226 NetLogEventPhase::NONE);
4227 ExpectLogContainsSomewhere(
4228 entries, pos,
4229 NetLogEventType::HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
4230 NetLogEventPhase::NONE);
4231
4232 const HttpResponseInfo* response = trans->GetResponseInfo();
4233 ASSERT_TRUE(response);
4234 ASSERT_TRUE(response->headers);
4235 EXPECT_TRUE(response->headers->IsKeepAlive());
4236 EXPECT_EQ(407, response->headers->response_code());
4237 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
4238 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge));
4239
4240 LoadTimingInfo load_timing_info;
4241 // CONNECT requests and responses are handled at the connect job level, so
4242 // the transaction does not yet have a connection.
4243 EXPECT_FALSE(trans->GetLoadTimingInfo(&load_timing_info));
4244
4245 TestCompletionCallback callback2;
4246
4247 rv =
4248 trans->RestartWithAuth(AuthCredentials(kFoo, kBar), callback2.callback());
4249 EXPECT_THAT(callback2.GetResult(rv), IsOk());
4250
4251 EXPECT_TRUE(response->headers->IsKeepAlive());
4252 EXPECT_EQ(200, response->headers->response_code());
4253 EXPECT_EQ(5, response->headers->GetContentLength());
4254 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
4255
4256 // The password prompt info should not be set.
4257 EXPECT_FALSE(response->auth_challenge.has_value());
4258
4259 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
4260 TestLoadTimingNotReusedWithPac(load_timing_info,
4261 CONNECT_TIMING_HAS_SSL_TIMES);
4262
4263 trans.reset();
4264 session->CloseAllConnections(ERR_FAILED, "Very good reason");
4265 }
4266
4267 // Test the case a proxy closes a socket while the challenge body is being
4268 // drained.
TEST_P(HttpNetworkTransactionTest,BasicAuthProxyKeepAliveHangupDuringBody)4269 TEST_P(HttpNetworkTransactionTest, BasicAuthProxyKeepAliveHangupDuringBody) {
4270 HttpRequestInfo request;
4271 request.method = "GET";
4272 request.url = GURL("https://www.example.org/");
4273 // Ensure that proxy authentication is attempted even
4274 // when the no authentication data flag is set.
4275 request.privacy_mode = PRIVACY_MODE_ENABLED;
4276 request.traffic_annotation =
4277 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
4278
4279 // Configure against proxy server "myproxy:70".
4280 session_deps_.proxy_resolution_service =
4281 ConfiguredProxyResolutionService::CreateFixedForTest(
4282 "myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
4283 std::unique_ptr<HttpNetworkSession> session = CreateSession(&session_deps_);
4284
4285 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
4286
4287 // Since we have proxy, should try to establish tunnel.
4288 MockWrite data_writes1[] = {
4289 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
4290 "Host: www.example.org:443\r\n"
4291 "Proxy-Connection: keep-alive\r\n\r\n"),
4292 };
4293
4294 // The proxy responds to the connect with a 407, using a persistent
4295 // connection.
4296 MockRead data_reads1[] = {
4297 // No credentials.
4298 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
4299 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
4300 MockRead("Content-Length: 10\r\n\r\n"),
4301 MockRead("spam!"),
4302 // Server hands up in the middle of the body.
4303 MockRead(ASYNC, ERR_CONNECTION_CLOSED),
4304 };
4305
4306 MockWrite data_writes2[] = {
4307 // After calling trans.RestartWithAuth(), this is the request we should
4308 // be issuing -- the final header line contains the credentials.
4309 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
4310 "Host: www.example.org:443\r\n"
4311 "Proxy-Connection: keep-alive\r\n"
4312 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
4313
4314 MockWrite("GET / HTTP/1.1\r\n"
4315 "Host: www.example.org\r\n"
4316 "Connection: keep-alive\r\n\r\n"),
4317 };
4318
4319 MockRead data_reads2[] = {
4320 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
4321
4322 MockRead("HTTP/1.1 200 OK\r\n"),
4323 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
4324 MockRead("Content-Length: 5\r\n\r\n"),
4325 MockRead(SYNCHRONOUS, "hello"),
4326 };
4327
4328 StaticSocketDataProvider data1(data_reads1, data_writes1);
4329 session_deps_.socket_factory->AddSocketDataProvider(&data1);
4330 StaticSocketDataProvider data2(data_reads2, data_writes2);
4331 session_deps_.socket_factory->AddSocketDataProvider(&data2);
4332 SSLSocketDataProvider ssl(ASYNC, OK);
4333 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
4334
4335 TestCompletionCallback callback;
4336
4337 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
4338 EXPECT_THAT(callback.GetResult(rv), IsOk());
4339
4340 const HttpResponseInfo* response = trans.GetResponseInfo();
4341 ASSERT_TRUE(response);
4342 ASSERT_TRUE(response->headers);
4343 EXPECT_TRUE(response->headers->IsKeepAlive());
4344 EXPECT_EQ(407, response->headers->response_code());
4345 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge));
4346
4347 rv = trans.RestartWithAuth(AuthCredentials(kFoo, kBar), callback.callback());
4348 EXPECT_THAT(callback.GetResult(rv), IsOk());
4349
4350 response = trans.GetResponseInfo();
4351 ASSERT_TRUE(response);
4352 ASSERT_TRUE(response->headers);
4353 EXPECT_TRUE(response->headers->IsKeepAlive());
4354 EXPECT_EQ(200, response->headers->response_code());
4355 std::string body;
4356 EXPECT_THAT(ReadTransaction(&trans, &body), IsOk());
4357 EXPECT_EQ("hello", body);
4358 }
4359
4360 // Test that we don't read the response body when we fail to establish a tunnel,
4361 // even if the user cancels the proxy's auth attempt.
TEST_P(HttpNetworkTransactionTest,BasicAuthProxyCancelTunnel)4362 TEST_P(HttpNetworkTransactionTest, BasicAuthProxyCancelTunnel) {
4363 HttpRequestInfo request;
4364 request.method = "GET";
4365 request.url = GURL("https://www.example.org/");
4366 request.traffic_annotation =
4367 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
4368
4369 // Configure against proxy server "myproxy:70".
4370 session_deps_.proxy_resolution_service =
4371 ConfiguredProxyResolutionService::CreateFixedForTest(
4372 "myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
4373
4374 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
4375
4376 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
4377
4378 // Since we have proxy, should try to establish tunnel.
4379 MockWrite data_writes[] = {
4380 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
4381 "Host: www.example.org:443\r\n"
4382 "Proxy-Connection: keep-alive\r\n\r\n"),
4383 };
4384
4385 // The proxy responds to the connect with a 407.
4386 MockRead data_reads[] = {
4387 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
4388 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
4389 MockRead("Content-Length: 10\r\n\r\n"),
4390 MockRead("0123456789"),
4391 MockRead(SYNCHRONOUS, ERR_UNEXPECTED),
4392 };
4393
4394 StaticSocketDataProvider data(data_reads, data_writes);
4395 session_deps_.socket_factory->AddSocketDataProvider(&data);
4396
4397 TestCompletionCallback callback;
4398
4399 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
4400 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
4401
4402 rv = callback.WaitForResult();
4403 EXPECT_THAT(rv, IsOk());
4404
4405 const HttpResponseInfo* response = trans.GetResponseInfo();
4406 ASSERT_TRUE(response);
4407 ASSERT_TRUE(response->headers);
4408 EXPECT_TRUE(response->headers->IsKeepAlive());
4409 EXPECT_EQ(407, response->headers->response_code());
4410 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
4411
4412 std::string response_data;
4413 rv = ReadTransaction(&trans, &response_data);
4414 EXPECT_THAT(rv, IsError(ERR_TUNNEL_CONNECTION_FAILED));
4415
4416 // Flush the idle socket before the HttpNetworkTransaction goes out of scope.
4417 session->CloseAllConnections(ERR_FAILED, "Very good reason");
4418 }
4419
4420 // Test the no-tunnel HTTP auth case where proxy and server origins and realms
4421 // are the same, but the user/passwords are different. Serves to verify
4422 // credentials are correctly separated based on HttpAuth::Target.
TEST_P(HttpNetworkTransactionTest,BasicAuthProxyMatchesServerAuthNoTunnel)4423 TEST_P(HttpNetworkTransactionTest, BasicAuthProxyMatchesServerAuthNoTunnel) {
4424 HttpRequestInfo request;
4425 request.method = "GET";
4426 request.url = GURL("http://myproxy:70/");
4427 request.traffic_annotation =
4428 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
4429
4430 // Proxy matches request URL.
4431 session_deps_.proxy_resolution_service =
4432 ConfiguredProxyResolutionService::CreateFixedFromPacResultForTest(
4433 "PROXY myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
4434 NetLogWithSource net_log_with_source =
4435 NetLogWithSource::Make(NetLogSourceType::NONE);
4436 session_deps_.net_log = NetLog::Get();
4437 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
4438
4439 MockWrite data_writes[] = {
4440 // Initial request gets a proxy auth challenge.
4441 MockWrite("GET http://myproxy:70/ HTTP/1.1\r\n"
4442 "Host: myproxy:70\r\n"
4443 "Proxy-Connection: keep-alive\r\n\r\n"),
4444 // Retry with proxy auth credentials, which will result in a server auth
4445 // challenge.
4446 MockWrite("GET http://myproxy:70/ HTTP/1.1\r\n"
4447 "Host: myproxy:70\r\n"
4448 "Proxy-Connection: keep-alive\r\n"
4449 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
4450 // Retry with proxy and server auth credentials, which gets a response.
4451 MockWrite("GET http://myproxy:70/ HTTP/1.1\r\n"
4452 "Host: myproxy:70\r\n"
4453 "Proxy-Connection: keep-alive\r\n"
4454 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n"
4455 "Authorization: Basic Zm9vMjpiYXIy\r\n\r\n"),
4456 // A second request should preemptively send the correct proxy and server
4457 // auth headers.
4458 MockWrite("GET http://myproxy:70/ HTTP/1.1\r\n"
4459 "Host: myproxy:70\r\n"
4460 "Proxy-Connection: keep-alive\r\n"
4461 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n"
4462 "Authorization: Basic Zm9vMjpiYXIy\r\n\r\n"),
4463 };
4464
4465 MockRead data_reads[] = {
4466 // Proxy auth challenge.
4467 MockRead("HTTP/1.0 407 Proxy Authentication Required\r\n"
4468 "Proxy-Connection: keep-alive\r\n"
4469 "Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"
4470 "Content-Length: 0\r\n\r\n"),
4471 // Server auth challenge.
4472 MockRead("HTTP/1.0 401 Authentication Required\r\n"
4473 "Proxy-Connection: keep-alive\r\n"
4474 "WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"
4475 "Content-Length: 0\r\n\r\n"),
4476 // Response.
4477 MockRead("HTTP/1.1 200 OK\r\n"
4478 "Proxy-Connection: keep-alive\r\n"
4479 "Content-Length: 5\r\n\r\n"
4480 "hello"),
4481 // Response to second request.
4482 MockRead("HTTP/1.1 200 OK\r\n"
4483 "Proxy-Connection: keep-alive\r\n"
4484 "Content-Length: 2\r\n\r\n"
4485 "hi"),
4486 };
4487
4488 StaticSocketDataProvider data(data_reads, data_writes);
4489 session_deps_.socket_factory->AddSocketDataProvider(&data);
4490
4491 TestCompletionCallback callback;
4492
4493 auto trans =
4494 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
4495 int rv = trans->Start(&request, callback.callback(), net_log_with_source);
4496 EXPECT_THAT(callback.GetResult(rv), IsOk());
4497 const HttpResponseInfo* response = trans->GetResponseInfo();
4498 ASSERT_TRUE(response);
4499 ASSERT_TRUE(response->headers);
4500 EXPECT_EQ(407, response->headers->response_code());
4501 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge));
4502
4503 rv = trans->RestartWithAuth(AuthCredentials(kFoo, kBar), callback.callback());
4504 EXPECT_THAT(callback.GetResult(rv), IsOk());
4505 response = trans->GetResponseInfo();
4506 ASSERT_TRUE(response);
4507 EXPECT_EQ(401, response->headers->response_code());
4508 EXPECT_FALSE(response->auth_challenge->is_proxy);
4509 EXPECT_EQ("http://myproxy:70",
4510 response->auth_challenge->challenger.Serialize());
4511 EXPECT_EQ("MyRealm1", response->auth_challenge->realm);
4512 EXPECT_EQ(kBasicAuthScheme, response->auth_challenge->scheme);
4513
4514 rv = trans->RestartWithAuth(AuthCredentials(kFoo2, kBar2),
4515 callback.callback());
4516 EXPECT_THAT(callback.GetResult(rv), IsOk());
4517 response = trans->GetResponseInfo();
4518 ASSERT_TRUE(response);
4519 EXPECT_EQ(200, response->headers->response_code());
4520 // The password prompt info should not be set.
4521 EXPECT_FALSE(response->auth_challenge.has_value());
4522
4523 std::string response_data;
4524 EXPECT_THAT(ReadTransaction(trans.get(), &response_data), IsOk());
4525 EXPECT_EQ("hello", response_data);
4526
4527 // Check that the credentials were cached correctly.
4528 HttpAuthCache::Entry* entry = session->http_auth_cache()->Lookup(
4529 url::SchemeHostPort(url::SchemeHostPort(GURL("http://myproxy:70"))),
4530 HttpAuth::AUTH_PROXY, "MyRealm1", HttpAuth::AUTH_SCHEME_BASIC,
4531 NetworkAnonymizationKey());
4532 ASSERT_TRUE(entry);
4533 ASSERT_EQ(kFoo, entry->credentials().username());
4534 ASSERT_EQ(kBar, entry->credentials().password());
4535 entry = session->http_auth_cache()->Lookup(
4536 url::SchemeHostPort(url::SchemeHostPort(GURL("http://myproxy:70"))),
4537 HttpAuth::AUTH_SERVER, "MyRealm1", HttpAuth::AUTH_SCHEME_BASIC,
4538 NetworkAnonymizationKey());
4539 ASSERT_TRUE(entry);
4540 ASSERT_EQ(kFoo2, entry->credentials().username());
4541 ASSERT_EQ(kBar2, entry->credentials().password());
4542
4543 // Make another request, which should automatically send the correct proxy and
4544 // server auth credentials and get another response.
4545 trans =
4546 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
4547 rv = trans->Start(&request, callback.callback(), net_log_with_source);
4548 EXPECT_THAT(callback.GetResult(rv), IsOk());
4549 response = trans->GetResponseInfo();
4550 ASSERT_TRUE(response);
4551 EXPECT_EQ(200, response->headers->response_code());
4552 // The password prompt info should not be set.
4553 EXPECT_FALSE(response->auth_challenge.has_value());
4554
4555 EXPECT_THAT(ReadTransaction(trans.get(), &response_data), IsOk());
4556 EXPECT_EQ("hi", response_data);
4557
4558 trans.reset();
4559 session->CloseAllConnections(ERR_FAILED, "Very good reason");
4560 }
4561
4562 // Test the no-tunnel HTTP auth case where proxy and server origins and realms
4563 // are the same, but the user/passwords are different, and with different
4564 // NetworkAnonymizationKeys. Sends one request with a NAK, response to both
4565 // proxy and auth challenges, sends another request with another NAK, expecting
4566 // only the proxy credentials to be cached, and thus sees only a server auth
4567 // challenge. Then sends a request with the original NAK, expecting cached proxy
4568 // and auth credentials that match the ones used in the first request.
4569 //
4570 // Serves to verify credentials are correctly separated based on
4571 // HttpAuth::Target and NetworkAnonymizationKeys, but NetworkAnonymizationKey
4572 // only affects server credentials, not proxy credentials.
TEST_P(HttpNetworkTransactionTest,BasicAuthProxyMatchesServerAuthWithNetworkAnonymizationKeyNoTunnel)4573 TEST_P(HttpNetworkTransactionTest,
4574 BasicAuthProxyMatchesServerAuthWithNetworkAnonymizationKeyNoTunnel) {
4575 const SchemefulSite kSite1(GURL("https://foo.test/"));
4576 const auto kNetworkAnonymizationKey1 =
4577 net::NetworkAnonymizationKey::CreateSameSite(kSite1);
4578 const net::NetworkIsolationKey kNetworkIsolationKey1(kSite1, kSite1);
4579 const SchemefulSite kSite2(GURL("https://bar.test/"));
4580 const auto kNetworkAnonymizationKey2 =
4581 net::NetworkAnonymizationKey::CreateSameSite(kSite2);
4582 const net::NetworkIsolationKey kNetworkIsolationKey2(kSite2, kSite2);
4583
4584 // This test would need to use a single socket without this option enabled.
4585 // Best to use this option when it would affect a test, as it will eventually
4586 // become the default behavior.
4587 base::test::ScopedFeatureList feature_list;
4588 feature_list.InitAndEnableFeature(
4589 features::kPartitionConnectionsByNetworkIsolationKey);
4590
4591 // Proxy matches request URL.
4592 session_deps_.proxy_resolution_service =
4593 ConfiguredProxyResolutionService::CreateFixedFromPacResultForTest(
4594 "PROXY myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
4595 NetLogWithSource net_log_with_source =
4596 NetLogWithSource::Make(NetLogSourceType::NONE);
4597
4598 session_deps_.net_log = NetLog::Get();
4599 session_deps_.key_auth_cache_server_entries_by_network_anonymization_key =
4600 true;
4601 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
4602
4603 MockWrite data_writes[] = {
4604 // Initial request gets a proxy auth challenge.
4605 MockWrite("GET http://myproxy:70/ HTTP/1.1\r\n"
4606 "Host: myproxy:70\r\n"
4607 "Proxy-Connection: keep-alive\r\n\r\n"),
4608 // Retry with proxy auth credentials, which will result in a server auth
4609 // challenge.
4610 MockWrite("GET http://myproxy:70/ HTTP/1.1\r\n"
4611 "Host: myproxy:70\r\n"
4612 "Proxy-Connection: keep-alive\r\n"
4613 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
4614 // Retry with proxy and server auth credentials, which gets a response.
4615 MockWrite("GET http://myproxy:70/ HTTP/1.1\r\n"
4616 "Host: myproxy:70\r\n"
4617 "Proxy-Connection: keep-alive\r\n"
4618 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n"
4619 "Authorization: Basic Zm9vMjpiYXIy\r\n\r\n"),
4620 // Another request to the same server and using the same NAK should
4621 // preemptively send the correct cached proxy and server
4622 // auth headers.
4623 MockWrite("GET http://myproxy:70/ HTTP/1.1\r\n"
4624 "Host: myproxy:70\r\n"
4625 "Proxy-Connection: keep-alive\r\n"
4626 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n"
4627 "Authorization: Basic Zm9vMjpiYXIy\r\n\r\n"),
4628 };
4629
4630 MockRead data_reads[] = {
4631 // Proxy auth challenge.
4632 MockRead("HTTP/1.0 407 Proxy Authentication Required\r\n"
4633 "Proxy-Connection: keep-alive\r\n"
4634 "Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"
4635 "Content-Length: 0\r\n\r\n"),
4636 // Server auth challenge.
4637 MockRead("HTTP/1.0 401 Authentication Required\r\n"
4638 "Proxy-Connection: keep-alive\r\n"
4639 "WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"
4640 "Content-Length: 0\r\n\r\n"),
4641 // Response.
4642 MockRead("HTTP/1.1 200 OK\r\n"
4643 "Proxy-Connection: keep-alive\r\n"
4644 "Content-Length: 5\r\n\r\n"
4645 "hello"),
4646 // Response to second request.
4647 MockRead("HTTP/1.1 200 OK\r\n"
4648 "Proxy-Connection: keep-alive\r\n"
4649 "Content-Length: 2\r\n\r\n"
4650 "hi"),
4651 };
4652
4653 StaticSocketDataProvider data(data_reads, data_writes);
4654 session_deps_.socket_factory->AddSocketDataProvider(&data);
4655
4656 MockWrite data_writes2[] = {
4657 // Initial request using a different NetworkAnonymizationKey includes the
4658 // cached proxy credentials, but not server credentials.
4659 MockWrite("GET http://myproxy:70/ HTTP/1.1\r\n"
4660 "Host: myproxy:70\r\n"
4661 "Proxy-Connection: keep-alive\r\n"
4662 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
4663 // Retry with proxy and new server auth credentials, which gets a
4664 // response.
4665 MockWrite("GET http://myproxy:70/ HTTP/1.1\r\n"
4666 "Host: myproxy:70\r\n"
4667 "Proxy-Connection: keep-alive\r\n"
4668 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n"
4669 "Authorization: Basic Zm9vMzpiYXIz\r\n\r\n"),
4670 };
4671
4672 MockRead data_reads2[] = {
4673 // Server auth challenge.
4674 MockRead("HTTP/1.0 401 Authentication Required\r\n"
4675 "Proxy-Connection: keep-alive\r\n"
4676 "WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"
4677 "Content-Length: 0\r\n\r\n"),
4678 // Response.
4679 MockRead("HTTP/1.1 200 OK\r\n"
4680 "Proxy-Connection: keep-alive\r\n"
4681 "Content-Length: 9\r\n\r\n"
4682 "greetings"),
4683 };
4684
4685 StaticSocketDataProvider data2(data_reads2, data_writes2);
4686 session_deps_.socket_factory->AddSocketDataProvider(&data2);
4687
4688 TestCompletionCallback callback;
4689
4690 HttpRequestInfo request;
4691 request.method = "GET";
4692 request.url = GURL("http://myproxy:70/");
4693 request.traffic_annotation =
4694 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
4695 request.network_isolation_key = kNetworkIsolationKey1;
4696 request.network_anonymization_key = kNetworkAnonymizationKey1;
4697
4698 auto trans =
4699 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
4700 int rv = trans->Start(&request, callback.callback(), net_log_with_source);
4701 EXPECT_THAT(callback.GetResult(rv), IsOk());
4702 const HttpResponseInfo* response = trans->GetResponseInfo();
4703 ASSERT_TRUE(response);
4704 ASSERT_TRUE(response->headers);
4705 EXPECT_EQ(407, response->headers->response_code());
4706 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge));
4707
4708 rv = trans->RestartWithAuth(AuthCredentials(kFoo, kBar), callback.callback());
4709 EXPECT_THAT(callback.GetResult(rv), IsOk());
4710 response = trans->GetResponseInfo();
4711 ASSERT_TRUE(response);
4712 EXPECT_EQ(401, response->headers->response_code());
4713 EXPECT_FALSE(response->auth_challenge->is_proxy);
4714 EXPECT_EQ("http://myproxy:70",
4715 response->auth_challenge->challenger.Serialize());
4716 EXPECT_EQ("MyRealm1", response->auth_challenge->realm);
4717 EXPECT_EQ(kBasicAuthScheme, response->auth_challenge->scheme);
4718
4719 rv = trans->RestartWithAuth(AuthCredentials(kFoo2, kBar2),
4720 callback.callback());
4721 EXPECT_THAT(callback.GetResult(rv), IsOk());
4722 response = trans->GetResponseInfo();
4723 ASSERT_TRUE(response);
4724 EXPECT_EQ(200, response->headers->response_code());
4725 // The password prompt info should not be set.
4726 EXPECT_FALSE(response->auth_challenge.has_value());
4727 std::string response_data;
4728 EXPECT_THAT(ReadTransaction(trans.get(), &response_data), IsOk());
4729 EXPECT_EQ("hello", response_data);
4730
4731 // Check that the proxy credentials were cached correctly. The should be
4732 // accessible with any NetworkAnonymizationKey.
4733 HttpAuthCache::Entry* entry = session->http_auth_cache()->Lookup(
4734 url::SchemeHostPort(url::SchemeHostPort(GURL("http://myproxy:70"))),
4735 HttpAuth::AUTH_PROXY, "MyRealm1", HttpAuth::AUTH_SCHEME_BASIC,
4736 kNetworkAnonymizationKey1);
4737 ASSERT_TRUE(entry);
4738 ASSERT_EQ(kFoo, entry->credentials().username());
4739 ASSERT_EQ(kBar, entry->credentials().password());
4740 EXPECT_EQ(entry, session->http_auth_cache()->Lookup(
4741 url::SchemeHostPort(GURL("http://myproxy:70")),
4742 HttpAuth::AUTH_PROXY, "MyRealm1",
4743 HttpAuth::AUTH_SCHEME_BASIC, kNetworkAnonymizationKey2));
4744
4745 // Check that the server credentials were cached correctly. The should be
4746 // accessible with only kNetworkAnonymizationKey1.
4747 entry = session->http_auth_cache()->Lookup(
4748 url::SchemeHostPort(GURL("http://myproxy:70")), HttpAuth::AUTH_SERVER,
4749 "MyRealm1", HttpAuth::AUTH_SCHEME_BASIC, kNetworkAnonymizationKey1);
4750 ASSERT_TRUE(entry);
4751 ASSERT_EQ(kFoo2, entry->credentials().username());
4752 ASSERT_EQ(kBar2, entry->credentials().password());
4753 // Looking up the server entry with another NetworkAnonymizationKey should
4754 // fail.
4755 EXPECT_FALSE(session->http_auth_cache()->Lookup(
4756 url::SchemeHostPort(GURL("http://myproxy:70")), HttpAuth::AUTH_SERVER,
4757 "MyRealm1", HttpAuth::AUTH_SCHEME_BASIC, kNetworkAnonymizationKey2));
4758
4759 // Make another request with a different NetworkAnonymizationKey. It should
4760 // use another socket, reuse the cached proxy credentials, but result in a
4761 // server auth challenge.
4762 request.network_isolation_key = kNetworkIsolationKey2;
4763 request.network_anonymization_key = kNetworkAnonymizationKey2;
4764
4765 trans =
4766 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
4767 rv = trans->Start(&request, callback.callback(), net_log_with_source);
4768 EXPECT_THAT(callback.GetResult(rv), IsOk());
4769 response = trans->GetResponseInfo();
4770 ASSERT_TRUE(response);
4771 EXPECT_EQ(401, response->headers->response_code());
4772 EXPECT_FALSE(response->auth_challenge->is_proxy);
4773 EXPECT_EQ("http://myproxy:70",
4774 response->auth_challenge->challenger.Serialize());
4775 EXPECT_EQ("MyRealm1", response->auth_challenge->realm);
4776 EXPECT_EQ(kBasicAuthScheme, response->auth_challenge->scheme);
4777
4778 rv = trans->RestartWithAuth(AuthCredentials(kFoo3, kBar3),
4779 callback.callback());
4780 EXPECT_THAT(callback.GetResult(rv), IsOk());
4781 response = trans->GetResponseInfo();
4782 ASSERT_TRUE(response);
4783 EXPECT_EQ(200, response->headers->response_code());
4784 // The password prompt info should not be set.
4785 EXPECT_FALSE(response->auth_challenge.has_value());
4786 EXPECT_THAT(ReadTransaction(trans.get(), &response_data), IsOk());
4787 EXPECT_EQ("greetings", response_data);
4788
4789 // Check that the proxy credentials are still cached.
4790 entry = session->http_auth_cache()->Lookup(
4791 url::SchemeHostPort(GURL("http://myproxy:70")), HttpAuth::AUTH_PROXY,
4792 "MyRealm1", HttpAuth::AUTH_SCHEME_BASIC, kNetworkAnonymizationKey1);
4793 ASSERT_TRUE(entry);
4794 ASSERT_EQ(kFoo, entry->credentials().username());
4795 ASSERT_EQ(kBar, entry->credentials().password());
4796 EXPECT_EQ(entry, session->http_auth_cache()->Lookup(
4797 url::SchemeHostPort(GURL("http://myproxy:70")),
4798 HttpAuth::AUTH_PROXY, "MyRealm1",
4799 HttpAuth::AUTH_SCHEME_BASIC, kNetworkAnonymizationKey2));
4800
4801 // Check that the correct server credentials are cached for each
4802 // NetworkAnonymizationKey.
4803 entry = session->http_auth_cache()->Lookup(
4804 url::SchemeHostPort(GURL("http://myproxy:70")), HttpAuth::AUTH_SERVER,
4805 "MyRealm1", HttpAuth::AUTH_SCHEME_BASIC, kNetworkAnonymizationKey1);
4806 ASSERT_TRUE(entry);
4807 ASSERT_EQ(kFoo2, entry->credentials().username());
4808 ASSERT_EQ(kBar2, entry->credentials().password());
4809 entry = session->http_auth_cache()->Lookup(
4810 url::SchemeHostPort(GURL("http://myproxy:70")), HttpAuth::AUTH_SERVER,
4811 "MyRealm1", HttpAuth::AUTH_SCHEME_BASIC, kNetworkAnonymizationKey2);
4812 ASSERT_TRUE(entry);
4813 ASSERT_EQ(kFoo3, entry->credentials().username());
4814 ASSERT_EQ(kBar3, entry->credentials().password());
4815
4816 // Make a request with the original NetworkAnonymizationKey. It should reuse
4817 // the first socket, and the proxy credentials sent on the first socket.
4818 request.network_isolation_key = kNetworkIsolationKey1;
4819 request.network_anonymization_key = kNetworkAnonymizationKey1;
4820 trans =
4821 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
4822 rv = trans->Start(&request, callback.callback(), net_log_with_source);
4823 EXPECT_THAT(callback.GetResult(rv), IsOk());
4824 response = trans->GetResponseInfo();
4825 ASSERT_TRUE(response);
4826 EXPECT_EQ(200, response->headers->response_code());
4827 // The password prompt info should not be set.
4828 EXPECT_FALSE(response->auth_challenge.has_value());
4829 EXPECT_THAT(ReadTransaction(trans.get(), &response_data), IsOk());
4830 EXPECT_EQ("hi", response_data);
4831
4832 trans.reset();
4833 session->CloseAllConnections(ERR_FAILED, "Very good reason");
4834 }
4835
4836 // Much like the test above, but uses tunnelled connections.
TEST_P(HttpNetworkTransactionTest,BasicAuthProxyMatchesServerAuthWithNetworkAnonymizationKeyWithTunnel)4837 TEST_P(HttpNetworkTransactionTest,
4838 BasicAuthProxyMatchesServerAuthWithNetworkAnonymizationKeyWithTunnel) {
4839 const SchemefulSite kSite1(GURL("https://foo.test/"));
4840 const auto kNetworkAnonymizationKey1 =
4841 net::NetworkAnonymizationKey::CreateSameSite(kSite1);
4842 const net::NetworkIsolationKey kNetworkIsolationKey1(kSite1, kSite1);
4843 const SchemefulSite kSite2(GURL("https://bar.test/"));
4844 const auto kNetworkAnonymizationKey2 =
4845 net::NetworkAnonymizationKey::CreateSameSite(kSite2);
4846 const net::NetworkIsolationKey kNetworkIsolationKey2(kSite2, kSite2);
4847
4848 // This test would need to use a single socket without this option enabled.
4849 // Best to use this option when it would affect a test, as it will eventually
4850 // become the default behavior.
4851 base::test::ScopedFeatureList feature_list;
4852 feature_list.InitAndEnableFeature(
4853 features::kPartitionConnectionsByNetworkIsolationKey);
4854
4855 // Proxy matches request URL.
4856 session_deps_.proxy_resolution_service =
4857 ConfiguredProxyResolutionService::CreateFixedFromPacResultForTest(
4858 "HTTPS myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
4859 NetLogWithSource net_log_with_source =
4860 NetLogWithSource::Make(NetLogSourceType::NONE);
4861 session_deps_.net_log = NetLog::Get();
4862 session_deps_.key_auth_cache_server_entries_by_network_anonymization_key =
4863 true;
4864 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
4865
4866 MockWrite data_writes[] = {
4867 // Initial tunnel request gets a proxy auth challenge.
4868 MockWrite("CONNECT myproxy:70 HTTP/1.1\r\n"
4869 "Host: myproxy:70\r\n"
4870 "Proxy-Connection: keep-alive\r\n\r\n"),
4871 // Retry with proxy auth credentials, which will result in establishing a
4872 // tunnel.
4873 MockWrite("CONNECT myproxy:70 HTTP/1.1\r\n"
4874 "Host: myproxy:70\r\n"
4875 "Proxy-Connection: keep-alive\r\n"
4876 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
4877 // Request over the tunnel, which gets a server auth challenge.
4878 MockWrite("GET / HTTP/1.1\r\n"
4879 "Host: myproxy:70\r\n"
4880 "Connection: keep-alive\r\n\r\n"),
4881 // Retry with server auth credentials, which gets a response.
4882 MockWrite("GET / HTTP/1.1\r\n"
4883 "Host: myproxy:70\r\n"
4884 "Connection: keep-alive\r\n"
4885 "Authorization: Basic Zm9vMjpiYXIy\r\n\r\n"),
4886 // Another request to the same server and using the same NAK should
4887 // preemptively send the correct cached server
4888 // auth header. Since a tunnel was already established, the proxy headers
4889 // won't be sent again except when establishing another tunnel.
4890 MockWrite("GET / HTTP/1.1\r\n"
4891 "Host: myproxy:70\r\n"
4892 "Connection: keep-alive\r\n"
4893 "Authorization: Basic Zm9vMjpiYXIy\r\n\r\n"),
4894 };
4895
4896 MockRead data_reads[] = {
4897 // Proxy auth challenge.
4898 MockRead("HTTP/1.0 407 Proxy Authentication Required\r\n"
4899 "Proxy-Connection: keep-alive\r\n"
4900 "Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"
4901 "Content-Length: 0\r\n\r\n"),
4902 // Tunnel success
4903 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
4904 // Server auth challenge.
4905 MockRead("HTTP/1.0 401 Authentication Required\r\n"
4906 "Connection: keep-alive\r\n"
4907 "WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"
4908 "Content-Length: 0\r\n\r\n"),
4909 // Response.
4910 MockRead("HTTP/1.1 200 OK\r\n"
4911 "Connection: keep-alive\r\n"
4912 "Content-Length: 5\r\n\r\n"
4913 "hello"),
4914 // Response to second request.
4915 MockRead("HTTP/1.1 200 OK\r\n"
4916 "Connection: keep-alive\r\n"
4917 "Content-Length: 2\r\n\r\n"
4918 "hi"),
4919 };
4920
4921 StaticSocketDataProvider data(data_reads, data_writes);
4922 session_deps_.socket_factory->AddSocketDataProvider(&data);
4923 // One for the proxy connection, one of the server connection.
4924 SSLSocketDataProvider ssl(ASYNC, OK);
4925 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
4926 SSLSocketDataProvider ssl2(ASYNC, OK);
4927 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
4928
4929 MockWrite data_writes2[] = {
4930 // Initial request using a different NetworkAnonymizationKey includes the
4931 // cached proxy credentials when establishing a tunnel.
4932 MockWrite("CONNECT myproxy:70 HTTP/1.1\r\n"
4933 "Host: myproxy:70\r\n"
4934 "Proxy-Connection: keep-alive\r\n"
4935 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
4936 // Request over the tunnel, which gets a server auth challenge. Cached
4937 // credentials cannot be used, since the NAK is different.
4938 MockWrite("GET / HTTP/1.1\r\n"
4939 "Host: myproxy:70\r\n"
4940 "Connection: keep-alive\r\n\r\n"),
4941 // Retry with server auth credentials, which gets a response.
4942 MockWrite("GET / HTTP/1.1\r\n"
4943 "Host: myproxy:70\r\n"
4944 "Connection: keep-alive\r\n"
4945 "Authorization: Basic Zm9vMzpiYXIz\r\n\r\n"),
4946 };
4947
4948 MockRead data_reads2[] = {
4949 // Tunnel success
4950 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
4951 // Server auth challenge.
4952 MockRead("HTTP/1.0 401 Authentication Required\r\n"
4953 "Connection: keep-alive\r\n"
4954 "WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"
4955 "Content-Length: 0\r\n\r\n"),
4956 // Response.
4957 MockRead("HTTP/1.1 200 OK\r\n"
4958 "Connection: keep-alive\r\n"
4959 "Content-Length: 9\r\n\r\n"
4960 "greetings"),
4961 };
4962
4963 StaticSocketDataProvider data2(data_reads2, data_writes2);
4964 session_deps_.socket_factory->AddSocketDataProvider(&data2);
4965 // One for the proxy connection, one of the server connection.
4966 SSLSocketDataProvider ssl3(ASYNC, OK);
4967 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl3);
4968 SSLSocketDataProvider ssl4(ASYNC, OK);
4969 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl4);
4970
4971 TestCompletionCallback callback;
4972
4973 HttpRequestInfo request;
4974 request.method = "GET";
4975 request.url = GURL("https://myproxy:70/");
4976 request.traffic_annotation =
4977 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
4978 request.network_isolation_key = kNetworkIsolationKey1;
4979 request.network_anonymization_key = kNetworkAnonymizationKey1;
4980
4981 auto trans =
4982 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
4983 int rv = trans->Start(&request, callback.callback(), net_log_with_source);
4984 EXPECT_THAT(callback.GetResult(rv), IsOk());
4985 const HttpResponseInfo* response = trans->GetResponseInfo();
4986 ASSERT_TRUE(response);
4987 ASSERT_TRUE(response->headers);
4988 EXPECT_EQ(407, response->headers->response_code());
4989 EXPECT_TRUE(CheckBasicSecureProxyAuth(response->auth_challenge));
4990
4991 rv = trans->RestartWithAuth(AuthCredentials(kFoo, kBar), callback.callback());
4992 EXPECT_THAT(callback.GetResult(rv), IsOk());
4993 response = trans->GetResponseInfo();
4994 ASSERT_TRUE(response);
4995 EXPECT_EQ(401, response->headers->response_code());
4996 EXPECT_FALSE(response->auth_challenge->is_proxy);
4997 EXPECT_EQ("https://myproxy:70",
4998 response->auth_challenge->challenger.Serialize());
4999 EXPECT_EQ("MyRealm1", response->auth_challenge->realm);
5000 EXPECT_EQ(kBasicAuthScheme, response->auth_challenge->scheme);
5001
5002 rv = trans->RestartWithAuth(AuthCredentials(kFoo2, kBar2),
5003 callback.callback());
5004 EXPECT_THAT(callback.GetResult(rv), IsOk());
5005 response = trans->GetResponseInfo();
5006 ASSERT_TRUE(response);
5007 EXPECT_EQ(200, response->headers->response_code());
5008 // The password prompt info should not be set.
5009 EXPECT_FALSE(response->auth_challenge.has_value());
5010 std::string response_data;
5011 EXPECT_THAT(ReadTransaction(trans.get(), &response_data), IsOk());
5012 EXPECT_EQ("hello", response_data);
5013
5014 // Check that the proxy credentials were cached correctly. The should be
5015 // accessible with any NetworkAnonymizationKey.
5016 HttpAuthCache::Entry* entry = session->http_auth_cache()->Lookup(
5017 url::SchemeHostPort(url::SchemeHostPort(GURL("https://myproxy:70"))),
5018 HttpAuth::AUTH_PROXY, "MyRealm1", HttpAuth::AUTH_SCHEME_BASIC,
5019 kNetworkAnonymizationKey1);
5020 ASSERT_TRUE(entry);
5021 ASSERT_EQ(kFoo, entry->credentials().username());
5022 ASSERT_EQ(kBar, entry->credentials().password());
5023 EXPECT_EQ(entry, session->http_auth_cache()->Lookup(
5024 url::SchemeHostPort(GURL("https://myproxy:70")),
5025 HttpAuth::AUTH_PROXY, "MyRealm1",
5026 HttpAuth::AUTH_SCHEME_BASIC, kNetworkAnonymizationKey2));
5027
5028 // Check that the server credentials were cached correctly. The should be
5029 // accessible with only kNetworkAnonymizationKey1.
5030 entry = session->http_auth_cache()->Lookup(
5031 url::SchemeHostPort(GURL("https://myproxy:70")), HttpAuth::AUTH_SERVER,
5032 "MyRealm1", HttpAuth::AUTH_SCHEME_BASIC, kNetworkAnonymizationKey1);
5033 ASSERT_TRUE(entry);
5034 ASSERT_EQ(kFoo2, entry->credentials().username());
5035 ASSERT_EQ(kBar2, entry->credentials().password());
5036 // Looking up the server entry with another NetworkAnonymiationKey should
5037 // fail.
5038 EXPECT_FALSE(session->http_auth_cache()->Lookup(
5039 url::SchemeHostPort(GURL("https://myproxy:70")), HttpAuth::AUTH_SERVER,
5040 "MyRealm1", HttpAuth::AUTH_SCHEME_BASIC, kNetworkAnonymizationKey2));
5041
5042 // Make another request with a different NetworkAnonymiationKey. It should use
5043 // another socket, reuse the cached proxy credentials, but result in a server
5044 // auth challenge.
5045 request.network_isolation_key = kNetworkIsolationKey2;
5046 request.network_anonymization_key = kNetworkAnonymizationKey2;
5047
5048 trans =
5049 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
5050 rv = trans->Start(&request, callback.callback(), net_log_with_source);
5051 EXPECT_THAT(callback.GetResult(rv), IsOk());
5052 response = trans->GetResponseInfo();
5053 ASSERT_TRUE(response);
5054 EXPECT_EQ(401, response->headers->response_code());
5055 EXPECT_FALSE(response->auth_challenge->is_proxy);
5056 EXPECT_EQ("https://myproxy:70",
5057 response->auth_challenge->challenger.Serialize());
5058 EXPECT_EQ("MyRealm1", response->auth_challenge->realm);
5059 EXPECT_EQ(kBasicAuthScheme, response->auth_challenge->scheme);
5060
5061 rv = trans->RestartWithAuth(AuthCredentials(kFoo3, kBar3),
5062 callback.callback());
5063 EXPECT_THAT(callback.GetResult(rv), IsOk());
5064 response = trans->GetResponseInfo();
5065 ASSERT_TRUE(response);
5066 EXPECT_EQ(200, response->headers->response_code());
5067 // The password prompt info should not be set.
5068 EXPECT_FALSE(response->auth_challenge.has_value());
5069 EXPECT_THAT(ReadTransaction(trans.get(), &response_data), IsOk());
5070 EXPECT_EQ("greetings", response_data);
5071
5072 // Check that the proxy credentials are still cached.
5073 entry = session->http_auth_cache()->Lookup(
5074 url::SchemeHostPort(GURL("https://myproxy:70")), HttpAuth::AUTH_PROXY,
5075 "MyRealm1", HttpAuth::AUTH_SCHEME_BASIC, kNetworkAnonymizationKey1);
5076 ASSERT_TRUE(entry);
5077 ASSERT_EQ(kFoo, entry->credentials().username());
5078 ASSERT_EQ(kBar, entry->credentials().password());
5079 EXPECT_EQ(entry, session->http_auth_cache()->Lookup(
5080 url::SchemeHostPort(GURL("https://myproxy:70")),
5081 HttpAuth::AUTH_PROXY, "MyRealm1",
5082 HttpAuth::AUTH_SCHEME_BASIC, kNetworkAnonymizationKey2));
5083
5084 // Check that the correct server credentials are cached for each
5085 // NetworkAnonymiationKey.
5086 entry = session->http_auth_cache()->Lookup(
5087 url::SchemeHostPort(GURL("https://myproxy:70")), HttpAuth::AUTH_SERVER,
5088 "MyRealm1", HttpAuth::AUTH_SCHEME_BASIC, kNetworkAnonymizationKey1);
5089 ASSERT_TRUE(entry);
5090 ASSERT_EQ(kFoo2, entry->credentials().username());
5091 ASSERT_EQ(kBar2, entry->credentials().password());
5092 entry = session->http_auth_cache()->Lookup(
5093 url::SchemeHostPort(GURL("https://myproxy:70")), HttpAuth::AUTH_SERVER,
5094 "MyRealm1", HttpAuth::AUTH_SCHEME_BASIC, kNetworkAnonymizationKey2);
5095 ASSERT_TRUE(entry);
5096 ASSERT_EQ(kFoo3, entry->credentials().username());
5097 ASSERT_EQ(kBar3, entry->credentials().password());
5098
5099 // Make a request with the original NetworkAnonymiationKey. It should reuse
5100 // the first socket, and the proxy credentials sent on the first socket.
5101 request.network_isolation_key = kNetworkIsolationKey1;
5102 request.network_anonymization_key = kNetworkAnonymizationKey1;
5103
5104 trans =
5105 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
5106 rv = trans->Start(&request, callback.callback(), net_log_with_source);
5107 EXPECT_THAT(callback.GetResult(rv), IsOk());
5108 response = trans->GetResponseInfo();
5109 ASSERT_TRUE(response);
5110 EXPECT_EQ(200, response->headers->response_code());
5111 // The password prompt info should not be set.
5112 EXPECT_FALSE(response->auth_challenge.has_value());
5113 EXPECT_THAT(ReadTransaction(trans.get(), &response_data), IsOk());
5114 EXPECT_EQ("hi", response_data);
5115
5116 trans.reset();
5117 session->CloseAllConnections(ERR_FAILED, "Very good reason");
5118 }
5119
5120 // Test that we don't pass extraneous headers from the proxy's response to the
5121 // caller when the proxy responds to CONNECT with 407.
TEST_P(HttpNetworkTransactionTest,SanitizeProxyAuthHeaders)5122 TEST_P(HttpNetworkTransactionTest, SanitizeProxyAuthHeaders) {
5123 HttpRequestInfo request;
5124 request.method = "GET";
5125 request.url = GURL("https://www.example.org/");
5126 request.traffic_annotation =
5127 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
5128
5129 // Configure against proxy server "myproxy:70".
5130 session_deps_.proxy_resolution_service =
5131 ConfiguredProxyResolutionService::CreateFixedForTest(
5132 "myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
5133
5134 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
5135
5136 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
5137
5138 // Since we have proxy, should try to establish tunnel.
5139 MockWrite data_writes[] = {
5140 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
5141 "Host: www.example.org:443\r\n"
5142 "Proxy-Connection: keep-alive\r\n\r\n"),
5143 };
5144
5145 // The proxy responds to the connect with a 407.
5146 MockRead data_reads[] = {
5147 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
5148 MockRead("X-Foo: bar\r\n"),
5149 MockRead("Set-Cookie: foo=bar\r\n"),
5150 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
5151 MockRead("Content-Length: 10\r\n\r\n"),
5152 MockRead(SYNCHRONOUS, ERR_UNEXPECTED),
5153 };
5154
5155 StaticSocketDataProvider data(data_reads, data_writes);
5156 session_deps_.socket_factory->AddSocketDataProvider(&data);
5157
5158 TestCompletionCallback callback;
5159
5160 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
5161 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
5162
5163 rv = callback.WaitForResult();
5164 EXPECT_THAT(rv, IsOk());
5165
5166 const HttpResponseInfo* response = trans.GetResponseInfo();
5167 ASSERT_TRUE(response);
5168 ASSERT_TRUE(response->headers);
5169 EXPECT_TRUE(response->headers->IsKeepAlive());
5170 EXPECT_EQ(407, response->headers->response_code());
5171 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
5172 EXPECT_FALSE(response->headers->HasHeader("X-Foo"));
5173 EXPECT_FALSE(response->headers->HasHeader("Set-Cookie"));
5174
5175 std::string response_data;
5176 rv = ReadTransaction(&trans, &response_data);
5177 EXPECT_THAT(rv, IsError(ERR_TUNNEL_CONNECTION_FAILED));
5178
5179 // Flush the idle socket before the HttpNetworkTransaction goes out of scope.
5180 session->CloseAllConnections(ERR_FAILED, "Very good reason");
5181 }
5182
5183 // Test when a server (non-proxy) returns a 407 (proxy-authenticate).
5184 // The request should fail with ERR_UNEXPECTED_PROXY_AUTH.
TEST_P(HttpNetworkTransactionTest,UnexpectedProxyAuth)5185 TEST_P(HttpNetworkTransactionTest, UnexpectedProxyAuth) {
5186 HttpRequestInfo request;
5187 request.method = "GET";
5188 request.url = GURL("http://www.example.org/");
5189 request.traffic_annotation =
5190 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
5191
5192 // We are using a DIRECT connection (i.e. no proxy) for this session.
5193 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
5194 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
5195
5196 MockWrite data_writes1[] = {
5197 MockWrite("GET / HTTP/1.1\r\n"
5198 "Host: www.example.org\r\n"
5199 "Connection: keep-alive\r\n\r\n"),
5200 };
5201
5202 MockRead data_reads1[] = {
5203 MockRead("HTTP/1.0 407 Proxy Auth required\r\n"),
5204 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
5205 // Large content-length -- won't matter, as connection will be reset.
5206 MockRead("Content-Length: 10000\r\n\r\n"),
5207 MockRead(SYNCHRONOUS, ERR_FAILED),
5208 };
5209
5210 StaticSocketDataProvider data1(data_reads1, data_writes1);
5211 session_deps_.socket_factory->AddSocketDataProvider(&data1);
5212
5213 TestCompletionCallback callback;
5214
5215 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
5216 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
5217
5218 rv = callback.WaitForResult();
5219 EXPECT_THAT(rv, IsError(ERR_UNEXPECTED_PROXY_AUTH));
5220 }
5221
5222 // Tests when an HTTPS server (non-proxy) returns a 407 (proxy-authentication)
5223 // through a non-authenticating proxy. The request should fail with
5224 // ERR_UNEXPECTED_PROXY_AUTH.
5225 // Note that it is impossible to detect if an HTTP server returns a 407 through
5226 // a non-authenticating proxy - there is nothing to indicate whether the
5227 // response came from the proxy or the server, so it is treated as if the proxy
5228 // issued the challenge.
TEST_P(HttpNetworkTransactionTest,HttpsServerRequestsProxyAuthThroughProxy)5229 TEST_P(HttpNetworkTransactionTest, HttpsServerRequestsProxyAuthThroughProxy) {
5230 HttpRequestInfo request;
5231 request.method = "GET";
5232 request.url = GURL("https://www.example.org/");
5233 request.traffic_annotation =
5234 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
5235
5236 session_deps_.proxy_resolution_service =
5237 ConfiguredProxyResolutionService::CreateFixedForTest(
5238 "myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
5239 RecordingNetLogObserver net_log_observer;
5240 session_deps_.net_log = NetLog::Get();
5241 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
5242
5243 // Since we have proxy, should try to establish tunnel.
5244 MockWrite data_writes1[] = {
5245 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
5246 "Host: www.example.org:443\r\n"
5247 "Proxy-Connection: keep-alive\r\n\r\n"),
5248
5249 MockWrite("GET / HTTP/1.1\r\n"
5250 "Host: www.example.org\r\n"
5251 "Connection: keep-alive\r\n\r\n"),
5252 };
5253
5254 MockRead data_reads1[] = {
5255 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
5256
5257 MockRead("HTTP/1.1 407 Unauthorized\r\n"),
5258 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
5259 MockRead("\r\n"),
5260 MockRead(SYNCHRONOUS, OK),
5261 };
5262
5263 StaticSocketDataProvider data1(data_reads1, data_writes1);
5264 session_deps_.socket_factory->AddSocketDataProvider(&data1);
5265 SSLSocketDataProvider ssl(ASYNC, OK);
5266 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
5267
5268 TestCompletionCallback callback;
5269
5270 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
5271
5272 int rv = trans.Start(&request, callback.callback(),
5273 NetLogWithSource::Make(NetLogSourceType::NONE));
5274 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
5275
5276 rv = callback.WaitForResult();
5277 EXPECT_THAT(rv, IsError(ERR_UNEXPECTED_PROXY_AUTH));
5278 auto entries = net_log_observer.GetEntries();
5279 size_t pos = ExpectLogContainsSomewhere(
5280 entries, 0, NetLogEventType::HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
5281 NetLogEventPhase::NONE);
5282 ExpectLogContainsSomewhere(
5283 entries, pos,
5284 NetLogEventType::HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
5285 NetLogEventPhase::NONE);
5286 }
5287
5288 // Test a proxy auth scheme that allows default credentials and a proxy server
5289 // that uses non-persistent connections.
TEST_P(HttpNetworkTransactionTest,AuthAllowsDefaultCredentialsTunnelConnectionClose)5290 TEST_P(HttpNetworkTransactionTest,
5291 AuthAllowsDefaultCredentialsTunnelConnectionClose) {
5292 HttpRequestInfo request;
5293 request.method = "GET";
5294 request.url = GURL("https://www.example.org/");
5295 request.traffic_annotation =
5296 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
5297
5298 // Configure against proxy server "myproxy:70".
5299 session_deps_.proxy_resolution_service =
5300 ConfiguredProxyResolutionService::CreateFixedFromPacResultForTest(
5301 "PROXY myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
5302
5303 auto auth_handler_factory = std::make_unique<HttpAuthHandlerMock::Factory>();
5304 auth_handler_factory->set_do_init_from_challenge(true);
5305 auto mock_handler = std::make_unique<HttpAuthHandlerMock>();
5306 mock_handler->set_allows_default_credentials(true);
5307 auth_handler_factory->AddMockHandler(std::move(mock_handler),
5308 HttpAuth::AUTH_PROXY);
5309 session_deps_.http_auth_handler_factory = std::move(auth_handler_factory);
5310
5311 // Add NetLog just so can verify load timing information gets a NetLog ID.
5312 session_deps_.net_log = NetLog::Get();
5313 std::unique_ptr<HttpNetworkSession> session = CreateSession(&session_deps_);
5314
5315 // Since we have proxy, should try to establish tunnel.
5316 MockWrite data_writes1[] = {
5317 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
5318 "Host: www.example.org:443\r\n"
5319 "Proxy-Connection: keep-alive\r\n\r\n"),
5320 };
5321
5322 // The proxy responds to the connect with a 407, using a non-persistent
5323 // connection.
5324 MockRead data_reads1[] = {
5325 // No credentials.
5326 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
5327 MockRead("Proxy-Authenticate: Mock\r\n"),
5328 MockRead("Proxy-Connection: close\r\n\r\n"),
5329 };
5330
5331 // Since the first connection couldn't be reused, need to establish another
5332 // once given credentials.
5333 MockWrite data_writes2[] = {
5334 // After calling trans->RestartWithAuth(), this is the request we should
5335 // be issuing -- the final header line contains the credentials.
5336 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
5337 "Host: www.example.org:443\r\n"
5338 "Proxy-Connection: keep-alive\r\n"
5339 "Proxy-Authorization: auth_token\r\n\r\n"),
5340
5341 MockWrite("GET / HTTP/1.1\r\n"
5342 "Host: www.example.org\r\n"
5343 "Connection: keep-alive\r\n\r\n"),
5344 };
5345
5346 MockRead data_reads2[] = {
5347 MockRead("HTTP/1.0 200 Connection Established\r\n\r\n"),
5348
5349 MockRead("HTTP/1.1 200 OK\r\n"),
5350 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
5351 MockRead("Content-Length: 5\r\n\r\n"),
5352 MockRead(SYNCHRONOUS, "hello"),
5353 };
5354
5355 StaticSocketDataProvider data1(data_reads1, data_writes1);
5356 session_deps_.socket_factory->AddSocketDataProvider(&data1);
5357 StaticSocketDataProvider data2(data_reads2, data_writes2);
5358 session_deps_.socket_factory->AddSocketDataProvider(&data2);
5359 SSLSocketDataProvider ssl(ASYNC, OK);
5360 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
5361
5362 auto trans =
5363 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
5364
5365 TestCompletionCallback callback;
5366 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
5367 EXPECT_THAT(callback.GetResult(rv), IsOk());
5368
5369 const HttpResponseInfo* response = trans->GetResponseInfo();
5370 ASSERT_TRUE(response);
5371 ASSERT_TRUE(response->headers);
5372 EXPECT_FALSE(response->headers->IsKeepAlive());
5373 EXPECT_EQ(407, response->headers->response_code());
5374 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
5375 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
5376 EXPECT_FALSE(response->auth_challenge.has_value());
5377
5378 LoadTimingInfo load_timing_info;
5379 // CONNECT requests and responses are handled at the connect job level, so
5380 // the transaction does not yet have a connection.
5381 EXPECT_FALSE(trans->GetLoadTimingInfo(&load_timing_info));
5382
5383 rv = trans->RestartWithAuth(AuthCredentials(), callback.callback());
5384 EXPECT_THAT(callback.GetResult(rv), IsOk());
5385 response = trans->GetResponseInfo();
5386 ASSERT_TRUE(response);
5387 ASSERT_TRUE(response->headers);
5388 EXPECT_TRUE(response->headers->IsKeepAlive());
5389 EXPECT_EQ(200, response->headers->response_code());
5390 EXPECT_EQ(5, response->headers->GetContentLength());
5391 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
5392
5393 // The password prompt info should not be set.
5394 EXPECT_FALSE(response->auth_challenge.has_value());
5395
5396 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
5397 TestLoadTimingNotReusedWithPac(load_timing_info,
5398 CONNECT_TIMING_HAS_SSL_TIMES);
5399
5400 trans.reset();
5401 session->CloseAllConnections(ERR_FAILED, "Very good reason");
5402 }
5403
5404 // Test a proxy auth scheme that allows default credentials and a proxy server
5405 // that hangs up when credentials are initially sent.
TEST_P(HttpNetworkTransactionTest,AuthAllowsDefaultCredentialsTunnelServerClosesConnection)5406 TEST_P(HttpNetworkTransactionTest,
5407 AuthAllowsDefaultCredentialsTunnelServerClosesConnection) {
5408 HttpRequestInfo request;
5409 request.method = "GET";
5410 request.url = GURL("https://www.example.org/");
5411 request.traffic_annotation =
5412 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
5413
5414 // Configure against proxy server "myproxy:70".
5415 session_deps_.proxy_resolution_service =
5416 ConfiguredProxyResolutionService::CreateFixedFromPacResultForTest(
5417 "PROXY myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
5418
5419 auto auth_handler_factory = std::make_unique<HttpAuthHandlerMock::Factory>();
5420 auth_handler_factory->set_do_init_from_challenge(true);
5421 auto mock_handler = std::make_unique<HttpAuthHandlerMock>();
5422 mock_handler->set_allows_default_credentials(true);
5423 auth_handler_factory->AddMockHandler(std::move(mock_handler),
5424 HttpAuth::AUTH_PROXY);
5425 session_deps_.http_auth_handler_factory = std::move(auth_handler_factory);
5426
5427 // Add NetLog just so can verify load timing information gets a NetLog ID.
5428 session_deps_.net_log = NetLog::Get();
5429 std::unique_ptr<HttpNetworkSession> session = CreateSession(&session_deps_);
5430
5431 // Should try to establish tunnel.
5432 MockWrite data_writes1[] = {
5433 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
5434 "Host: www.example.org:443\r\n"
5435 "Proxy-Connection: keep-alive\r\n\r\n"),
5436
5437 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
5438 "Host: www.example.org:443\r\n"
5439 "Proxy-Connection: keep-alive\r\n"
5440 "Proxy-Authorization: auth_token\r\n\r\n"),
5441 };
5442
5443 // The proxy responds to the connect with a 407, using a non-persistent
5444 // connection.
5445 MockRead data_reads1[] = {
5446 // No credentials.
5447 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
5448 MockRead("Proxy-Authenticate: Mock\r\n\r\n"),
5449 MockRead(SYNCHRONOUS, ERR_CONNECTION_CLOSED),
5450 };
5451
5452 // Since the first connection was closed, need to establish another once given
5453 // credentials.
5454 MockWrite data_writes2[] = {
5455 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
5456 "Host: www.example.org:443\r\n"
5457 "Proxy-Connection: keep-alive\r\n"
5458 "Proxy-Authorization: auth_token\r\n\r\n"),
5459
5460 MockWrite("GET / HTTP/1.1\r\n"
5461 "Host: www.example.org\r\n"
5462 "Connection: keep-alive\r\n\r\n"),
5463 };
5464
5465 MockRead data_reads2[] = {
5466 MockRead("HTTP/1.0 200 Connection Established\r\n\r\n"),
5467
5468 MockRead("HTTP/1.1 200 OK\r\n"),
5469 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
5470 MockRead("Content-Length: 5\r\n\r\n"),
5471 MockRead(SYNCHRONOUS, "hello"),
5472 };
5473
5474 StaticSocketDataProvider data1(data_reads1, data_writes1);
5475 session_deps_.socket_factory->AddSocketDataProvider(&data1);
5476 StaticSocketDataProvider data2(data_reads2, data_writes2);
5477 session_deps_.socket_factory->AddSocketDataProvider(&data2);
5478 SSLSocketDataProvider ssl(ASYNC, OK);
5479 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
5480
5481 auto trans =
5482 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
5483
5484 TestCompletionCallback callback;
5485 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
5486 EXPECT_THAT(callback.GetResult(rv), IsOk());
5487
5488 const HttpResponseInfo* response = trans->GetResponseInfo();
5489 ASSERT_TRUE(response);
5490 ASSERT_TRUE(response->headers);
5491 EXPECT_TRUE(response->headers->IsKeepAlive());
5492 EXPECT_EQ(407, response->headers->response_code());
5493 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
5494 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
5495 EXPECT_FALSE(response->auth_challenge.has_value());
5496
5497 LoadTimingInfo load_timing_info;
5498 // CONNECT requests and responses are handled at the connect job level, so
5499 // the transaction does not yet have a connection.
5500 EXPECT_FALSE(trans->GetLoadTimingInfo(&load_timing_info));
5501
5502 rv = trans->RestartWithAuth(AuthCredentials(), callback.callback());
5503 EXPECT_THAT(callback.GetResult(rv), IsOk());
5504
5505 response = trans->GetResponseInfo();
5506 ASSERT_TRUE(response);
5507 ASSERT_TRUE(response->headers);
5508 EXPECT_TRUE(response->headers->IsKeepAlive());
5509 EXPECT_EQ(200, response->headers->response_code());
5510 EXPECT_EQ(5, response->headers->GetContentLength());
5511 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
5512
5513 // The password prompt info should not be set.
5514 EXPECT_FALSE(response->auth_challenge.has_value());
5515
5516 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
5517 TestLoadTimingNotReusedWithPac(load_timing_info,
5518 CONNECT_TIMING_HAS_SSL_TIMES);
5519
5520 trans.reset();
5521 session->CloseAllConnections(ERR_FAILED, "Very good reason");
5522 }
5523
5524 // Test a proxy auth scheme that allows default credentials and a proxy server
5525 // that hangs up when credentials are initially sent, and hangs up again when
5526 // they are retried.
TEST_P(HttpNetworkTransactionTest,AuthAllowsDefaultCredentialsTunnelServerClosesConnectionTwice)5527 TEST_P(HttpNetworkTransactionTest,
5528 AuthAllowsDefaultCredentialsTunnelServerClosesConnectionTwice) {
5529 HttpRequestInfo request;
5530 request.method = "GET";
5531 request.url = GURL("https://www.example.org/");
5532 request.traffic_annotation =
5533 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
5534
5535 // Configure against proxy server "myproxy:70".
5536 session_deps_.proxy_resolution_service =
5537 ConfiguredProxyResolutionService::CreateFixedFromPacResultForTest(
5538 "PROXY myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
5539
5540 auto auth_handler_factory = std::make_unique<HttpAuthHandlerMock::Factory>();
5541 auth_handler_factory->set_do_init_from_challenge(true);
5542 auto mock_handler = std::make_unique<HttpAuthHandlerMock>();
5543 mock_handler->set_allows_default_credentials(true);
5544 auth_handler_factory->AddMockHandler(std::move(mock_handler),
5545 HttpAuth::AUTH_PROXY);
5546 session_deps_.http_auth_handler_factory = std::move(auth_handler_factory);
5547
5548 // Add NetLog just so can verify load timing information gets a NetLog ID.
5549 session_deps_.net_log = NetLog::Get();
5550 std::unique_ptr<HttpNetworkSession> session = CreateSession(&session_deps_);
5551
5552 // Should try to establish tunnel.
5553 MockWrite data_writes1[] = {
5554 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
5555 "Host: www.example.org:443\r\n"
5556 "Proxy-Connection: keep-alive\r\n\r\n"),
5557
5558 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
5559 "Host: www.example.org:443\r\n"
5560 "Proxy-Connection: keep-alive\r\n"
5561 "Proxy-Authorization: auth_token\r\n\r\n"),
5562 };
5563
5564 // The proxy responds to the connect with a 407, and then hangs up after the
5565 // second request is sent.
5566 MockRead data_reads1[] = {
5567 // No credentials.
5568 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
5569 MockRead("Content-Length: 0\r\n"),
5570 MockRead("Proxy-Connection: keep-alive\r\n"),
5571 MockRead("Proxy-Authenticate: Mock\r\n\r\n"),
5572 MockRead(SYNCHRONOUS, ERR_CONNECTION_CLOSED),
5573 };
5574
5575 // HttpNetworkTransaction sees a reused connection that was closed with
5576 // ERR_CONNECTION_CLOSED, realized it might have been a race, so retries the
5577 // request.
5578 MockWrite data_writes2[] = {
5579 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
5580 "Host: www.example.org:443\r\n"
5581 "Proxy-Connection: keep-alive\r\n\r\n"),
5582 };
5583
5584 // The proxy, having had more than enough of us, just hangs up.
5585 MockRead data_reads2[] = {
5586 // No credentials.
5587 MockRead(SYNCHRONOUS, ERR_CONNECTION_CLOSED),
5588 };
5589
5590 StaticSocketDataProvider data1(data_reads1, data_writes1);
5591 session_deps_.socket_factory->AddSocketDataProvider(&data1);
5592 StaticSocketDataProvider data2(data_reads2, data_writes2);
5593 session_deps_.socket_factory->AddSocketDataProvider(&data2);
5594
5595 auto trans =
5596 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
5597
5598 TestCompletionCallback callback;
5599 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
5600 EXPECT_THAT(callback.GetResult(rv), IsOk());
5601
5602 const HttpResponseInfo* response = trans->GetResponseInfo();
5603 ASSERT_TRUE(response);
5604 ASSERT_TRUE(response->headers);
5605 EXPECT_TRUE(response->headers->IsKeepAlive());
5606 EXPECT_EQ(407, response->headers->response_code());
5607 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
5608 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
5609 EXPECT_FALSE(response->auth_challenge.has_value());
5610
5611 LoadTimingInfo load_timing_info;
5612 EXPECT_FALSE(trans->GetLoadTimingInfo(&load_timing_info));
5613
5614 rv = trans->RestartWithAuth(AuthCredentials(), callback.callback());
5615 EXPECT_THAT(callback.GetResult(rv), IsError(ERR_EMPTY_RESPONSE));
5616
5617 trans.reset();
5618 session->CloseAllConnections(ERR_FAILED, "Very good reason");
5619 }
5620
5621 // This test exercises an odd edge case where the proxy closes the connection
5622 // after the authentication handshake is complete. Presumably this technique is
5623 // used in lieu of returning a 403 or 5xx status code when the authentication
5624 // succeeds, but the user is not authorized to connect to the destination
5625 // server. There's no standard for what a proxy should do to indicate a blocked
5626 // site.
TEST_P(HttpNetworkTransactionTest,AuthAllowsDefaultCredentialsTunnelConnectionClosesBeforeBody)5627 TEST_P(HttpNetworkTransactionTest,
5628 AuthAllowsDefaultCredentialsTunnelConnectionClosesBeforeBody) {
5629 HttpRequestInfo request;
5630 request.method = "GET";
5631 request.url = GURL("https://www.example.org/");
5632 request.traffic_annotation =
5633 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
5634
5635 // Configure against proxy server "myproxy:70".
5636 session_deps_.proxy_resolution_service =
5637 ConfiguredProxyResolutionService::CreateFixedFromPacResultForTest(
5638 "PROXY myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
5639
5640 auto auth_handler_factory = std::make_unique<HttpAuthHandlerMock::Factory>();
5641 auth_handler_factory->set_do_init_from_challenge(true);
5642
5643 // Create two mock AuthHandlers. This is because the transaction gets retried
5644 // after the first ERR_CONNECTION_CLOSED since it's ambiguous whether there
5645 // was a real network error.
5646 //
5647 // The handlers support both default and explicit credentials. The retry
5648 // mentioned above should be able to reuse the default identity. Thus there
5649 // should never be a need to prompt for explicit credentials.
5650 auto mock_handler = std::make_unique<HttpAuthHandlerMock>();
5651 mock_handler->set_allows_default_credentials(true);
5652 mock_handler->set_allows_explicit_credentials(true);
5653 mock_handler->set_connection_based(true);
5654 auth_handler_factory->AddMockHandler(std::move(mock_handler),
5655 HttpAuth::AUTH_PROXY);
5656 mock_handler = std::make_unique<HttpAuthHandlerMock>();
5657 mock_handler->set_allows_default_credentials(true);
5658 mock_handler->set_allows_explicit_credentials(true);
5659 mock_handler->set_connection_based(true);
5660 auth_handler_factory->AddMockHandler(std::move(mock_handler),
5661 HttpAuth::AUTH_PROXY);
5662 session_deps_.http_auth_handler_factory = std::move(auth_handler_factory);
5663
5664 session_deps_.net_log = NetLog::Get();
5665 std::unique_ptr<HttpNetworkSession> session = CreateSession(&session_deps_);
5666
5667 // Data for both sockets.
5668 //
5669 // Writes are for the tunnel establishment attempts and the
5670 // authentication handshake.
5671 MockWrite data_writes1[] = {
5672 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
5673 "Host: www.example.org:443\r\n"
5674 "Proxy-Connection: keep-alive\r\n\r\n"),
5675
5676 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
5677 "Host: www.example.org:443\r\n"
5678 "Proxy-Connection: keep-alive\r\n"
5679 "Proxy-Authorization: auth_token\r\n\r\n"),
5680
5681 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
5682 "Host: www.example.org:443\r\n"
5683 "Proxy-Connection: keep-alive\r\n"
5684 "Proxy-Authorization: auth_token\r\n\r\n"),
5685 };
5686
5687 // The server side of the authentication handshake. Note that the response to
5688 // the final CONNECT request is ERR_CONNECTION_CLOSED.
5689 MockRead data_reads1[] = {
5690 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
5691 MockRead("Content-Length: 0\r\n"),
5692 MockRead("Proxy-Connection: keep-alive\r\n"),
5693 MockRead("Proxy-Authenticate: Mock\r\n\r\n"),
5694
5695 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
5696 MockRead("Content-Length: 0\r\n"),
5697 MockRead("Proxy-Connection: keep-alive\r\n"),
5698 MockRead("Proxy-Authenticate: Mock foo\r\n\r\n"),
5699
5700 MockRead(SYNCHRONOUS, ERR_CONNECTION_CLOSED),
5701 };
5702
5703 StaticSocketDataProvider data1(data_reads1, data_writes1);
5704 session_deps_.socket_factory->AddSocketDataProvider(&data1);
5705
5706 // The second socket is for the reconnection attempt. Data is identical to the
5707 // first attempt.
5708 StaticSocketDataProvider data2(data_reads1, data_writes1);
5709 session_deps_.socket_factory->AddSocketDataProvider(&data2);
5710
5711 auto trans =
5712 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
5713
5714 TestCompletionCallback callback;
5715 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
5716
5717 // Two rounds per handshake. After one retry, the error is propagated up the
5718 // stack.
5719 for (int i = 0; i < 4; ++i) {
5720 EXPECT_THAT(callback.GetResult(rv), IsOk());
5721
5722 const HttpResponseInfo* response = trans->GetResponseInfo();
5723 ASSERT_TRUE(response);
5724 ASSERT_TRUE(response->headers);
5725 EXPECT_EQ(407, response->headers->response_code());
5726 ASSERT_TRUE(trans->IsReadyToRestartForAuth());
5727
5728 rv = trans->RestartWithAuth(AuthCredentials(), callback.callback());
5729 }
5730
5731 // One shall be the number thou shalt retry, and the number of the retrying
5732 // shall be one. Two shalt thou not retry, neither retry thou zero, excepting
5733 // that thou then proceed to one. Three is right out. Once the number one,
5734 // being the first number, be reached, then lobbest thou thy
5735 // ERR_CONNECTION_CLOSED towards they network transaction, who shall snuff it.
5736 EXPECT_EQ(ERR_CONNECTION_CLOSED, callback.GetResult(rv));
5737
5738 trans.reset();
5739 session->CloseAllConnections(ERR_FAILED, "Very good reason");
5740 }
5741
5742 // Test a proxy auth scheme that allows default credentials and a proxy server
5743 // that hangs up when credentials are initially sent, and sends a challenge
5744 // again they are retried.
TEST_P(HttpNetworkTransactionTest,AuthAllowsDefaultCredentialsTunnelServerChallengesTwice)5745 TEST_P(HttpNetworkTransactionTest,
5746 AuthAllowsDefaultCredentialsTunnelServerChallengesTwice) {
5747 HttpRequestInfo request;
5748 request.method = "GET";
5749 request.url = GURL("https://www.example.org/");
5750 request.traffic_annotation =
5751 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
5752
5753 // Configure against proxy server "myproxy:70".
5754 session_deps_.proxy_resolution_service =
5755 ConfiguredProxyResolutionService::CreateFixedFromPacResultForTest(
5756 "PROXY myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
5757
5758 auto auth_handler_factory = std::make_unique<HttpAuthHandlerMock::Factory>();
5759 auth_handler_factory->set_do_init_from_challenge(true);
5760 auto mock_handler = std::make_unique<HttpAuthHandlerMock>();
5761 mock_handler->set_allows_default_credentials(true);
5762 auth_handler_factory->AddMockHandler(std::move(mock_handler),
5763 HttpAuth::AUTH_PROXY);
5764 // Add another handler for the second challenge. It supports default
5765 // credentials, but they shouldn't be used, since they were already tried.
5766 mock_handler = std::make_unique<HttpAuthHandlerMock>();
5767 mock_handler->set_allows_default_credentials(true);
5768 auth_handler_factory->AddMockHandler(std::move(mock_handler),
5769 HttpAuth::AUTH_PROXY);
5770 session_deps_.http_auth_handler_factory = std::move(auth_handler_factory);
5771
5772 // Add NetLog just so can verify load timing information gets a NetLog ID.
5773 session_deps_.net_log = NetLog::Get();
5774 std::unique_ptr<HttpNetworkSession> session = CreateSession(&session_deps_);
5775
5776 // Should try to establish tunnel.
5777 MockWrite data_writes1[] = {
5778 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
5779 "Host: www.example.org:443\r\n"
5780 "Proxy-Connection: keep-alive\r\n\r\n"),
5781 };
5782
5783 // The proxy responds to the connect with a 407, using a non-persistent
5784 // connection.
5785 MockRead data_reads1[] = {
5786 // No credentials.
5787 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
5788 MockRead("Proxy-Authenticate: Mock\r\n"),
5789 MockRead("Proxy-Connection: close\r\n\r\n"),
5790 };
5791
5792 // Since the first connection was closed, need to establish another once given
5793 // credentials.
5794 MockWrite data_writes2[] = {
5795 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
5796 "Host: www.example.org:443\r\n"
5797 "Proxy-Connection: keep-alive\r\n"
5798 "Proxy-Authorization: auth_token\r\n\r\n"),
5799 };
5800
5801 MockRead data_reads2[] = {
5802 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
5803 MockRead("Proxy-Authenticate: Mock\r\n"),
5804 MockRead("Proxy-Connection: close\r\n\r\n"),
5805 };
5806
5807 StaticSocketDataProvider data1(data_reads1, data_writes1);
5808 session_deps_.socket_factory->AddSocketDataProvider(&data1);
5809 StaticSocketDataProvider data2(data_reads2, data_writes2);
5810 session_deps_.socket_factory->AddSocketDataProvider(&data2);
5811 SSLSocketDataProvider ssl(ASYNC, OK);
5812 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
5813
5814 auto trans =
5815 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
5816
5817 TestCompletionCallback callback;
5818 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
5819 EXPECT_THAT(callback.GetResult(rv), IsOk());
5820
5821 const HttpResponseInfo* response = trans->GetResponseInfo();
5822 ASSERT_TRUE(response);
5823 ASSERT_TRUE(response->headers);
5824 EXPECT_EQ(407, response->headers->response_code());
5825 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
5826 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
5827 EXPECT_FALSE(response->auth_challenge.has_value());
5828
5829 LoadTimingInfo load_timing_info;
5830 EXPECT_FALSE(trans->GetLoadTimingInfo(&load_timing_info));
5831
5832 rv = trans->RestartWithAuth(AuthCredentials(), callback.callback());
5833 EXPECT_THAT(callback.GetResult(rv), IsOk());
5834 response = trans->GetResponseInfo();
5835 ASSERT_TRUE(response);
5836 ASSERT_TRUE(response->headers);
5837 EXPECT_EQ(407, response->headers->response_code());
5838 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
5839 EXPECT_TRUE(response->auth_challenge.has_value());
5840
5841 trans.reset();
5842 session->CloseAllConnections(ERR_FAILED, "Very good reason");
5843 }
5844
5845 // A more nuanced test than GenerateAuthToken test which asserts that
5846 // ERR_INVALID_AUTH_CREDENTIALS does not cause the auth scheme to be
5847 // unnecessarily invalidated, and that if the server co-operates, the
5848 // authentication handshake can continue with the same scheme but with a
5849 // different identity.
TEST_P(HttpNetworkTransactionTest,NonPermanentGenerateAuthTokenError)5850 TEST_P(HttpNetworkTransactionTest, NonPermanentGenerateAuthTokenError) {
5851 HttpRequestInfo request;
5852 request.method = "GET";
5853 request.url = GURL("http://www.example.org/");
5854 request.traffic_annotation =
5855 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
5856
5857 auto auth_handler_factory = std::make_unique<HttpAuthHandlerMock::Factory>();
5858 auth_handler_factory->set_do_init_from_challenge(true);
5859
5860 // First handler. Uses default credentials, but barfs at generate auth token.
5861 auto mock_handler = std::make_unique<HttpAuthHandlerMock>();
5862 mock_handler->set_allows_default_credentials(true);
5863 mock_handler->set_allows_explicit_credentials(true);
5864 mock_handler->set_connection_based(true);
5865 mock_handler->SetGenerateExpectation(true, ERR_INVALID_AUTH_CREDENTIALS);
5866 auth_handler_factory->AddMockHandler(std::move(mock_handler),
5867 HttpAuth::AUTH_SERVER);
5868
5869 // Add another handler for the second challenge. It supports default
5870 // credentials, but they shouldn't be used, since they were already tried.
5871 mock_handler = std::make_unique<HttpAuthHandlerMock>();
5872 mock_handler->set_allows_default_credentials(true);
5873 mock_handler->set_allows_explicit_credentials(true);
5874 mock_handler->set_connection_based(true);
5875 auth_handler_factory->AddMockHandler(std::move(mock_handler),
5876 HttpAuth::AUTH_SERVER);
5877 session_deps_.http_auth_handler_factory = std::move(auth_handler_factory);
5878
5879 std::unique_ptr<HttpNetworkSession> session = CreateSession(&session_deps_);
5880
5881 MockWrite data_writes1[] = {
5882 MockWrite("GET / HTTP/1.1\r\n"
5883 "Host: www.example.org\r\n"
5884 "Connection: keep-alive\r\n\r\n"),
5885 };
5886
5887 MockRead data_reads1[] = {
5888 MockRead("HTTP/1.1 401 Authentication Required\r\n"
5889 "WWW-Authenticate: Mock\r\n"
5890 "Connection: keep-alive\r\n\r\n"),
5891 };
5892
5893 // Identical to data_writes1[]. The AuthHandler encounters a
5894 // ERR_INVALID_AUTH_CREDENTIALS during the GenerateAuthToken stage, so the
5895 // transaction procceds without an authorization header.
5896 MockWrite data_writes2[] = {
5897 MockWrite("GET / HTTP/1.1\r\n"
5898 "Host: www.example.org\r\n"
5899 "Connection: keep-alive\r\n\r\n"),
5900 };
5901
5902 MockRead data_reads2[] = {
5903 MockRead("HTTP/1.1 401 Authentication Required\r\n"
5904 "WWW-Authenticate: Mock\r\n"
5905 "Connection: keep-alive\r\n\r\n"),
5906 };
5907
5908 MockWrite data_writes3[] = {
5909 MockWrite("GET / HTTP/1.1\r\n"
5910 "Host: www.example.org\r\n"
5911 "Connection: keep-alive\r\n"
5912 "Authorization: auth_token\r\n\r\n"),
5913 };
5914
5915 MockRead data_reads3[] = {
5916 MockRead("HTTP/1.1 200 OK\r\n"
5917 "Content-Length: 5\r\n"
5918 "Content-Type: text/plain\r\n"
5919 "Connection: keep-alive\r\n\r\n"
5920 "Hello"),
5921 };
5922
5923 StaticSocketDataProvider data1(data_reads1, data_writes1);
5924 session_deps_.socket_factory->AddSocketDataProvider(&data1);
5925
5926 StaticSocketDataProvider data2(data_reads2, data_writes2);
5927 session_deps_.socket_factory->AddSocketDataProvider(&data2);
5928
5929 StaticSocketDataProvider data3(data_reads3, data_writes3);
5930 session_deps_.socket_factory->AddSocketDataProvider(&data3);
5931
5932 auto trans =
5933 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
5934
5935 TestCompletionCallback callback;
5936 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
5937 EXPECT_THAT(callback.GetResult(rv), IsOk());
5938
5939 const HttpResponseInfo* response = trans->GetResponseInfo();
5940 ASSERT_TRUE(response);
5941 ASSERT_TRUE(response->headers);
5942 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
5943
5944 // The following three tests assert that an authentication challenge was
5945 // received and that the stack is ready to respond to the challenge using
5946 // ambient credentials.
5947 EXPECT_EQ(401, response->headers->response_code());
5948 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
5949 EXPECT_FALSE(response->auth_challenge.has_value());
5950
5951 rv = trans->RestartWithAuth(AuthCredentials(), callback.callback());
5952 EXPECT_THAT(callback.GetResult(rv), IsOk());
5953 response = trans->GetResponseInfo();
5954 ASSERT_TRUE(response);
5955 ASSERT_TRUE(response->headers);
5956
5957 // The following three tests assert that an authentication challenge was
5958 // received and that the stack needs explicit credentials before it is ready
5959 // to respond to the challenge.
5960 EXPECT_EQ(401, response->headers->response_code());
5961 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
5962 EXPECT_TRUE(response->auth_challenge.has_value());
5963
5964 rv = trans->RestartWithAuth(AuthCredentials(), callback.callback());
5965 EXPECT_THAT(callback.GetResult(rv), IsOk());
5966 response = trans->GetResponseInfo();
5967 ASSERT_TRUE(response);
5968 ASSERT_TRUE(response->headers);
5969 EXPECT_EQ(200, response->headers->response_code());
5970
5971 trans.reset();
5972 session->CloseAllConnections(ERR_FAILED, "Very good reason");
5973 }
5974
5975 // Proxy resolver that returns a proxy with the same host and port for different
5976 // schemes, based on the path of the URL being requests.
5977 class SameProxyWithDifferentSchemesProxyResolver : public ProxyResolver {
5978 public:
5979 SameProxyWithDifferentSchemesProxyResolver() = default;
5980
5981 SameProxyWithDifferentSchemesProxyResolver(
5982 const SameProxyWithDifferentSchemesProxyResolver&) = delete;
5983 SameProxyWithDifferentSchemesProxyResolver& operator=(
5984 const SameProxyWithDifferentSchemesProxyResolver&) = delete;
5985
5986 ~SameProxyWithDifferentSchemesProxyResolver() override = default;
5987
5988 static constexpr uint16_t kProxyPort = 10000;
5989
ProxyHostPortPair()5990 static HostPortPair ProxyHostPortPair() {
5991 return HostPortPair("proxy.test", kProxyPort);
5992 }
5993
ProxyHostPortPairAsString()5994 static std::string ProxyHostPortPairAsString() {
5995 return ProxyHostPortPair().ToString();
5996 }
5997
5998 // ProxyResolver implementation.
GetProxyForURL(const GURL & url,const NetworkAnonymizationKey & network_anonymization_key,ProxyInfo * results,CompletionOnceCallback callback,std::unique_ptr<Request> * request,const NetLogWithSource &)5999 int GetProxyForURL(const GURL& url,
6000 const NetworkAnonymizationKey& network_anonymization_key,
6001 ProxyInfo* results,
6002 CompletionOnceCallback callback,
6003 std::unique_ptr<Request>* request,
6004 const NetLogWithSource& /*net_log*/) override {
6005 *results = ProxyInfo();
6006 results->set_traffic_annotation(
6007 MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS));
6008 if (url.path() == "/socks4") {
6009 results->UsePacString("SOCKS " + ProxyHostPortPairAsString());
6010 return OK;
6011 }
6012 if (url.path() == "/socks5") {
6013 results->UsePacString("SOCKS5 " + ProxyHostPortPairAsString());
6014 return OK;
6015 }
6016 if (url.path() == "/http") {
6017 results->UsePacString("PROXY " + ProxyHostPortPairAsString());
6018 return OK;
6019 }
6020 if (url.path() == "/https") {
6021 results->UsePacString("HTTPS " + ProxyHostPortPairAsString());
6022 return OK;
6023 }
6024 NOTREACHED();
6025 return ERR_NOT_IMPLEMENTED;
6026 }
6027 };
6028
6029 class SameProxyWithDifferentSchemesProxyResolverFactory
6030 : public ProxyResolverFactory {
6031 public:
SameProxyWithDifferentSchemesProxyResolverFactory()6032 SameProxyWithDifferentSchemesProxyResolverFactory()
6033 : ProxyResolverFactory(false) {}
6034
6035 SameProxyWithDifferentSchemesProxyResolverFactory(
6036 const SameProxyWithDifferentSchemesProxyResolverFactory&) = delete;
6037 SameProxyWithDifferentSchemesProxyResolverFactory& operator=(
6038 const SameProxyWithDifferentSchemesProxyResolverFactory&) = delete;
6039
CreateProxyResolver(const scoped_refptr<PacFileData> & pac_script,std::unique_ptr<ProxyResolver> * resolver,CompletionOnceCallback callback,std::unique_ptr<Request> * request)6040 int CreateProxyResolver(const scoped_refptr<PacFileData>& pac_script,
6041 std::unique_ptr<ProxyResolver>* resolver,
6042 CompletionOnceCallback callback,
6043 std::unique_ptr<Request>* request) override {
6044 *resolver = std::make_unique<SameProxyWithDifferentSchemesProxyResolver>();
6045 return OK;
6046 }
6047 };
6048
6049 // Check that when different proxy schemes are all applied to a proxy at the
6050 // same address, the connections are not grouped together. i.e., a request to
6051 // foo.com using proxy.com as an HTTPS proxy won't use the same socket as a
6052 // request to foo.com using proxy.com as an HTTP proxy.
TEST_P(HttpNetworkTransactionTest,SameDestinationForDifferentProxyTypes)6053 TEST_P(HttpNetworkTransactionTest, SameDestinationForDifferentProxyTypes) {
6054 session_deps_.proxy_resolution_service =
6055 std::make_unique<ConfiguredProxyResolutionService>(
6056 std::make_unique<ProxyConfigServiceFixed>(ProxyConfigWithAnnotation(
6057 ProxyConfig::CreateAutoDetect(), TRAFFIC_ANNOTATION_FOR_TESTS)),
6058 std::make_unique<SameProxyWithDifferentSchemesProxyResolverFactory>(),
6059 nullptr, /*quick_check_enabled=*/true);
6060
6061 std::unique_ptr<HttpNetworkSession> session = CreateSession(&session_deps_);
6062
6063 MockWrite socks_writes[] = {
6064 MockWrite(SYNCHRONOUS, kSOCKS4OkRequestLocalHostPort80,
6065 kSOCKS4OkRequestLocalHostPort80Length),
6066 MockWrite(SYNCHRONOUS,
6067 "GET /socks4 HTTP/1.1\r\n"
6068 "Host: test\r\n"
6069 "Connection: keep-alive\r\n\r\n"),
6070 };
6071 MockRead socks_reads[] = {
6072 MockRead(SYNCHRONOUS, kSOCKS4OkReply, kSOCKS4OkReplyLength),
6073 MockRead("HTTP/1.0 200 OK\r\n"
6074 "Connection: keep-alive\r\n"
6075 "Content-Length: 15\r\n\r\n"
6076 "SOCKS4 Response"),
6077 };
6078 StaticSocketDataProvider socks_data(socks_reads, socks_writes);
6079 session_deps_.socket_factory->AddSocketDataProvider(&socks_data);
6080
6081 const char kSOCKS5Request[] = {
6082 0x05, // Version
6083 0x01, // Command (CONNECT)
6084 0x00, // Reserved
6085 0x03, // Address type (DOMAINNAME)
6086 0x04, // Length of domain (4)
6087 't', 'e', 's', 't', // Domain string
6088 0x00, 0x50, // 16-bit port (80)
6089 };
6090 MockWrite socks5_writes[] = {
6091 MockWrite(ASYNC, kSOCKS5GreetRequest, kSOCKS5GreetRequestLength),
6092 MockWrite(ASYNC, kSOCKS5Request, std::size(kSOCKS5Request)),
6093 MockWrite(SYNCHRONOUS,
6094 "GET /socks5 HTTP/1.1\r\n"
6095 "Host: test\r\n"
6096 "Connection: keep-alive\r\n\r\n"),
6097 };
6098 MockRead socks5_reads[] = {
6099 MockRead(ASYNC, kSOCKS5GreetResponse, kSOCKS5GreetResponseLength),
6100 MockRead(ASYNC, kSOCKS5OkResponse, kSOCKS5OkResponseLength),
6101 MockRead("HTTP/1.0 200 OK\r\n"
6102 "Connection: keep-alive\r\n"
6103 "Content-Length: 15\r\n\r\n"
6104 "SOCKS5 Response"),
6105 };
6106 StaticSocketDataProvider socks5_data(socks5_reads, socks5_writes);
6107 session_deps_.socket_factory->AddSocketDataProvider(&socks5_data);
6108
6109 MockWrite http_writes[] = {
6110 MockWrite(SYNCHRONOUS,
6111 "GET http://test/http HTTP/1.1\r\n"
6112 "Host: test\r\n"
6113 "Proxy-Connection: keep-alive\r\n\r\n"),
6114 };
6115 MockRead http_reads[] = {
6116 MockRead("HTTP/1.1 200 OK\r\n"
6117 "Proxy-Connection: keep-alive\r\n"
6118 "Content-Length: 13\r\n\r\n"
6119 "HTTP Response"),
6120 };
6121 StaticSocketDataProvider http_data(http_reads, http_writes);
6122 session_deps_.socket_factory->AddSocketDataProvider(&http_data);
6123
6124 MockWrite https_writes[] = {
6125 MockWrite(SYNCHRONOUS,
6126 "GET http://test/https HTTP/1.1\r\n"
6127 "Host: test\r\n"
6128 "Proxy-Connection: keep-alive\r\n\r\n"),
6129 };
6130 MockRead https_reads[] = {
6131 MockRead("HTTP/1.1 200 OK\r\n"
6132 "Proxy-Connection: keep-alive\r\n"
6133 "Content-Length: 14\r\n\r\n"
6134 "HTTPS Response"),
6135 };
6136 StaticSocketDataProvider https_data(https_reads, https_writes);
6137 session_deps_.socket_factory->AddSocketDataProvider(&https_data);
6138 SSLSocketDataProvider ssl(SYNCHRONOUS, OK);
6139 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
6140
6141 SSLSocketDataProvider ssl2(SYNCHRONOUS, OK);
6142 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
6143
6144 struct TestCase {
6145 GURL url;
6146 std::string expected_response;
6147 // How many idle sockets there should be in the SOCKS 4/5 proxy socket pools
6148 // after the test.
6149 int expected_idle_socks4_sockets;
6150 int expected_idle_socks5_sockets;
6151 // How many idle sockets there should be in the HTTP/HTTPS proxy socket
6152 // pools after the test.
6153 int expected_idle_http_sockets;
6154 int expected_idle_https_sockets;
6155 } const kTestCases[] = {
6156 {GURL("http://test/socks4"), "SOCKS4 Response", 1, 0, 0, 0},
6157 {GURL("http://test/socks5"), "SOCKS5 Response", 1, 1, 0, 0},
6158 {GURL("http://test/http"), "HTTP Response", 1, 1, 1, 0},
6159 {GURL("http://test/https"), "HTTPS Response", 1, 1, 1, 1},
6160 };
6161
6162 for (const auto& test_case : kTestCases) {
6163 SCOPED_TRACE(test_case.url);
6164
6165 HttpRequestInfo request;
6166 request.method = "GET";
6167 request.url = test_case.url;
6168 request.traffic_annotation =
6169 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
6170 ConnectedHandler connected_handler;
6171
6172 auto transaction = std::make_unique<HttpNetworkTransaction>(
6173 DEFAULT_PRIORITY, session.get());
6174
6175 transaction->SetConnectedCallback(connected_handler.Callback());
6176
6177 TestCompletionCallback callback;
6178 int rv =
6179 transaction->Start(&request, callback.callback(), NetLogWithSource());
6180 EXPECT_THAT(callback.GetResult(rv), IsOk());
6181
6182 const HttpResponseInfo* response = transaction->GetResponseInfo();
6183 ASSERT_TRUE(response);
6184 ASSERT_TRUE(response->headers);
6185 EXPECT_EQ(200, response->headers->response_code());
6186 std::string response_data;
6187 EXPECT_THAT(ReadTransaction(transaction.get(), &response_data), IsOk());
6188 EXPECT_EQ(test_case.expected_response, response_data);
6189
6190 TransportInfo expected_transport;
6191 expected_transport.type = TransportType::kProxied;
6192 expected_transport.endpoint =
6193 IPEndPoint(IPAddress::IPv4Localhost(),
6194 SameProxyWithDifferentSchemesProxyResolver::kProxyPort);
6195 expected_transport.negotiated_protocol = kProtoUnknown;
6196 EXPECT_THAT(connected_handler.transports(),
6197 ElementsAre(expected_transport));
6198
6199 // Return the socket to the socket pool, so can make sure it's not used for
6200 // the next requests.
6201 transaction.reset();
6202 base::RunLoop().RunUntilIdle();
6203
6204 // Check the number of idle sockets in the pool, to make sure that used
6205 // sockets are indeed being returned to the socket pool. If each request
6206 // doesn't return an idle socket to the pool, the test would incorrectly
6207 // pass.
6208 EXPECT_EQ(test_case.expected_idle_socks4_sockets,
6209 session
6210 ->GetSocketPool(
6211 HttpNetworkSession::NORMAL_SOCKET_POOL,
6212 ProxyChain(ProxyServer::SCHEME_SOCKS4,
6213 SameProxyWithDifferentSchemesProxyResolver::
6214 ProxyHostPortPair()))
6215 ->IdleSocketCount());
6216 EXPECT_EQ(test_case.expected_idle_socks5_sockets,
6217 session
6218 ->GetSocketPool(
6219 HttpNetworkSession::NORMAL_SOCKET_POOL,
6220 ProxyChain(ProxyServer::SCHEME_SOCKS5,
6221 SameProxyWithDifferentSchemesProxyResolver::
6222 ProxyHostPortPair()))
6223 ->IdleSocketCount());
6224 EXPECT_EQ(test_case.expected_idle_http_sockets,
6225 session
6226 ->GetSocketPool(
6227 HttpNetworkSession::NORMAL_SOCKET_POOL,
6228 ProxyChain(ProxyServer::SCHEME_HTTP,
6229 SameProxyWithDifferentSchemesProxyResolver::
6230 ProxyHostPortPair()))
6231 ->IdleSocketCount());
6232 EXPECT_EQ(test_case.expected_idle_https_sockets,
6233 session
6234 ->GetSocketPool(
6235 HttpNetworkSession::NORMAL_SOCKET_POOL,
6236 ProxyChain(ProxyServer::SCHEME_HTTPS,
6237 SameProxyWithDifferentSchemesProxyResolver::
6238 ProxyHostPortPair()))
6239 ->IdleSocketCount());
6240 }
6241 }
6242
6243 // Test the load timing for HTTPS requests with an HTTP proxy.
TEST_P(HttpNetworkTransactionTest,HttpProxyLoadTimingNoPacTwoRequests)6244 TEST_P(HttpNetworkTransactionTest, HttpProxyLoadTimingNoPacTwoRequests) {
6245 HttpRequestInfo request1;
6246 request1.method = "GET";
6247 request1.url = GURL("https://www.example.org/1");
6248 request1.traffic_annotation =
6249 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
6250
6251 HttpRequestInfo request2;
6252 request2.method = "GET";
6253 request2.url = GURL("https://www.example.org/2");
6254 request2.traffic_annotation =
6255 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
6256
6257 // Configure against proxy server "myproxy:70".
6258 session_deps_.proxy_resolution_service =
6259 ConfiguredProxyResolutionService::CreateFixedForTest(
6260 "myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
6261 NetLogWithSource net_log_with_source =
6262 NetLogWithSource::Make(NetLogSourceType::NONE);
6263 session_deps_.net_log = NetLog::Get();
6264 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
6265
6266 // Since we have proxy, should try to establish tunnel.
6267 MockWrite data_writes1[] = {
6268 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
6269 "Host: www.example.org:443\r\n"
6270 "Proxy-Connection: keep-alive\r\n\r\n"),
6271
6272 MockWrite("GET /1 HTTP/1.1\r\n"
6273 "Host: www.example.org\r\n"
6274 "Connection: keep-alive\r\n\r\n"),
6275
6276 MockWrite("GET /2 HTTP/1.1\r\n"
6277 "Host: www.example.org\r\n"
6278 "Connection: keep-alive\r\n\r\n"),
6279 };
6280
6281 // The proxy responds to the connect with a 407, using a persistent
6282 // connection.
6283 MockRead data_reads1[] = {
6284 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
6285
6286 MockRead("HTTP/1.1 200 OK\r\n"),
6287 MockRead("Content-Length: 1\r\n\r\n"),
6288 MockRead(SYNCHRONOUS, "1"),
6289
6290 MockRead("HTTP/1.1 200 OK\r\n"),
6291 MockRead("Content-Length: 2\r\n\r\n"),
6292 MockRead(SYNCHRONOUS, "22"),
6293 };
6294
6295 StaticSocketDataProvider data1(data_reads1, data_writes1);
6296 session_deps_.socket_factory->AddSocketDataProvider(&data1);
6297 SSLSocketDataProvider ssl(ASYNC, OK);
6298 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
6299
6300 TestCompletionCallback callback1;
6301 auto trans1 =
6302 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
6303
6304 int rv = trans1->Start(&request1, callback1.callback(), net_log_with_source);
6305 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
6306
6307 rv = callback1.WaitForResult();
6308 EXPECT_THAT(rv, IsOk());
6309
6310 const HttpResponseInfo* response1 = trans1->GetResponseInfo();
6311 ASSERT_TRUE(response1);
6312 ASSERT_EQ(1u, response1->proxy_chain.length());
6313 EXPECT_TRUE(response1->proxy_chain.GetProxyServer(0).is_http());
6314 ASSERT_TRUE(response1->headers);
6315 EXPECT_EQ(1, response1->headers->GetContentLength());
6316
6317 LoadTimingInfo load_timing_info1;
6318 EXPECT_TRUE(trans1->GetLoadTimingInfo(&load_timing_info1));
6319 TestLoadTimingNotReused(load_timing_info1, CONNECT_TIMING_HAS_SSL_TIMES);
6320
6321 trans1.reset();
6322
6323 TestCompletionCallback callback2;
6324 auto trans2 =
6325 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
6326
6327 rv = trans2->Start(&request2, callback2.callback(), net_log_with_source);
6328 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
6329
6330 rv = callback2.WaitForResult();
6331 EXPECT_THAT(rv, IsOk());
6332
6333 const HttpResponseInfo* response2 = trans2->GetResponseInfo();
6334 ASSERT_TRUE(response2);
6335 ASSERT_EQ(1u, response2->proxy_chain.length());
6336 EXPECT_TRUE(response2->proxy_chain.GetProxyServer(0).is_http());
6337 ASSERT_TRUE(response2->headers);
6338 EXPECT_EQ(2, response2->headers->GetContentLength());
6339
6340 LoadTimingInfo load_timing_info2;
6341 EXPECT_TRUE(trans2->GetLoadTimingInfo(&load_timing_info2));
6342 TestLoadTimingReused(load_timing_info2);
6343
6344 EXPECT_EQ(load_timing_info1.socket_log_id, load_timing_info2.socket_log_id);
6345
6346 trans2.reset();
6347 session->CloseAllConnections(ERR_FAILED, "Very good reason");
6348 }
6349
6350 // Test the load timing for HTTPS requests with an HTTP proxy and a PAC script.
TEST_P(HttpNetworkTransactionTest,HttpProxyLoadTimingWithPacTwoRequests)6351 TEST_P(HttpNetworkTransactionTest, HttpProxyLoadTimingWithPacTwoRequests) {
6352 HttpRequestInfo request1;
6353 request1.method = "GET";
6354 request1.url = GURL("https://www.example.org/1");
6355 request1.traffic_annotation =
6356 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
6357
6358 HttpRequestInfo request2;
6359 request2.method = "GET";
6360 request2.url = GURL("https://www.example.org/2");
6361 request2.traffic_annotation =
6362 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
6363
6364 // Configure against proxy server "myproxy:70".
6365 session_deps_.proxy_resolution_service =
6366 ConfiguredProxyResolutionService::CreateFixedFromPacResultForTest(
6367 "PROXY myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
6368 NetLogWithSource net_log_with_source =
6369 NetLogWithSource::Make(NetLogSourceType::NONE);
6370 session_deps_.net_log = NetLog::Get();
6371 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
6372
6373 // Since we have proxy, should try to establish tunnel.
6374 MockWrite data_writes1[] = {
6375 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
6376 "Host: www.example.org:443\r\n"
6377 "Proxy-Connection: keep-alive\r\n\r\n"),
6378
6379 MockWrite("GET /1 HTTP/1.1\r\n"
6380 "Host: www.example.org\r\n"
6381 "Connection: keep-alive\r\n\r\n"),
6382
6383 MockWrite("GET /2 HTTP/1.1\r\n"
6384 "Host: www.example.org\r\n"
6385 "Connection: keep-alive\r\n\r\n"),
6386 };
6387
6388 // The proxy responds to the connect with a 407, using a persistent
6389 // connection.
6390 MockRead data_reads1[] = {
6391 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
6392
6393 MockRead("HTTP/1.1 200 OK\r\n"),
6394 MockRead("Content-Length: 1\r\n\r\n"),
6395 MockRead(SYNCHRONOUS, "1"),
6396
6397 MockRead("HTTP/1.1 200 OK\r\n"),
6398 MockRead("Content-Length: 2\r\n\r\n"),
6399 MockRead(SYNCHRONOUS, "22"),
6400 };
6401
6402 StaticSocketDataProvider data1(data_reads1, data_writes1);
6403 session_deps_.socket_factory->AddSocketDataProvider(&data1);
6404 SSLSocketDataProvider ssl(ASYNC, OK);
6405 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
6406
6407 TestCompletionCallback callback1;
6408 auto trans1 =
6409 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
6410
6411 int rv = trans1->Start(&request1, callback1.callback(), net_log_with_source);
6412 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
6413
6414 rv = callback1.WaitForResult();
6415 EXPECT_THAT(rv, IsOk());
6416
6417 const HttpResponseInfo* response1 = trans1->GetResponseInfo();
6418 ASSERT_TRUE(response1);
6419 ASSERT_TRUE(response1->headers);
6420 EXPECT_EQ(1, response1->headers->GetContentLength());
6421
6422 LoadTimingInfo load_timing_info1;
6423 EXPECT_TRUE(trans1->GetLoadTimingInfo(&load_timing_info1));
6424 TestLoadTimingNotReusedWithPac(load_timing_info1,
6425 CONNECT_TIMING_HAS_SSL_TIMES);
6426
6427 trans1.reset();
6428
6429 TestCompletionCallback callback2;
6430 auto trans2 =
6431 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
6432
6433 rv = trans2->Start(&request2, callback2.callback(), net_log_with_source);
6434 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
6435
6436 rv = callback2.WaitForResult();
6437 EXPECT_THAT(rv, IsOk());
6438
6439 const HttpResponseInfo* response2 = trans2->GetResponseInfo();
6440 ASSERT_TRUE(response2);
6441 ASSERT_TRUE(response2->headers);
6442 EXPECT_EQ(2, response2->headers->GetContentLength());
6443
6444 LoadTimingInfo load_timing_info2;
6445 EXPECT_TRUE(trans2->GetLoadTimingInfo(&load_timing_info2));
6446 TestLoadTimingReusedWithPac(load_timing_info2);
6447
6448 EXPECT_EQ(load_timing_info1.socket_log_id, load_timing_info2.socket_log_id);
6449
6450 trans2.reset();
6451 session->CloseAllConnections(ERR_FAILED, "Very good reason");
6452 }
6453
6454 // Make sure that NetworkAnonymizationKeys are passed down to the proxy layer.
TEST_P(HttpNetworkTransactionTest,ProxyResolvedWithNetworkAnonymizationKey)6455 TEST_P(HttpNetworkTransactionTest, ProxyResolvedWithNetworkAnonymizationKey) {
6456 const SchemefulSite kSite(GURL("https://foo.test/"));
6457 const SchemefulSite kOtherSite(GURL("https://bar.test/"));
6458 const NetworkIsolationKey kNetworkIsolationKey =
6459 NetworkIsolationKey(kSite, kOtherSite);
6460 const NetworkAnonymizationKey kNetworkAnonymizationKey =
6461 NetworkAnonymizationKey::CreateFromNetworkIsolationKey(
6462 kNetworkIsolationKey);
6463
6464 ProxyConfig proxy_config;
6465 proxy_config.set_auto_detect(true);
6466 proxy_config.set_pac_url(GURL("http://fooproxyurl"));
6467
6468 CapturingProxyResolver capturing_proxy_resolver;
6469 capturing_proxy_resolver.set_proxy_chain(ProxyChain::Direct());
6470 session_deps_.proxy_resolution_service =
6471 std::make_unique<ConfiguredProxyResolutionService>(
6472 std::make_unique<ProxyConfigServiceFixed>(ProxyConfigWithAnnotation(
6473 proxy_config, TRAFFIC_ANNOTATION_FOR_TESTS)),
6474 std::make_unique<CapturingProxyResolverFactory>(
6475 &capturing_proxy_resolver),
6476 nullptr, /*quick_check_enabled=*/true);
6477
6478 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
6479
6480 // No need to continue with the network request - proxy resolution occurs
6481 // before establishing a data.
6482 StaticSocketDataProvider data{base::span<MockRead>(),
6483 base::span<MockWrite>()};
6484 data.set_connect_data(MockConnect(SYNCHRONOUS, ERR_FAILED));
6485 session_deps_.socket_factory->AddSocketDataProvider(&data);
6486
6487 // Run first request until an auth challenge is observed.
6488 HttpRequestInfo request;
6489 request.method = "GET";
6490 request.url = GURL("http://foo.test/");
6491 request.traffic_annotation =
6492 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
6493 request.network_isolation_key = kNetworkIsolationKey;
6494 request.network_anonymization_key = kNetworkAnonymizationKey;
6495 HttpNetworkTransaction trans(LOWEST, session.get());
6496 TestCompletionCallback callback;
6497 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
6498 EXPECT_THAT(callback.GetResult(rv), IsError(ERR_FAILED));
6499
6500 ASSERT_EQ(1u, capturing_proxy_resolver.lookup_info().size());
6501 ASSERT_EQ(
6502 kNetworkAnonymizationKey,
6503 capturing_proxy_resolver.lookup_info()[0].network_anonymization_key);
6504 ASSERT_EQ(request.url, capturing_proxy_resolver.lookup_info()[0].url);
6505 }
6506
6507 // Test that a failure in resolving the proxy hostname is retrievable.
TEST_P(HttpNetworkTransactionTest,ProxyHostResolutionFailure)6508 TEST_P(HttpNetworkTransactionTest, ProxyHostResolutionFailure) {
6509 HttpRequestInfo request;
6510 request.method = "GET";
6511 request.url = GURL("http://www.example.org/");
6512 request.traffic_annotation =
6513 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
6514
6515 // Configure against https proxy server "proxy:70".
6516 session_deps_.proxy_resolution_service =
6517 ConfiguredProxyResolutionService::CreateFixedForTest(
6518 "https://proxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
6519 auto resolver = std::make_unique<MockHostResolver>();
6520 resolver->rules()->AddSimulatedTimeoutFailure("proxy");
6521 session_deps_.net_log = net::NetLog::Get();
6522 session_deps_.host_resolver = std::move(resolver);
6523 std::unique_ptr<HttpNetworkSession> session = CreateSession(&session_deps_);
6524 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
6525 TestCompletionCallback callback;
6526
6527 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
6528 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
6529 EXPECT_THAT(callback.WaitForResult(), IsError(ERR_PROXY_CONNECTION_FAILED));
6530
6531 const HttpResponseInfo* response = trans.GetResponseInfo();
6532 ASSERT_TRUE(response);
6533 EXPECT_THAT(response->resolve_error_info.error, IsError(ERR_DNS_TIMED_OUT));
6534 }
6535
6536 // Test a simple GET (for an HTTP endpoint) through an HTTPS Proxy
6537 // (HTTPS -> HTTP).
TEST_P(HttpNetworkTransactionTest,HttpsProxyGet)6538 TEST_P(HttpNetworkTransactionTest, HttpsProxyGet) {
6539 HttpRequestInfo request;
6540 request.method = "GET";
6541 request.url = GURL("http://www.example.org/");
6542 request.traffic_annotation =
6543 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
6544
6545 // Configure against https proxy server "proxy:70".
6546 session_deps_.proxy_resolution_service =
6547 ConfiguredProxyResolutionService::CreateFixedForTest(
6548 "https://proxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
6549 session_deps_.net_log = NetLog::Get();
6550 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
6551
6552 // Since we have proxy, should use full url
6553 MockWrite data_writes1[] = {
6554 MockWrite("GET http://www.example.org/ HTTP/1.1\r\n"
6555 "Host: www.example.org\r\n"
6556 "Proxy-Connection: keep-alive\r\n\r\n"),
6557 };
6558
6559 MockRead data_reads1[] = {
6560 MockRead("HTTP/1.1 200 OK\r\n"),
6561 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
6562 MockRead("Content-Length: 100\r\n\r\n"),
6563 MockRead(SYNCHRONOUS, OK),
6564 };
6565
6566 StaticSocketDataProvider data1(data_reads1, data_writes1);
6567 session_deps_.socket_factory->AddSocketDataProvider(&data1);
6568 SSLSocketDataProvider ssl(ASYNC, OK);
6569 ssl.ssl_info.cert =
6570 ImportCertFromFile(GetTestCertsDirectory(), "ok_cert.pem");
6571 ASSERT_TRUE(ssl.ssl_info.cert);
6572 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
6573
6574 ConnectedHandler connected_handler;
6575 TestCompletionCallback callback;
6576
6577 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
6578
6579 trans.SetConnectedCallback(connected_handler.Callback());
6580
6581 int rv = trans.Start(&request, callback.callback(),
6582 NetLogWithSource::Make(NetLogSourceType::NONE));
6583 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
6584
6585 rv = callback.WaitForResult();
6586 EXPECT_THAT(rv, IsOk());
6587
6588 LoadTimingInfo load_timing_info;
6589 EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info));
6590 TestLoadTimingNotReused(load_timing_info,
6591 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY);
6592
6593 const HttpResponseInfo* response = trans.GetResponseInfo();
6594 ASSERT_TRUE(response);
6595
6596 ASSERT_EQ(1u, response->proxy_chain.length());
6597 EXPECT_TRUE(response->proxy_chain.GetProxyServer(0).is_https());
6598 EXPECT_TRUE(response->headers->IsKeepAlive());
6599 EXPECT_EQ(200, response->headers->response_code());
6600 EXPECT_EQ(100, response->headers->GetContentLength());
6601 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
6602
6603 // DNS aliases should be empty when using a proxy.
6604 EXPECT_TRUE(response->dns_aliases.empty());
6605
6606 TransportInfo expected_transport;
6607 expected_transport.type = TransportType::kProxied;
6608 expected_transport.endpoint = IPEndPoint(IPAddress::IPv4Localhost(), 70);
6609 expected_transport.negotiated_protocol = kProtoUnknown;
6610 EXPECT_THAT(connected_handler.transports(), ElementsAre(expected_transport));
6611
6612 // The password prompt info should not be set.
6613 EXPECT_FALSE(response->auth_challenge.has_value());
6614
6615 // Although we use an HTTPS proxy, the `SSLInfo` from that connection should
6616 // not be reported as a property of the origin.
6617 EXPECT_FALSE(response->ssl_info.cert);
6618 }
6619
6620 // Test a simple GET (for an HTTP endpoint) through two HTTPS proxies
6621 // (HTTPS -> HTTPS -> HTTP). This should tunnel through both proxies.
TEST_P(HttpNetworkTransactionTest,HttpsNestedProxyGet)6622 TEST_P(HttpNetworkTransactionTest, HttpsNestedProxyGet) {
6623 HttpRequestInfo request;
6624 request.method = "GET";
6625 request.url = GURL("http://www.example.org/");
6626 request.traffic_annotation =
6627 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
6628
6629 // Configure a nested proxy.
6630 const ProxyServer kProxyServer1{ProxyServer::SCHEME_HTTPS,
6631 HostPortPair("proxy1.test", 70)};
6632 const ProxyServer kProxyServer2{ProxyServer::SCHEME_HTTPS,
6633 HostPortPair("proxy2.test", 71)};
6634 const ProxyChain kNestedProxyChain{{kProxyServer1, kProxyServer2}};
6635
6636 ProxyList proxy_list;
6637 proxy_list.AddProxyChain(kNestedProxyChain);
6638 ProxyConfig proxy_config = ProxyConfig::CreateForTesting(proxy_list);
6639
6640 session_deps_.proxy_resolution_service =
6641 ConfiguredProxyResolutionService::CreateFixedForTest(
6642 ProxyConfigWithAnnotation(proxy_config,
6643 TRAFFIC_ANNOTATION_FOR_TESTS));
6644 session_deps_.net_log = NetLog::Get();
6645 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
6646
6647 MockWrite data_writes1[] = {
6648 MockWrite("CONNECT proxy2.test:71 HTTP/1.1\r\n"
6649 "Host: proxy2.test:71\r\n"
6650 "Proxy-Connection: keep-alive\r\n\r\n"),
6651 MockWrite("CONNECT www.example.org:80 HTTP/1.1\r\n"
6652 "Host: www.example.org:80\r\n"
6653 "Proxy-Connection: keep-alive\r\n\r\n"),
6654 MockWrite("GET / HTTP/1.1\r\n"
6655 "Host: www.example.org\r\n"
6656 "Connection: keep-alive\r\n\r\n"),
6657 };
6658
6659 MockRead data_reads1[] = {
6660 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
6661 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
6662 MockRead("HTTP/1.1 200 OK\r\n"),
6663 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
6664 MockRead("Content-Length: 100\r\n\r\n"),
6665 MockRead(SYNCHRONOUS, OK),
6666 };
6667
6668 StaticSocketDataProvider data1(data_reads1, data_writes1);
6669 session_deps_.socket_factory->AddSocketDataProvider(&data1);
6670
6671 SSLSocketDataProvider ssl(ASYNC, OK);
6672 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
6673
6674 SSLSocketDataProvider ssl2(ASYNC, OK);
6675 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
6676
6677 ConnectedHandler connected_handler;
6678 TestCompletionCallback callback;
6679
6680 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
6681
6682 trans.SetConnectedCallback(connected_handler.Callback());
6683
6684 int rv = trans.Start(&request, callback.callback(),
6685 NetLogWithSource::Make(NetLogSourceType::NONE));
6686 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
6687
6688 rv = callback.WaitForResult();
6689 EXPECT_THAT(rv, IsOk());
6690
6691 LoadTimingInfo load_timing_info;
6692 EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info));
6693 TestLoadTimingNotReused(load_timing_info,
6694 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY);
6695
6696 const HttpResponseInfo* response = trans.GetResponseInfo();
6697 ASSERT_TRUE(response);
6698
6699 EXPECT_EQ(2u, response->proxy_chain.length());
6700 EXPECT_TRUE(response->proxy_chain.GetProxyServer(0).is_https());
6701 EXPECT_TRUE(response->proxy_chain.GetProxyServer(1).is_https());
6702 EXPECT_TRUE(response->headers->IsKeepAlive());
6703 EXPECT_EQ(200, response->headers->response_code());
6704 EXPECT_EQ(100, response->headers->GetContentLength());
6705 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
6706
6707 // DNS aliases should be empty when using a proxy.
6708 EXPECT_TRUE(response->dns_aliases.empty());
6709
6710 TransportInfo expected_transport;
6711 expected_transport.type = TransportType::kProxied;
6712 expected_transport.endpoint = IPEndPoint(IPAddress::IPv4Localhost(), 70);
6713 EXPECT_THAT(connected_handler.transports(), ElementsAre(expected_transport));
6714
6715 // The password prompt info should not be set.
6716 EXPECT_FALSE(response->auth_challenge.has_value());
6717
6718 // Although we use an HTTPS proxy, the `SSLInfo` from that connection should
6719 // not be reported as a property of the origin.
6720 EXPECT_FALSE(response->ssl_info.cert);
6721 }
6722
6723 // Test a SPDY GET (for an HTTP endpoint) through an HTTPS (SPDY) proxy
6724 // (SPDY -> HTTP).
TEST_P(HttpNetworkTransactionTest,HttpsProxySpdyGet)6725 TEST_P(HttpNetworkTransactionTest, HttpsProxySpdyGet) {
6726 HttpRequestInfo request;
6727 request.method = "GET";
6728 request.url = GURL("http://www.example.org/");
6729 request.traffic_annotation =
6730 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
6731
6732 // Configure against https proxy server "proxy:70".
6733 session_deps_.proxy_resolution_service =
6734 ConfiguredProxyResolutionService::CreateFixedForTest(
6735 "https://proxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
6736 session_deps_.net_log = NetLog::Get();
6737 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
6738
6739 // fetch http://www.example.org/ via SPDY
6740 spdy::SpdySerializedFrame req(
6741 spdy_util_.ConstructSpdyGet("http://www.example.org/", 1, LOWEST));
6742 MockWrite spdy_writes[] = {CreateMockWrite(req, 0)};
6743
6744 spdy::SpdySerializedFrame resp(
6745 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
6746 spdy::SpdySerializedFrame data(spdy_util_.ConstructSpdyDataFrame(1, true));
6747 MockRead spdy_reads[] = {
6748 CreateMockRead(resp, 1),
6749 CreateMockRead(data, 2),
6750 MockRead(ASYNC, 0, 3),
6751 };
6752
6753 SequencedSocketData spdy_data(spdy_reads, spdy_writes);
6754 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
6755
6756 SSLSocketDataProvider ssl(ASYNC, OK);
6757 ssl.ssl_info.cert =
6758 ImportCertFromFile(GetTestCertsDirectory(), "ok_cert.pem");
6759 ASSERT_TRUE(ssl.ssl_info.cert);
6760 ssl.next_proto = kProtoHTTP2;
6761 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
6762
6763 ConnectedHandler connected_handler;
6764 TestCompletionCallback callback;
6765
6766 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
6767
6768 trans.SetConnectedCallback(connected_handler.Callback());
6769
6770 int rv = trans.Start(&request, callback.callback(),
6771 NetLogWithSource::Make(NetLogSourceType::NONE));
6772 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
6773
6774 rv = callback.WaitForResult();
6775 EXPECT_THAT(rv, IsOk());
6776
6777 LoadTimingInfo load_timing_info;
6778 EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info));
6779 TestLoadTimingNotReused(load_timing_info,
6780 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY);
6781
6782 const HttpResponseInfo* response = trans.GetResponseInfo();
6783 ASSERT_TRUE(response);
6784 EXPECT_EQ(1u, response->proxy_chain.length());
6785 EXPECT_TRUE(response->proxy_chain.GetProxyServer(0).is_https());
6786 ASSERT_TRUE(response->headers);
6787 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
6788
6789 // DNS aliases should be empty when using a proxy.
6790 EXPECT_TRUE(response->dns_aliases.empty());
6791
6792 TransportInfo expected_transport;
6793 expected_transport.type = TransportType::kProxied;
6794 expected_transport.endpoint = IPEndPoint(IPAddress::IPv4Localhost(), 70);
6795 expected_transport.negotiated_protocol = kProtoHTTP2;
6796 EXPECT_THAT(connected_handler.transports(), ElementsAre(expected_transport));
6797
6798 std::string response_data;
6799 ASSERT_THAT(ReadTransaction(&trans, &response_data), IsOk());
6800 EXPECT_EQ(kUploadData, response_data);
6801
6802 // Although we use an HTTPS proxy, the `SSLInfo` from that connection should
6803 // not be reported as a property of the origin.
6804 EXPECT_FALSE(response->ssl_info.cert);
6805 }
6806
6807 // Test a SPDY GET (for an HTTP endpoint) through two HTTPS (SPDY) proxies
6808 // (SPDY -> SPDY -> HTTP).
TEST_P(HttpNetworkTransactionTest,HttpsNestedProxySpdyGet)6809 TEST_P(HttpNetworkTransactionTest, HttpsNestedProxySpdyGet) {
6810 HttpRequestInfo request;
6811 request.method = "GET";
6812 request.url = GURL("http://www.example.org/");
6813 request.traffic_annotation =
6814 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
6815
6816 // Configure a nested proxy.
6817 const ProxyServer kProxyServer1{ProxyServer::SCHEME_HTTPS,
6818 HostPortPair("proxy1.test", 70)};
6819 const ProxyServer kProxyServer2{ProxyServer::SCHEME_HTTPS,
6820 HostPortPair("proxy2.test", 71)};
6821 const ProxyChain kNestedProxyChain{{kProxyServer1, kProxyServer2}};
6822
6823 ProxyList proxy_list;
6824 proxy_list.AddProxyChain(kNestedProxyChain);
6825 ProxyConfig proxy_config = ProxyConfig::CreateForTesting(proxy_list);
6826
6827 session_deps_.proxy_resolution_service =
6828 ConfiguredProxyResolutionService::CreateFixedForTest(
6829 ProxyConfigWithAnnotation(proxy_config,
6830 TRAFFIC_ANNOTATION_FOR_TESTS));
6831 session_deps_.net_log = NetLog::Get();
6832 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
6833
6834 // CONNECT to proxy2.test:71 via SPDY.
6835 spdy::SpdySerializedFrame proxy2_connect(spdy_util_.ConstructSpdyConnect(
6836 /*extra_headers=*/nullptr, 0, 1,
6837 HttpProxyConnectJob::kH2QuicTunnelPriority,
6838 kProxyServer2.host_port_pair()));
6839
6840 spdy::SpdySerializedFrame proxy2_connect_resp(
6841 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
6842
6843 // CONNECT to www.example.org:80 via SPDY.
6844 // Need to use a new `SpdyTestUtil()` so that the stream parent ID of this
6845 // request is calculated correctly.
6846 SpdyTestUtil spdy_util2(/*use_priority_header=*/true);
6847 spdy::SpdySerializedFrame endpoint_connect(spdy_util2.ConstructSpdyConnect(
6848 /*extra_headers=*/nullptr, 0, 1,
6849 HttpProxyConnectJob::kH2QuicTunnelPriority,
6850 HostPortPair("www.example.org", 80)));
6851 spdy::SpdySerializedFrame wrapped_endpoint_connect(
6852 spdy_util_.ConstructWrappedSpdyFrame(endpoint_connect, 1));
6853
6854 spdy::SpdySerializedFrame endpoint_connect_resp(
6855 spdy_util2.ConstructSpdyGetReply(nullptr, 0, 1));
6856 spdy::SpdySerializedFrame wrapped_endpoint_connect_resp(
6857 spdy_util_.ConstructWrappedSpdyFrame(endpoint_connect_resp, 1));
6858
6859 // fetch http://www.example.org/ via HTTP.
6860 // Since this request will go over two tunnels, it needs to be double-wrapped.
6861 const char kGet[] =
6862 "GET / HTTP/1.1\r\n"
6863 "Host: www.example.org\r\n"
6864 "Connection: keep-alive\r\n\r\n";
6865 spdy::SpdySerializedFrame wrapped_get(
6866 spdy_util2.ConstructSpdyDataFrame(1, kGet, false));
6867 spdy::SpdySerializedFrame wrapped_wrapped_get(
6868 spdy_util_.ConstructWrappedSpdyFrame(wrapped_get, 1));
6869
6870 const char kResp[] =
6871 "HTTP/1.1 200 OK\r\n"
6872 "Content-Length: 10\r\n\r\n";
6873 spdy::SpdySerializedFrame wrapped_get_resp(
6874 spdy_util2.ConstructSpdyDataFrame(1, kResp, false));
6875 spdy::SpdySerializedFrame wrapped_wrapped_get_resp(
6876 spdy_util_.ConstructWrappedSpdyFrame(wrapped_get_resp, 1));
6877
6878 const char kRespData[] = "1234567890";
6879 spdy::SpdySerializedFrame wrapped_body(
6880 spdy_util2.ConstructSpdyDataFrame(1, kRespData, false));
6881 spdy::SpdySerializedFrame wrapped_wrapped_body(
6882 spdy_util_.ConstructWrappedSpdyFrame(wrapped_body, 1));
6883
6884 MockWrite spdy_writes[] = {
6885 CreateMockWrite(proxy2_connect, 0),
6886 CreateMockWrite(wrapped_endpoint_connect, 2),
6887 CreateMockWrite(wrapped_wrapped_get, 5),
6888 };
6889
6890 MockRead spdy_reads[] = {
6891 CreateMockRead(proxy2_connect_resp, 1),
6892 // TODO(https://crbug.com/497228): We have to manually delay this read so
6893 // that the higher-level SPDY stream doesn't get notified of an available
6894 // read before the write it initiated (the second CONNECT) finishes,
6895 // triggering a DCHECK.
6896 MockRead(ASYNC, ERR_IO_PENDING, 3),
6897 CreateMockRead(wrapped_endpoint_connect_resp, 4, ASYNC),
6898 CreateMockRead(wrapped_wrapped_get_resp, 6, ASYNC),
6899 CreateMockRead(wrapped_wrapped_body, 7, ASYNC),
6900 MockRead(ASYNC, 0, 8),
6901 };
6902
6903 SequencedSocketData spdy_data(spdy_reads, spdy_writes);
6904 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
6905
6906 SSLSocketDataProvider ssl(ASYNC, OK);
6907 ssl.next_proto = kProtoHTTP2;
6908 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
6909
6910 SSLSocketDataProvider ssl2(ASYNC, OK);
6911 ssl2.next_proto = kProtoHTTP2;
6912 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
6913
6914 ConnectedHandler connected_handler;
6915 TestCompletionCallback callback;
6916
6917 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
6918
6919 trans.SetConnectedCallback(connected_handler.Callback());
6920
6921 int rv = trans.Start(&request, callback.callback(),
6922 NetLogWithSource::Make(NetLogSourceType::NONE));
6923 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
6924
6925 spdy_data.RunUntilPaused();
6926 base::RunLoop().RunUntilIdle();
6927 spdy_data.Resume();
6928
6929 rv = callback.WaitForResult();
6930 ASSERT_THAT(rv, IsOk());
6931
6932 LoadTimingInfo load_timing_info;
6933 EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info));
6934 TestLoadTimingNotReused(load_timing_info,
6935 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY);
6936
6937 const HttpResponseInfo* response = trans.GetResponseInfo();
6938 ASSERT_TRUE(response);
6939 EXPECT_EQ(response->proxy_chain.GetProxyServer(/*chain_index=*/0),
6940 kProxyServer1);
6941 EXPECT_EQ(response->proxy_chain.GetProxyServer(/*chain_index=*/1),
6942 kProxyServer2);
6943 ASSERT_TRUE(response->headers);
6944 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
6945
6946 // DNS aliases should be empty when using a proxy.
6947 EXPECT_TRUE(response->dns_aliases.empty());
6948
6949 TransportInfo expected_transport;
6950 expected_transport.type = TransportType::kProxied;
6951 expected_transport.endpoint = IPEndPoint(IPAddress::IPv4Localhost(), 70);
6952 expected_transport.negotiated_protocol = kProtoUnknown;
6953 EXPECT_THAT(connected_handler.transports(), ElementsAre(expected_transport));
6954
6955 std::string response_data;
6956 ASSERT_THAT(ReadTransaction(&trans, &response_data), IsOk());
6957 EXPECT_EQ(kRespData, response_data);
6958
6959 // Although we use an HTTPS proxy, the `SSLInfo` from that connection should
6960 // not be reported as a property of the origin.
6961 EXPECT_FALSE(response->ssl_info.cert);
6962 }
6963
6964 // Test a SPDY GET (for an HTTP endpoint) through the same HTTPS (SPDY) proxy
6965 // twice (SPDY -> SPDY -> HTTP).
TEST_P(HttpNetworkTransactionTest,HttpsNestedProxySameProxyTwiceSpdyGet)6966 TEST_P(HttpNetworkTransactionTest, HttpsNestedProxySameProxyTwiceSpdyGet) {
6967 HttpRequestInfo request;
6968 request.method = "GET";
6969 request.url = GURL("http://www.example.org/");
6970 request.traffic_annotation =
6971 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
6972
6973 // Configure a nested proxy.
6974 const ProxyServer kProxyServer{ProxyServer::SCHEME_HTTPS,
6975 HostPortPair("proxy.test", 70)};
6976 const ProxyChain kNestedProxyChain{{kProxyServer, kProxyServer}};
6977
6978 ProxyList proxy_list;
6979 proxy_list.AddProxyChain(kNestedProxyChain);
6980 ProxyConfig proxy_config = ProxyConfig::CreateForTesting(proxy_list);
6981
6982 session_deps_.proxy_resolution_service =
6983 ConfiguredProxyResolutionService::CreateFixedForTest(
6984 ProxyConfigWithAnnotation(proxy_config,
6985 TRAFFIC_ANNOTATION_FOR_TESTS));
6986
6987 session_deps_.net_log = NetLog::Get();
6988 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
6989
6990 // CONNECT to proxy.test:70 via SPDY.
6991 spdy::SpdySerializedFrame proxy_connect(spdy_util_.ConstructSpdyConnect(
6992 /*extra_headers=*/nullptr, 0, 1,
6993 HttpProxyConnectJob::kH2QuicTunnelPriority,
6994 kProxyServer.host_port_pair()));
6995
6996 spdy::SpdySerializedFrame proxy_connect_resp(
6997 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
6998
6999 // CONNECT to www.example.org:80 via SPDY.
7000 // Need to use a new `SpdyTestUtil()` so that the stream parent ID of this
7001 // request is calculated correctly.
7002 SpdyTestUtil new_spdy_util(/*use_priority_header=*/true);
7003 spdy::SpdySerializedFrame endpoint_connect(new_spdy_util.ConstructSpdyConnect(
7004 /*extra_headers=*/nullptr, 0, 1,
7005 HttpProxyConnectJob::kH2QuicTunnelPriority,
7006 HostPortPair("www.example.org", 80)));
7007 spdy::SpdySerializedFrame wrapped_endpoint_connect(
7008 spdy_util_.ConstructWrappedSpdyFrame(endpoint_connect, 1));
7009
7010 spdy::SpdySerializedFrame endpoint_connect_resp(
7011 new_spdy_util.ConstructSpdyGetReply(nullptr, 0, 1));
7012 spdy::SpdySerializedFrame wrapped_endpoint_connect_resp(
7013 spdy_util_.ConstructWrappedSpdyFrame(endpoint_connect_resp, 1));
7014
7015 // fetch http://www.example.org/ via HTTP.
7016 // Since this request will go over two tunnels, it needs to be double-wrapped.
7017 const char kGet[] =
7018 "GET / HTTP/1.1\r\n"
7019 "Host: www.example.org\r\n"
7020 "Connection: keep-alive\r\n\r\n";
7021 spdy::SpdySerializedFrame wrapped_get(
7022 new_spdy_util.ConstructSpdyDataFrame(1, kGet, false));
7023 spdy::SpdySerializedFrame wrapped_wrapped_get(
7024 spdy_util_.ConstructWrappedSpdyFrame(wrapped_get, 1));
7025
7026 const char kResp[] =
7027 "HTTP/1.1 200 OK\r\n"
7028 "Content-Length: 10\r\n\r\n";
7029 spdy::SpdySerializedFrame wrapped_get_resp(
7030 new_spdy_util.ConstructSpdyDataFrame(1, kResp, false));
7031 spdy::SpdySerializedFrame wrapped_wrapped_get_resp(
7032 spdy_util_.ConstructWrappedSpdyFrame(wrapped_get_resp, 1));
7033
7034 const char kRespData[] = "1234567890";
7035 spdy::SpdySerializedFrame wrapped_body(
7036 new_spdy_util.ConstructSpdyDataFrame(1, kRespData, false));
7037 spdy::SpdySerializedFrame wrapped_wrapped_body(
7038 spdy_util_.ConstructWrappedSpdyFrame(wrapped_body, 1));
7039
7040 MockWrite spdy_writes[] = {
7041 CreateMockWrite(proxy_connect, 0),
7042 CreateMockWrite(wrapped_endpoint_connect, 2),
7043 CreateMockWrite(wrapped_wrapped_get, 5),
7044 };
7045
7046 MockRead spdy_reads[] = {
7047 CreateMockRead(proxy_connect_resp, 1),
7048 // TODO(https://crbug.com/497228): We have to manually delay this read so
7049 // that the higher-level SPDY stream doesn't get notified of an available
7050 // read before the write it initiated (the second CONNECT) finishes,
7051 // triggering a DCHECK.
7052 MockRead(ASYNC, ERR_IO_PENDING, 3),
7053 CreateMockRead(wrapped_endpoint_connect_resp, 4, ASYNC),
7054 CreateMockRead(wrapped_wrapped_get_resp, 6, ASYNC),
7055 CreateMockRead(wrapped_wrapped_body, 7, ASYNC),
7056 MockRead(ASYNC, 0, 8),
7057 };
7058
7059 SequencedSocketData spdy_data(spdy_reads, spdy_writes);
7060 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
7061
7062 SSLSocketDataProvider ssl(ASYNC, OK);
7063 ssl.next_proto = kProtoHTTP2;
7064 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
7065
7066 SSLSocketDataProvider ssl2(ASYNC, OK);
7067 ssl2.next_proto = kProtoHTTP2;
7068 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
7069
7070 ConnectedHandler connected_handler;
7071 TestCompletionCallback callback;
7072
7073 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
7074
7075 trans.SetConnectedCallback(connected_handler.Callback());
7076
7077 int rv = trans.Start(&request, callback.callback(),
7078 NetLogWithSource::Make(NetLogSourceType::NONE));
7079 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
7080
7081 spdy_data.RunUntilPaused();
7082 base::RunLoop().RunUntilIdle();
7083 spdy_data.Resume();
7084
7085 rv = callback.WaitForResult();
7086 ASSERT_THAT(rv, IsOk());
7087
7088 LoadTimingInfo load_timing_info;
7089 EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info));
7090 TestLoadTimingNotReused(load_timing_info,
7091 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY);
7092
7093 const HttpResponseInfo* response = trans.GetResponseInfo();
7094 ASSERT_TRUE(response);
7095 EXPECT_EQ(response->proxy_chain.GetProxyServer(/*chain_index=*/0),
7096 kProxyServer);
7097 EXPECT_EQ(response->proxy_chain.GetProxyServer(/*chain_index=*/1),
7098 kProxyServer);
7099 ASSERT_TRUE(response->headers);
7100 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
7101
7102 // DNS aliases should be empty when using a proxy.
7103 EXPECT_TRUE(response->dns_aliases.empty());
7104
7105 TransportInfo expected_transport;
7106 expected_transport.type = TransportType::kProxied;
7107 expected_transport.endpoint = IPEndPoint(IPAddress::IPv4Localhost(), 70);
7108 expected_transport.negotiated_protocol = kProtoUnknown;
7109 EXPECT_THAT(connected_handler.transports(), ElementsAre(expected_transport));
7110
7111 std::string response_data;
7112 ASSERT_THAT(ReadTransaction(&trans, &response_data), IsOk());
7113 EXPECT_EQ(kRespData, response_data);
7114
7115 // Although we use an HTTPS proxy, the `SSLInfo` from that connection should
7116 // not be reported as a property of the origin.
7117 EXPECT_FALSE(response->ssl_info.cert);
7118 }
7119
7120 // Test that a SPDY protocol error encountered when attempting to perform an
7121 // HTTP request over a multi-proxy chain is handled correctly.
TEST_P(HttpNetworkTransactionTest,NestedProxyHttpOverSpdyProtocolError)7122 TEST_P(HttpNetworkTransactionTest, NestedProxyHttpOverSpdyProtocolError) {
7123 const ProxyServer kProxyServer1{ProxyServer::SCHEME_HTTPS,
7124 HostPortPair("proxy1.test", 70)};
7125 const ProxyServer kProxyServer2{ProxyServer::SCHEME_HTTPS,
7126 HostPortPair("proxy2.test", 71)};
7127 const ProxyChain kNestedProxyChain{{kProxyServer1, kProxyServer2}};
7128
7129 ProxyList proxy_list;
7130 proxy_list.AddProxyChain(kNestedProxyChain);
7131 ProxyConfig proxy_config = ProxyConfig::CreateForTesting(proxy_list);
7132
7133 session_deps_.proxy_resolution_service =
7134 ConfiguredProxyResolutionService::CreateFixedForTest(
7135 ProxyConfigWithAnnotation(proxy_config,
7136 TRAFFIC_ANNOTATION_FOR_TESTS));
7137 session_deps_.net_log = NetLog::Get();
7138 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
7139
7140 // CONNECT to proxy2.test:71 via SPDY.
7141 spdy::SpdySerializedFrame proxy2_connect(spdy_util_.ConstructSpdyConnect(
7142 /*extra_headers=*/nullptr, 0, 1,
7143 HttpProxyConnectJob::kH2QuicTunnelPriority,
7144 kProxyServer2.host_port_pair()));
7145
7146 spdy::SpdySerializedFrame proxy2_connect_resp(
7147 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
7148
7149 // CONNECT to www.example.org:80 via SPDY.
7150 // Need to use a new `SpdyTestUtil()` so that the stream parent ID of this
7151 // request is calculated correctly.
7152 SpdyTestUtil spdy_util2(/*use_priority_header=*/true);
7153 spdy::SpdySerializedFrame endpoint_connect(spdy_util2.ConstructSpdyConnect(
7154 /*extra_headers=*/nullptr, 0, 1,
7155 HttpProxyConnectJob::kH2QuicTunnelPriority,
7156 HostPortPair("www.example.org", 80)));
7157 spdy::SpdySerializedFrame wrapped_endpoint_connect(
7158 spdy_util_.ConstructWrappedSpdyFrame(endpoint_connect, 1));
7159
7160 spdy::SpdySerializedFrame data(spdy_util2.ConstructSpdyDataFrame(1, true));
7161 spdy::SpdySerializedFrame wrapped_data(
7162 spdy_util_.ConstructWrappedSpdyFrame(data, 1));
7163
7164 MockWrite spdy_writes[] = {
7165 CreateMockWrite(proxy2_connect, 0),
7166 CreateMockWrite(wrapped_endpoint_connect, 2),
7167 };
7168
7169 MockRead spdy_reads[] = {
7170 CreateMockRead(proxy2_connect_resp, 1),
7171 // TODO(https://crbug.com/497228): We have to manually delay this read so
7172 // that the higher-level SPDY stream doesn't get notified of an available
7173 // read before the write it initiated (the second CONNECT) finishes,
7174 // triggering a DCHECK.
7175 MockRead(ASYNC, ERR_IO_PENDING, 3),
7176 // Instead of returning a valid response, just return wrapped data. This
7177 // should trigger an HTTP2 protocol error and not CHECK when nested
7178 // proxies are in use.
7179 CreateMockRead(wrapped_data, 4),
7180 MockRead(ASYNC, 0, 5),
7181 };
7182
7183 SequencedSocketData spdy_data(spdy_reads, spdy_writes);
7184 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
7185
7186 SSLSocketDataProvider ssl(ASYNC, OK);
7187 ssl.next_proto = kProtoHTTP2;
7188 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
7189
7190 SSLSocketDataProvider ssl2(ASYNC, OK);
7191 ssl2.next_proto = kProtoHTTP2;
7192 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
7193
7194 HttpRequestInfo request;
7195 request.method = "GET";
7196 request.url = GURL("http://www.example.org/");
7197 request.traffic_annotation =
7198 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
7199
7200 TestCompletionCallback callback;
7201
7202 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
7203
7204 int rv = trans.Start(&request, callback.callback(),
7205 NetLogWithSource::Make(NetLogSourceType::NONE));
7206 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
7207
7208 spdy_data.RunUntilPaused();
7209 base::RunLoop().RunUntilIdle();
7210 spdy_data.Resume();
7211
7212 rv = callback.WaitForResult();
7213 ASSERT_THAT(rv, IsError(ERR_HTTP2_PROTOCOL_ERROR));
7214 }
7215
7216 // Test that a proxy server requesting a client auth cert doesn't cause a crash.
7217 // TODO(https://crbug.com/1491092): This test can be deleted once we no longer
7218 // need the multi-proxy chain version below, since this functionality should
7219 // be sufficiently tested elsewhere. For now this test just shows that
7220 // single-proxy and multi-proxy behavior is consistent (when a read returns
7221 // ERR_SSL_CLIENT_AUTH_CERT_NEEDED).
TEST_P(HttpNetworkTransactionTest,HttpsClientAuthCertNeededNoCrash)7222 TEST_P(HttpNetworkTransactionTest, HttpsClientAuthCertNeededNoCrash) {
7223 // Configure against https proxy server "proxy:70".
7224 session_deps_.proxy_resolution_service =
7225 ConfiguredProxyResolutionService::CreateFixedForTest(
7226 "https://proxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
7227
7228 session_deps_.net_log = NetLog::Get();
7229 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
7230
7231 // CONNECT to www.example.org:443 via SPDY.
7232 spdy::SpdySerializedFrame endpoint_connect(spdy_util_.ConstructSpdyConnect(
7233 /*extra_headers=*/nullptr, 0, 1,
7234 HttpProxyConnectJob::kH2QuicTunnelPriority,
7235 HostPortPair("www.example.org", 443)));
7236
7237 spdy::SpdySerializedFrame spdy_response_go_away(
7238 spdy_util_.ConstructSpdyGoAway(0, spdy::ERROR_CODE_PROTOCOL_ERROR,
7239 "Error 110 reading from socket."));
7240
7241 MockWrite spdy_writes[] = {
7242 CreateMockWrite(endpoint_connect, 0),
7243 CreateMockWrite(spdy_response_go_away, 2),
7244 };
7245
7246 MockRead spdy_reads[] = {
7247 MockRead(ASYNC, ERR_SSL_CLIENT_AUTH_CERT_NEEDED, 1),
7248 MockRead(ASYNC, 0, 3),
7249 };
7250
7251 SequencedSocketData spdy_data(spdy_reads, spdy_writes);
7252 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
7253
7254 SSLSocketDataProvider ssl(ASYNC, OK);
7255 ssl.next_proto = kProtoHTTP2;
7256 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
7257
7258 HttpRequestInfo request;
7259 request.method = "GET";
7260 request.url = GURL("https://www.example.org/");
7261 request.traffic_annotation =
7262 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
7263
7264 TestCompletionCallback callback;
7265
7266 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
7267
7268 int rv = trans.Start(&request, callback.callback(),
7269 NetLogWithSource::Make(NetLogSourceType::NONE));
7270 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
7271
7272 rv = callback.WaitForResult();
7273 ASSERT_THAT(rv, IsError(ERR_SSL_CLIENT_AUTH_CERT_NEEDED));
7274 SSLCertRequestInfo* cert_request_info =
7275 trans.GetResponseInfo()->cert_request_info.get();
7276 // In the case of a read returning ERR_SSL_CLIENT_AUTH_CERT_NEEDED directly,
7277 // no `SSLCertRequestInfo` is available.
7278 EXPECT_FALSE(cert_request_info);
7279 }
7280
7281 // Test that the first proxy server in a multi-proxy chain requesting a client
7282 // auth cert doesn't cause a crash.
7283 // TODO(https://crbug.com/1491092): Support client auth certificates for
7284 // multi-proxy chains and then replace this test with a more robust one (for
7285 // instance, a version of the AuthEverywhere test that uses a multi-proxy
7286 // chain).
TEST_P(HttpNetworkTransactionTest,HttpsNestedProxyClientAuthCertNeededFirstProxyNoCrash)7287 TEST_P(HttpNetworkTransactionTest,
7288 HttpsNestedProxyClientAuthCertNeededFirstProxyNoCrash) {
7289 const ProxyServer kProxyServer1{ProxyServer::SCHEME_HTTPS,
7290 HostPortPair("proxy1.test", 70)};
7291 const ProxyServer kProxyServer2{ProxyServer::SCHEME_HTTPS,
7292 HostPortPair("proxy2.test", 71)};
7293 const ProxyChain kNestedProxyChain{{kProxyServer1, kProxyServer2}};
7294
7295 ProxyList proxy_list;
7296 proxy_list.AddProxyChain(kNestedProxyChain);
7297 ProxyConfig proxy_config = ProxyConfig::CreateForTesting(proxy_list);
7298
7299 session_deps_.proxy_resolution_service =
7300 ConfiguredProxyResolutionService::CreateFixedForTest(
7301 ProxyConfigWithAnnotation(proxy_config,
7302 TRAFFIC_ANNOTATION_FOR_TESTS));
7303 session_deps_.net_log = NetLog::Get();
7304 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
7305
7306 // CONNECT to proxy2.test:71 via SPDY.
7307 spdy::SpdySerializedFrame proxy2_connect(spdy_util_.ConstructSpdyConnect(
7308 /*extra_headers=*/nullptr, 0, 1,
7309 HttpProxyConnectJob::kH2QuicTunnelPriority,
7310 kProxyServer2.host_port_pair()));
7311
7312 spdy::SpdySerializedFrame spdy_response_go_away(
7313 spdy_util_.ConstructSpdyGoAway(0, spdy::ERROR_CODE_PROTOCOL_ERROR,
7314 "Error 110 reading from socket."));
7315
7316 MockWrite spdy_writes[] = {
7317 CreateMockWrite(proxy2_connect, 0),
7318 CreateMockWrite(spdy_response_go_away, 2),
7319 };
7320
7321 MockRead spdy_reads[] = {
7322 MockRead(ASYNC, ERR_SSL_CLIENT_AUTH_CERT_NEEDED, 1),
7323 MockRead(ASYNC, 0, 3),
7324 };
7325
7326 SequencedSocketData spdy_data(spdy_reads, spdy_writes);
7327 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
7328
7329 SSLSocketDataProvider ssl(ASYNC, OK);
7330 ssl.next_proto = kProtoHTTP2;
7331 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
7332
7333 HttpRequestInfo request;
7334 request.method = "GET";
7335 request.url = GURL("https://www.example.org/");
7336 request.traffic_annotation =
7337 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
7338
7339 TestCompletionCallback callback;
7340
7341 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
7342
7343 int rv = trans.Start(&request, callback.callback(),
7344 NetLogWithSource::Make(NetLogSourceType::NONE));
7345 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
7346
7347 rv = callback.WaitForResult();
7348 ASSERT_THAT(rv, IsError(ERR_SSL_CLIENT_AUTH_CERT_NEEDED));
7349 SSLCertRequestInfo* cert_request_info =
7350 trans.GetResponseInfo()->cert_request_info.get();
7351 // In the case of a read returning ERR_SSL_CLIENT_AUTH_CERT_NEEDED directly,
7352 // no `SSLCertRequestInfo` is available.
7353 EXPECT_FALSE(cert_request_info);
7354 }
7355
7356 // Same as above but using a different method to request the client auth
7357 // certificate.
7358 // TODO(https://crbug.com/1491092): Support client auth certificates for
7359 // multi-proxy chains and then replace this test with a more robust one (for
7360 // instance, a version of the AuthEverywhere test that uses a multi-proxy
7361 // chain).
TEST_P(HttpNetworkTransactionTest,HttpsNestedProxyClientAuthCertNeededFirstProxyNoCrash2)7362 TEST_P(HttpNetworkTransactionTest,
7363 HttpsNestedProxyClientAuthCertNeededFirstProxyNoCrash2) {
7364 const ProxyServer kProxyServer1{ProxyServer::SCHEME_HTTPS,
7365 HostPortPair("proxy1.test", 70)};
7366 const ProxyServer kProxyServer2{ProxyServer::SCHEME_HTTPS,
7367 HostPortPair("proxy2.test", 71)};
7368 const ProxyChain kNestedProxyChain{{kProxyServer1, kProxyServer2}};
7369
7370 ProxyList proxy_list;
7371 proxy_list.AddProxyChain(kNestedProxyChain);
7372 ProxyConfig proxy_config = ProxyConfig::CreateForTesting(proxy_list);
7373
7374 session_deps_.proxy_resolution_service =
7375 ConfiguredProxyResolutionService::CreateFixedForTest(
7376 ProxyConfigWithAnnotation(proxy_config,
7377 TRAFFIC_ANNOTATION_FOR_TESTS));
7378 session_deps_.net_log = NetLog::Get();
7379 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
7380
7381 StaticSocketDataProvider spdy_data{base::span<MockRead>(),
7382 base::span<MockWrite>()};
7383 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
7384
7385 auto cert_request_info_proxy = base::MakeRefCounted<SSLCertRequestInfo>();
7386 cert_request_info_proxy->host_and_port = kProxyServer1.host_port_pair();
7387
7388 SSLSocketDataProvider ssl(ASYNC, ERR_SSL_CLIENT_AUTH_CERT_NEEDED);
7389 ssl.cert_request_info = cert_request_info_proxy;
7390 ssl.expected_send_client_cert = false;
7391 ssl.next_proto = kProtoHTTP2;
7392 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
7393
7394 HttpRequestInfo request;
7395 request.method = "GET";
7396 request.url = GURL("https://www.example.org/");
7397 request.traffic_annotation =
7398 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
7399
7400 TestCompletionCallback callback;
7401
7402 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
7403
7404 int rv = trans.Start(&request, callback.callback(),
7405 NetLogWithSource::Make(NetLogSourceType::NONE));
7406 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
7407
7408 rv = callback.WaitForResult();
7409 ASSERT_THAT(rv, IsError(ERR_SSL_CLIENT_AUTH_CERT_NEEDED));
7410 SSLCertRequestInfo* cert_request_info =
7411 trans.GetResponseInfo()->cert_request_info.get();
7412 ASSERT_TRUE(cert_request_info);
7413 EXPECT_TRUE(cert_request_info->is_proxy);
7414 EXPECT_EQ(cert_request_info->host_and_port, kProxyServer1.host_port_pair());
7415 }
7416
7417 // Test that a read returning ERR_SSL_CLIENT_AUTH_CERT_NEEDED after the first
7418 // CONNECT doesn't result in a crash when a multi-proxy chain is in use.
7419 // TODO(https://crbug.com/1491092): Support client auth certificates for
7420 // multi-proxy chains and then replace this test with a more robust one (for
7421 // instance, a version of the AuthEverywhere test that uses a multi-proxy
7422 // chain).
TEST_P(HttpNetworkTransactionTest,HttpsNestedProxyClientAuthCertNeededAfterFirstConnectNoCrash2)7423 TEST_P(HttpNetworkTransactionTest,
7424 HttpsNestedProxyClientAuthCertNeededAfterFirstConnectNoCrash2) {
7425 const ProxyServer kProxyServer1{ProxyServer::SCHEME_HTTPS,
7426 HostPortPair("proxy1.test", 70)};
7427 const ProxyServer kProxyServer2{ProxyServer::SCHEME_HTTPS,
7428 HostPortPair("proxy2.test", 71)};
7429 const ProxyChain kNestedProxyChain{{kProxyServer1, kProxyServer2}};
7430
7431 ProxyList proxy_list;
7432 proxy_list.AddProxyChain(kNestedProxyChain);
7433 ProxyConfig proxy_config = ProxyConfig::CreateForTesting(proxy_list);
7434
7435 session_deps_.proxy_resolution_service =
7436 ConfiguredProxyResolutionService::CreateFixedForTest(
7437 ProxyConfigWithAnnotation(proxy_config,
7438 TRAFFIC_ANNOTATION_FOR_TESTS));
7439 session_deps_.net_log = NetLog::Get();
7440 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
7441
7442 // CONNECT to proxy2.test:71 via SPDY.
7443 spdy::SpdySerializedFrame proxy2_connect(spdy_util_.ConstructSpdyConnect(
7444 /*extra_headers=*/nullptr, 0, 1,
7445 HttpProxyConnectJob::kH2QuicTunnelPriority,
7446 kProxyServer2.host_port_pair()));
7447
7448 spdy::SpdySerializedFrame proxy2_connect_resp(
7449 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
7450
7451 // CONNECT to www.example.org:80 via SPDY.
7452 // Need to use a new `SpdyTestUtil()` so that the stream parent ID of this
7453 // request is calculated correctly.
7454 SpdyTestUtil spdy_util2(/*use_priority_header=*/true);
7455 spdy::SpdySerializedFrame endpoint_connect(spdy_util2.ConstructSpdyConnect(
7456 /*extra_headers=*/nullptr, 0, 1,
7457 HttpProxyConnectJob::kH2QuicTunnelPriority,
7458 HostPortPair("www.example.org", 80)));
7459 spdy::SpdySerializedFrame wrapped_endpoint_connect(
7460 spdy_util_.ConstructWrappedSpdyFrame(endpoint_connect, 1));
7461
7462 spdy::SpdySerializedFrame spdy_response_go_away(
7463 spdy_util_.ConstructSpdyGoAway(0, spdy::ERROR_CODE_PROTOCOL_ERROR,
7464 "Error 110 reading from socket."));
7465 MockWrite spdy_writes[] = {
7466 CreateMockWrite(proxy2_connect, 0),
7467 CreateMockWrite(wrapped_endpoint_connect, 2),
7468 CreateMockWrite(spdy_response_go_away, 5),
7469 };
7470
7471 MockRead spdy_reads[] = {
7472 CreateMockRead(proxy2_connect_resp, 1),
7473 // TODO(https://crbug.com/497228): We have to manually delay this read so
7474 // that the higher-level SPDY stream doesn't get notified of an available
7475 // read before the write it initiated (the second CONNECT) finishes,
7476 // triggering a DCHECK.
7477 MockRead(ASYNC, ERR_IO_PENDING, 3),
7478 MockRead(ASYNC, ERR_SSL_CLIENT_AUTH_CERT_NEEDED, 4),
7479 };
7480
7481 SequencedSocketData spdy_data(spdy_reads, spdy_writes);
7482 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
7483
7484 SSLSocketDataProvider ssl(ASYNC, OK);
7485 ssl.next_proto = kProtoHTTP2;
7486 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
7487
7488 SSLSocketDataProvider ssl2(ASYNC, OK);
7489 ssl2.next_proto = kProtoHTTP2;
7490 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
7491
7492 HttpRequestInfo request;
7493 request.method = "GET";
7494 request.url = GURL("http://www.example.org/");
7495 request.traffic_annotation =
7496 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
7497
7498 TestCompletionCallback callback;
7499
7500 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
7501
7502 int rv = trans.Start(&request, callback.callback(),
7503 NetLogWithSource::Make(NetLogSourceType::NONE));
7504 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
7505
7506 spdy_data.RunUntilPaused();
7507 base::RunLoop().RunUntilIdle();
7508 spdy_data.Resume();
7509
7510 rv = callback.WaitForResult();
7511 ASSERT_THAT(rv, IsError(ERR_CONNECTION_CLOSED));
7512 SSLCertRequestInfo* cert_request_info =
7513 trans.GetResponseInfo()->cert_request_info.get();
7514 EXPECT_FALSE(cert_request_info);
7515 }
7516
7517 // Test that the second proxy server in a multi-proxy chain requesting a client
7518 // auth cert doesn't cause a crash.
7519 // TODO(https://crbug.com/1491092): Support client auth certificates for
7520 // multi-proxy chains and then replace this test with a more robust one (for
7521 // instance, a version of the AuthEverywhere test that uses a multi-proxy
7522 // chain).
TEST_P(HttpNetworkTransactionTest,HttpsNestedProxyClientAuthCertNeededSecondProxyNoCrash)7523 TEST_P(HttpNetworkTransactionTest,
7524 HttpsNestedProxyClientAuthCertNeededSecondProxyNoCrash) {
7525 const ProxyServer kProxyServer1{ProxyServer::SCHEME_HTTPS,
7526 HostPortPair("proxy1.test", 70)};
7527 const ProxyServer kProxyServer2{ProxyServer::SCHEME_HTTPS,
7528 HostPortPair("proxy2.test", 71)};
7529 const ProxyChain kNestedProxyChain{{kProxyServer1, kProxyServer2}};
7530
7531 ProxyList proxy_list;
7532 proxy_list.AddProxyChain(kNestedProxyChain);
7533 ProxyConfig proxy_config = ProxyConfig::CreateForTesting(proxy_list);
7534
7535 session_deps_.proxy_resolution_service =
7536 ConfiguredProxyResolutionService::CreateFixedForTest(
7537 ProxyConfigWithAnnotation(proxy_config,
7538 TRAFFIC_ANNOTATION_FOR_TESTS));
7539 session_deps_.net_log = NetLog::Get();
7540 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
7541
7542 // CONNECT to proxy2.test:71 via SPDY.
7543 spdy::SpdySerializedFrame proxy2_connect(spdy_util_.ConstructSpdyConnect(
7544 /*extra_headers=*/nullptr, 0, 1,
7545 HttpProxyConnectJob::kH2QuicTunnelPriority,
7546 kProxyServer2.host_port_pair()));
7547
7548 spdy::SpdySerializedFrame proxy2_connect_resp(
7549 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
7550
7551 spdy::SpdySerializedFrame rst(
7552 spdy_util_.ConstructSpdyRstStream(1, spdy::ERROR_CODE_CANCEL));
7553
7554 MockWrite spdy_writes[] = {
7555 CreateMockWrite(proxy2_connect, 0),
7556 CreateMockWrite(rst, 2),
7557 };
7558
7559 MockRead spdy_reads[] = {
7560 CreateMockRead(proxy2_connect_resp, 1),
7561 MockRead(ASYNC, 0, 3),
7562 };
7563
7564 SequencedSocketData spdy_data(spdy_reads, spdy_writes);
7565 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
7566
7567 SSLSocketDataProvider ssl(ASYNC, OK);
7568 ssl.next_proto = kProtoHTTP2;
7569 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
7570
7571 auto cert_request_info_proxy = base::MakeRefCounted<SSLCertRequestInfo>();
7572 cert_request_info_proxy->host_and_port = kProxyServer2.host_port_pair();
7573
7574 SSLSocketDataProvider ssl2(ASYNC, ERR_SSL_CLIENT_AUTH_CERT_NEEDED);
7575 ssl2.cert_request_info = cert_request_info_proxy;
7576 ssl2.expected_send_client_cert = false;
7577 ssl2.next_proto = kProtoHTTP2;
7578 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
7579
7580 HttpRequestInfo request;
7581 request.method = "GET";
7582 request.url = GURL("http://www.example.org/");
7583 request.traffic_annotation =
7584 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
7585
7586 TestCompletionCallback callback;
7587
7588 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
7589
7590 int rv = trans.Start(&request, callback.callback(),
7591 NetLogWithSource::Make(NetLogSourceType::NONE));
7592 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
7593
7594 rv = callback.WaitForResult();
7595 ASSERT_THAT(rv, IsError(ERR_SSL_CLIENT_AUTH_CERT_NEEDED));
7596 SSLCertRequestInfo* cert_request_info =
7597 trans.GetResponseInfo()->cert_request_info.get();
7598 ASSERT_TRUE(cert_request_info);
7599 EXPECT_TRUE(cert_request_info->is_proxy);
7600 EXPECT_EQ(cert_request_info->host_and_port, kProxyServer2.host_port_pair());
7601 }
7602
7603 // Test that the endpoint requesting a client auth cert over a multi-proxy chain
7604 // tunnel doesn't cause a crash.
7605 // TODO(https://crbug.com/1491092): Support client auth certificates for
7606 // multi-proxy chains and then replace this test with a more robust one (for
7607 // instance, a version of the AuthEverywhere test that uses a multi-proxy
7608 // chain).
TEST_P(HttpNetworkTransactionTest,HttpsNestedProxyClientAuthCertNeededEndpointNoCrash)7609 TEST_P(HttpNetworkTransactionTest,
7610 HttpsNestedProxyClientAuthCertNeededEndpointNoCrash) {
7611 const ProxyServer kProxyServer1{ProxyServer::SCHEME_HTTPS,
7612 HostPortPair("proxy1.test", 70)};
7613 const ProxyServer kProxyServer2{ProxyServer::SCHEME_HTTPS,
7614 HostPortPair("proxy2.test", 71)};
7615 const ProxyChain kNestedProxyChain{{kProxyServer1, kProxyServer2}};
7616
7617 ProxyList proxy_list;
7618 proxy_list.AddProxyChain(kNestedProxyChain);
7619 ProxyConfig proxy_config = ProxyConfig::CreateForTesting(proxy_list);
7620
7621 session_deps_.proxy_resolution_service =
7622 ConfiguredProxyResolutionService::CreateFixedForTest(
7623 ProxyConfigWithAnnotation(proxy_config,
7624 TRAFFIC_ANNOTATION_FOR_TESTS));
7625 session_deps_.net_log = NetLog::Get();
7626 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
7627
7628 // CONNECT to proxy2.test:71 via SPDY.
7629 spdy::SpdySerializedFrame proxy2_connect(spdy_util_.ConstructSpdyConnect(
7630 nullptr, 0, 1, HttpProxyConnectJob::kH2QuicTunnelPriority,
7631 kProxyServer2.host_port_pair()));
7632
7633 spdy::SpdySerializedFrame proxy2_connect_resp(
7634 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
7635
7636 // CONNECT to www.example.org:443 via SPDY.
7637 // Need to use a new `SpdyTestUtil()` so that the stream parent ID of this
7638 // CONNECT is calculated correctly.
7639 SpdyTestUtil new_spdy_util;
7640 spdy::SpdySerializedFrame endpoint_connect(new_spdy_util.ConstructSpdyConnect(
7641 nullptr, 0, 1, HttpProxyConnectJob::kH2QuicTunnelPriority,
7642 HostPortPair("www.example.org", 443)));
7643
7644 // Since this request and response are sent over the tunnel established
7645 // previously, from a socket-perspective these need to be wrapped as data
7646 // frames.
7647 spdy::SpdySerializedFrame wrapped_endpoint_connect(
7648 spdy_util_.ConstructWrappedSpdyFrame(endpoint_connect, 1));
7649
7650 spdy::SpdySerializedFrame endpoint_connect_resp(
7651 new_spdy_util.ConstructSpdyGetReply(nullptr, 0, 1));
7652 spdy::SpdySerializedFrame wrapped_endpoint_connect_resp(
7653 spdy_util_.ConstructWrappedSpdyFrame(endpoint_connect_resp, 1));
7654
7655 spdy::SpdySerializedFrame rst(
7656 new_spdy_util.ConstructSpdyRstStream(1, spdy::ERROR_CODE_CANCEL));
7657 spdy::SpdySerializedFrame wrapped_rst(
7658 spdy_util_.ConstructWrappedSpdyFrame(rst, 1));
7659
7660 MockWrite spdy_writes[] = {
7661 CreateMockWrite(proxy2_connect, 0),
7662 CreateMockWrite(wrapped_endpoint_connect, 2),
7663 CreateMockWrite(wrapped_rst, 5),
7664 };
7665
7666 MockRead spdy_reads[] = {
7667 CreateMockRead(proxy2_connect_resp, 1, ASYNC),
7668 // TODO(https://crbug.com/497228): We have to manually delay this read so
7669 // that the higher-level SPDY stream doesn't get notified of an available
7670 // read before the write it initiated (the second CONNECT) finishes,
7671 // triggering a DCHECK.
7672 MockRead(ASYNC, ERR_IO_PENDING, 3),
7673 CreateMockRead(wrapped_endpoint_connect_resp, 4, ASYNC),
7674 MockRead(ASYNC, ERR_IO_PENDING, 6),
7675 MockRead(ASYNC, 0, 7),
7676 };
7677
7678 SequencedSocketData spdy_data(spdy_reads, spdy_writes);
7679 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
7680
7681 SSLSocketDataProvider ssl(ASYNC, OK);
7682 ssl.next_proto = kProtoHTTP2;
7683 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
7684
7685 SSLSocketDataProvider ssl2(ASYNC, OK);
7686 ssl2.next_proto = kProtoHTTP2;
7687 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
7688
7689 auto cert_request_info_origin = base::MakeRefCounted<SSLCertRequestInfo>();
7690 cert_request_info_origin->host_and_port =
7691 HostPortPair("www.example.org", 443);
7692
7693 SSLSocketDataProvider ssl3(ASYNC, ERR_SSL_CLIENT_AUTH_CERT_NEEDED);
7694 ssl3.cert_request_info = cert_request_info_origin;
7695 ssl3.expected_send_client_cert = false;
7696 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl3);
7697
7698 HttpRequestInfo request;
7699 request.method = "GET";
7700 request.url = GURL("https://www.example.org/");
7701 request.traffic_annotation =
7702 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
7703
7704 TestCompletionCallback callback;
7705
7706 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
7707
7708 int rv = trans.Start(&request, callback.callback(),
7709 NetLogWithSource::Make(NetLogSourceType::NONE));
7710 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
7711
7712 spdy_data.RunUntilPaused();
7713 base::RunLoop().RunUntilIdle();
7714 spdy_data.Resume();
7715
7716 rv = callback.WaitForResult();
7717 ASSERT_THAT(rv, IsError(ERR_SSL_CLIENT_AUTH_CERT_NEEDED));
7718 SSLCertRequestInfo* cert_request_info =
7719 trans.GetResponseInfo()->cert_request_info.get();
7720 ASSERT_TRUE(cert_request_info);
7721 EXPECT_FALSE(cert_request_info->is_proxy);
7722 EXPECT_EQ(cert_request_info->host_and_port,
7723 HostPortPair("www.example.org", 443));
7724 }
7725
7726 // Verifies that a session which races and wins against the owning transaction
7727 // (completing prior to host resolution), doesn't fail the transaction.
7728 // Regression test for crbug.com/334413.
TEST_P(HttpNetworkTransactionTest,HttpsProxySpdyGetWithSessionRace)7729 TEST_P(HttpNetworkTransactionTest, HttpsProxySpdyGetWithSessionRace) {
7730 HttpRequestInfo request;
7731 request.method = "GET";
7732 request.url = GURL("http://www.example.org/");
7733 request.traffic_annotation =
7734 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
7735
7736 // Configure SPDY proxy server "proxy:70".
7737 session_deps_.proxy_resolution_service =
7738 ConfiguredProxyResolutionService::CreateFixedForTest(
7739 "https://proxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
7740 NetLogWithSource net_log_with_source =
7741 NetLogWithSource::Make(NetLogSourceType::NONE);
7742 session_deps_.net_log = NetLog::Get();
7743 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
7744
7745 // Fetch http://www.example.org/ through the SPDY proxy.
7746 spdy::SpdySerializedFrame req(
7747 spdy_util_.ConstructSpdyGet("http://www.example.org/", 1, LOWEST));
7748 MockWrite spdy_writes[] = {CreateMockWrite(req, 0)};
7749
7750 spdy::SpdySerializedFrame resp(
7751 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
7752 spdy::SpdySerializedFrame data(spdy_util_.ConstructSpdyDataFrame(1, true));
7753 MockRead spdy_reads[] = {
7754 CreateMockRead(resp, 1),
7755 CreateMockRead(data, 2),
7756 MockRead(ASYNC, 0, 3),
7757 };
7758
7759 SequencedSocketData spdy_data(spdy_reads, spdy_writes);
7760 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
7761
7762 SSLSocketDataProvider ssl(ASYNC, OK);
7763 ssl.next_proto = kProtoHTTP2;
7764 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
7765
7766 TestCompletionCallback callback1;
7767
7768 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
7769
7770 // Stall the hostname resolution begun by the transaction.
7771 session_deps_.host_resolver->set_ondemand_mode(true);
7772
7773 int rv = trans.Start(&request, callback1.callback(), net_log_with_source);
7774 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
7775
7776 // Race a session to the proxy, which completes first.
7777 session_deps_.host_resolver->set_ondemand_mode(false);
7778 SpdySessionKey key(HostPortPair("proxy", 70), PRIVACY_MODE_DISABLED,
7779 ProxyChain::Direct(), SessionUsage::kProxy, SocketTag(),
7780 NetworkAnonymizationKey(), SecureDnsPolicy::kAllow,
7781 /*disable_cert_verification_network_fetches=*/true);
7782 base::WeakPtr<SpdySession> spdy_session =
7783 CreateSpdySession(session.get(), key, net_log_with_source);
7784
7785 // Unstall the resolution begun by the transaction.
7786 session_deps_.host_resolver->set_ondemand_mode(true);
7787 session_deps_.host_resolver->ResolveAllPending();
7788
7789 EXPECT_FALSE(callback1.have_result());
7790 rv = callback1.WaitForResult();
7791 EXPECT_THAT(rv, IsOk());
7792
7793 const HttpResponseInfo* response = trans.GetResponseInfo();
7794 ASSERT_TRUE(response);
7795 ASSERT_TRUE(response->headers);
7796 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
7797
7798 std::string response_data;
7799 ASSERT_THAT(ReadTransaction(&trans, &response_data), IsOk());
7800 EXPECT_EQ(kUploadData, response_data);
7801 }
7802
7803 // Test a SPDY GET through an HTTPS proxy that uses proxy auth.
TEST_P(HttpNetworkTransactionTest,HttpsProxySpdyGetWithProxyAuth)7804 TEST_P(HttpNetworkTransactionTest, HttpsProxySpdyGetWithProxyAuth) {
7805 HttpRequestInfo request;
7806 request.method = "GET";
7807 request.url = GURL("http://www.example.org/");
7808 request.traffic_annotation =
7809 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
7810
7811 // Configure against https proxy server "myproxy:70".
7812 session_deps_.proxy_resolution_service =
7813 ConfiguredProxyResolutionService::CreateFixedForTest(
7814 "https://myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
7815 session_deps_.net_log = NetLog::Get();
7816 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
7817
7818 // The first request will be a bare GET, the second request will be a
7819 // GET with a Proxy-Authorization header.
7820 spdy_util_.set_default_url(request.url);
7821 spdy::SpdySerializedFrame req_get(
7822 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST));
7823 spdy_util_.UpdateWithStreamDestruction(1);
7824 const char* const kExtraAuthorizationHeaders[] = {"proxy-authorization",
7825 "Basic Zm9vOmJhcg=="};
7826 spdy::SpdySerializedFrame req_get_authorization(spdy_util_.ConstructSpdyGet(
7827 kExtraAuthorizationHeaders, std::size(kExtraAuthorizationHeaders) / 2, 3,
7828 LOWEST));
7829 MockWrite spdy_writes[] = {
7830 CreateMockWrite(req_get, 0),
7831 CreateMockWrite(req_get_authorization, 3),
7832 };
7833
7834 // The first response is a 407 proxy authentication challenge, and the second
7835 // response will be a 200 response since the second request includes a valid
7836 // Authorization header.
7837 const char* const kExtraAuthenticationHeaders[] = {
7838 "proxy-authenticate", "Basic realm=\"MyRealm1\""};
7839 spdy::SpdySerializedFrame resp_authentication(
7840 spdy_util_.ConstructSpdyReplyError(
7841 "407", kExtraAuthenticationHeaders,
7842 std::size(kExtraAuthenticationHeaders) / 2, 1));
7843 spdy::SpdySerializedFrame body_authentication(
7844 spdy_util_.ConstructSpdyDataFrame(1, true));
7845 spdy::SpdySerializedFrame resp_data(
7846 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 3));
7847 spdy::SpdySerializedFrame body_data(
7848 spdy_util_.ConstructSpdyDataFrame(3, true));
7849 MockRead spdy_reads[] = {
7850 CreateMockRead(resp_authentication, 1),
7851 CreateMockRead(body_authentication, 2, SYNCHRONOUS),
7852 CreateMockRead(resp_data, 4),
7853 CreateMockRead(body_data, 5),
7854 MockRead(ASYNC, 0, 6),
7855 };
7856
7857 SequencedSocketData data(spdy_reads, spdy_writes);
7858 session_deps_.socket_factory->AddSocketDataProvider(&data);
7859
7860 SSLSocketDataProvider ssl(ASYNC, OK);
7861 ssl.next_proto = kProtoHTTP2;
7862 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
7863
7864 TestCompletionCallback callback1;
7865
7866 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
7867
7868 int rv = trans.Start(&request, callback1.callback(),
7869 NetLogWithSource::Make(NetLogSourceType::NONE));
7870 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
7871
7872 rv = callback1.WaitForResult();
7873 EXPECT_THAT(rv, IsOk());
7874
7875 const HttpResponseInfo* const response = trans.GetResponseInfo();
7876
7877 ASSERT_TRUE(response);
7878 ASSERT_TRUE(response->headers);
7879 EXPECT_EQ(407, response->headers->response_code());
7880 EXPECT_TRUE(response->was_fetched_via_spdy);
7881 EXPECT_TRUE(CheckBasicSecureProxyAuth(response->auth_challenge));
7882
7883 TestCompletionCallback callback2;
7884
7885 rv = trans.RestartWithAuth(AuthCredentials(kFoo, kBar), callback2.callback());
7886 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
7887
7888 rv = callback2.WaitForResult();
7889 EXPECT_THAT(rv, IsOk());
7890
7891 const HttpResponseInfo* const response_restart = trans.GetResponseInfo();
7892
7893 ASSERT_TRUE(response_restart);
7894 ASSERT_TRUE(response_restart->headers);
7895 EXPECT_EQ(200, response_restart->headers->response_code());
7896 // The password prompt info should not be set.
7897 EXPECT_FALSE(response_restart->auth_challenge.has_value());
7898 }
7899
7900 // Test a SPDY CONNECT through an HTTPS Proxy to an HTTPS (non-SPDY) Server
7901 // (SPDY -> HTTPS).
TEST_P(HttpNetworkTransactionTest,HttpsProxySpdyConnectHttps)7902 TEST_P(HttpNetworkTransactionTest, HttpsProxySpdyConnectHttps) {
7903 HttpRequestInfo request;
7904 request.method = "GET";
7905 request.url = GURL("https://www.example.org/");
7906 request.traffic_annotation =
7907 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
7908
7909 // Configure against https proxy server "proxy:70".
7910 session_deps_.proxy_resolution_service =
7911 ConfiguredProxyResolutionService::CreateFixedForTest(
7912 "https://proxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
7913 session_deps_.net_log = NetLog::Get();
7914 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
7915
7916 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
7917
7918 // CONNECT to www.example.org:443 via SPDY
7919 spdy::SpdySerializedFrame connect(spdy_util_.ConstructSpdyConnect(
7920 nullptr, 0, 1, HttpProxyConnectJob::kH2QuicTunnelPriority,
7921 HostPortPair("www.example.org", 443)));
7922 // fetch https://www.example.org/ via HTTP
7923
7924 const char kGet[] =
7925 "GET / HTTP/1.1\r\n"
7926 "Host: www.example.org\r\n"
7927 "Connection: keep-alive\r\n\r\n";
7928 spdy::SpdySerializedFrame wrapped_get(
7929 spdy_util_.ConstructSpdyDataFrame(1, kGet, false));
7930 spdy::SpdySerializedFrame conn_resp(
7931 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
7932 const char kResp[] =
7933 "HTTP/1.1 200 OK\r\n"
7934 "Content-Length: 10\r\n\r\n";
7935 spdy::SpdySerializedFrame wrapped_get_resp(
7936 spdy_util_.ConstructSpdyDataFrame(1, kResp, false));
7937 const char kRespData[] = "1234567890";
7938 spdy::SpdySerializedFrame wrapped_body(
7939 spdy_util_.ConstructSpdyDataFrame(1, kRespData, false));
7940
7941 MockWrite spdy_writes[] = {
7942 CreateMockWrite(connect, 0),
7943 CreateMockWrite(wrapped_get, 2),
7944 };
7945
7946 MockRead spdy_reads[] = {
7947 CreateMockRead(conn_resp, 1, ASYNC),
7948 CreateMockRead(wrapped_get_resp, 3, ASYNC),
7949 CreateMockRead(wrapped_body, 4, ASYNC),
7950 MockRead(ASYNC, 0, 5),
7951 };
7952
7953 SequencedSocketData spdy_data(spdy_reads, spdy_writes);
7954 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
7955
7956 SSLSocketDataProvider ssl(ASYNC, OK);
7957 ssl.next_proto = kProtoHTTP2;
7958 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
7959 SSLSocketDataProvider ssl2(ASYNC, OK);
7960 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
7961
7962 TestCompletionCallback callback1;
7963
7964 int rv = trans.Start(&request, callback1.callback(),
7965 NetLogWithSource::Make(NetLogSourceType::NONE));
7966 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
7967
7968 rv = callback1.WaitForResult();
7969 ASSERT_THAT(rv, IsOk());
7970
7971 LoadTimingInfo load_timing_info;
7972 EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info));
7973 TestLoadTimingNotReused(load_timing_info, CONNECT_TIMING_HAS_SSL_TIMES);
7974
7975 const HttpResponseInfo* response = trans.GetResponseInfo();
7976 ASSERT_TRUE(response);
7977 ASSERT_TRUE(response->headers);
7978 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
7979
7980 std::string response_data;
7981 ASSERT_THAT(ReadTransaction(&trans, &response_data), IsOk());
7982 EXPECT_EQ(kRespData, response_data);
7983 }
7984
7985 // Test a SPDY CONNECT through two HTTPS (SPDY) proxies to an HTTPS (non-SPDY)
7986 // server (SPDY -> SPDY -> HTTPS).
TEST_P(HttpNetworkTransactionTest,HttpsNestedProxySpdyConnectHttps)7987 TEST_P(HttpNetworkTransactionTest, HttpsNestedProxySpdyConnectHttps) {
7988 HttpRequestInfo request;
7989 request.method = "GET";
7990 request.url = GURL("https://www.example.org/");
7991 request.traffic_annotation =
7992 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
7993
7994 // Configure a nested proxy.
7995 const ProxyServer kProxyServer1{ProxyServer::SCHEME_HTTPS,
7996 HostPortPair("proxy1.test", 70)};
7997 const ProxyServer kProxyServer2{ProxyServer::SCHEME_HTTPS,
7998 HostPortPair("proxy2.test", 71)};
7999 const ProxyChain kNestedProxyChain{{kProxyServer1, kProxyServer2}};
8000
8001 ProxyList proxy_list;
8002 proxy_list.AddProxyChain(kNestedProxyChain);
8003 ProxyConfig proxy_config = ProxyConfig::CreateForTesting(proxy_list);
8004
8005 session_deps_.proxy_resolution_service =
8006 ConfiguredProxyResolutionService::CreateFixedForTest(
8007 ProxyConfigWithAnnotation(proxy_config,
8008 TRAFFIC_ANNOTATION_FOR_TESTS));
8009
8010 session_deps_.net_log = NetLog::Get();
8011 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
8012
8013 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
8014
8015 // CONNECT to proxy2.test:71 via SPDY.
8016 spdy::SpdySerializedFrame proxy2_connect(spdy_util_.ConstructSpdyConnect(
8017 nullptr, 0, 1, HttpProxyConnectJob::kH2QuicTunnelPriority,
8018 kProxyServer2.host_port_pair()));
8019
8020 spdy::SpdySerializedFrame proxy2_connect_resp(
8021 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
8022
8023 // CONNECT to www.example.org:443 via SPDY.
8024 // Need to use a new `SpdyTestUtil()` so that the stream parent ID of this
8025 // CONNECT is calculated correctly.
8026 SpdyTestUtil new_spdy_util;
8027 spdy::SpdySerializedFrame endpoint_connect(new_spdy_util.ConstructSpdyConnect(
8028 nullptr, 0, 1, HttpProxyConnectJob::kH2QuicTunnelPriority,
8029 HostPortPair("www.example.org", 443)));
8030
8031 // Since this request and response are sent over the tunnel established
8032 // previously, from a socket-perspective these need to be wrapped as data
8033 // frames.
8034 spdy::SpdySerializedFrame wrapped_endpoint_connect(
8035 spdy_util_.ConstructWrappedSpdyFrame(endpoint_connect, 1));
8036
8037 spdy::SpdySerializedFrame endpoint_connect_resp(
8038 new_spdy_util.ConstructSpdyGetReply(nullptr, 0, 1));
8039 spdy::SpdySerializedFrame wrapped_endpoint_connect_resp(
8040 spdy_util_.ConstructWrappedSpdyFrame(endpoint_connect_resp, 1));
8041
8042 // fetch https://www.example.org/ via HTTP.
8043 // Since this request will go over two tunnels, it needs to be double-wrapped.
8044 const char kGet[] =
8045 "GET / HTTP/1.1\r\n"
8046 "Host: www.example.org\r\n"
8047 "Connection: keep-alive\r\n\r\n";
8048 spdy::SpdySerializedFrame wrapped_get(
8049 new_spdy_util.ConstructSpdyDataFrame(1, kGet, false));
8050 spdy::SpdySerializedFrame wrapped_wrapped_get(
8051 spdy_util_.ConstructWrappedSpdyFrame(wrapped_get, 1));
8052
8053 const char kResp[] =
8054 "HTTP/1.1 200 OK\r\n"
8055 "Content-Length: 10\r\n\r\n";
8056 spdy::SpdySerializedFrame wrapped_get_resp(
8057 new_spdy_util.ConstructSpdyDataFrame(1, kResp, false));
8058 spdy::SpdySerializedFrame wrapped_wrapped_get_resp(
8059 spdy_util_.ConstructWrappedSpdyFrame(wrapped_get_resp, 1));
8060
8061 const char kRespData[] = "1234567890";
8062 spdy::SpdySerializedFrame wrapped_body(
8063 new_spdy_util.ConstructSpdyDataFrame(1, kRespData, false));
8064 spdy::SpdySerializedFrame wrapped_wrapped_body(
8065 spdy_util_.ConstructWrappedSpdyFrame(wrapped_body, 1));
8066
8067 MockWrite spdy_writes[] = {
8068 CreateMockWrite(proxy2_connect, 0),
8069 CreateMockWrite(wrapped_endpoint_connect, 2),
8070 CreateMockWrite(wrapped_wrapped_get, 5),
8071 };
8072
8073 MockRead spdy_reads[] = {
8074 CreateMockRead(proxy2_connect_resp, 1, ASYNC),
8075 // TODO(https://crbug.com/497228): We have to manually delay this read so
8076 // that the higher-level SPDY stream doesn't get notified of an available
8077 // read before the write it initiated (the second CONNECT) finishes,
8078 // triggering a DCHECK.
8079 MockRead(ASYNC, ERR_IO_PENDING, 3),
8080 CreateMockRead(wrapped_endpoint_connect_resp, 4, ASYNC),
8081 CreateMockRead(wrapped_wrapped_get_resp, 6, ASYNC),
8082 CreateMockRead(wrapped_wrapped_body, 7, ASYNC),
8083 MockRead(ASYNC, 0, 8),
8084 };
8085
8086 SequencedSocketData spdy_data(spdy_reads, spdy_writes);
8087 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
8088
8089 SSLSocketDataProvider ssl(ASYNC, OK);
8090 ssl.next_proto = kProtoHTTP2;
8091 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
8092 SSLSocketDataProvider ssl2(ASYNC, OK);
8093 ssl2.next_proto = kProtoHTTP2;
8094 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
8095 SSLSocketDataProvider ssl3(ASYNC, OK);
8096 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl3);
8097
8098 TestCompletionCallback callback1;
8099
8100 int rv = trans.Start(&request, callback1.callback(),
8101 NetLogWithSource::Make(NetLogSourceType::NONE));
8102 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
8103
8104 spdy_data.RunUntilPaused();
8105 base::RunLoop().RunUntilIdle();
8106 spdy_data.Resume();
8107
8108 rv = callback1.WaitForResult();
8109 ASSERT_THAT(rv, IsOk());
8110
8111 LoadTimingInfo load_timing_info;
8112 EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info));
8113 TestLoadTimingNotReused(load_timing_info, CONNECT_TIMING_HAS_SSL_TIMES);
8114
8115 const HttpResponseInfo* response = trans.GetResponseInfo();
8116 ASSERT_TRUE(response);
8117 ASSERT_TRUE(response->headers);
8118 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
8119
8120 std::string response_data;
8121 ASSERT_THAT(ReadTransaction(&trans, &response_data), IsOk());
8122 EXPECT_EQ(kRespData, response_data);
8123 }
8124
8125 // Test a SPDY CONNECT through an HTTPS Proxy to a SPDY server (SPDY -> SPDY).
TEST_P(HttpNetworkTransactionTest,HttpsProxySpdyConnectSpdy)8126 TEST_P(HttpNetworkTransactionTest, HttpsProxySpdyConnectSpdy) {
8127 SpdyTestUtil spdy_util_wrapped(/*use_priority_header=*/true);
8128
8129 HttpRequestInfo request;
8130 request.method = "GET";
8131 request.url = GURL("https://www.example.org/");
8132 request.traffic_annotation =
8133 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
8134
8135 // Configure against https proxy server "proxy:70".
8136 session_deps_.proxy_resolution_service =
8137 ConfiguredProxyResolutionService::CreateFixedForTest(
8138 "https://proxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
8139 session_deps_.net_log = NetLog::Get();
8140 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
8141
8142 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
8143
8144 // CONNECT to www.example.org:443 via SPDY
8145 spdy::SpdySerializedFrame connect(spdy_util_.ConstructSpdyConnect(
8146 nullptr, 0, 1, HttpProxyConnectJob::kH2QuicTunnelPriority,
8147 HostPortPair("www.example.org", 443)));
8148 // fetch https://www.example.org/ via SPDY
8149 const char kMyUrl[] = "https://www.example.org/";
8150 spdy::SpdySerializedFrame get(
8151 spdy_util_wrapped.ConstructSpdyGet(kMyUrl, 1, LOWEST));
8152 spdy::SpdySerializedFrame wrapped_get(
8153 spdy_util_.ConstructWrappedSpdyFrame(get, 1));
8154 spdy::SpdySerializedFrame conn_resp(
8155 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
8156 spdy::SpdySerializedFrame get_resp(
8157 spdy_util_wrapped.ConstructSpdyGetReply(nullptr, 0, 1));
8158 spdy::SpdySerializedFrame wrapped_get_resp(
8159 spdy_util_.ConstructWrappedSpdyFrame(get_resp, 1));
8160 spdy::SpdySerializedFrame body(
8161 spdy_util_wrapped.ConstructSpdyDataFrame(1, true));
8162 spdy::SpdySerializedFrame wrapped_body(
8163 spdy_util_.ConstructWrappedSpdyFrame(body, 1));
8164 spdy::SpdySerializedFrame window_update_get_resp(
8165 spdy_util_.ConstructSpdyWindowUpdate(1, wrapped_get_resp.size()));
8166 spdy::SpdySerializedFrame window_update_body(
8167 spdy_util_.ConstructSpdyWindowUpdate(1, wrapped_body.size()));
8168
8169 MockWrite spdy_writes[] = {
8170 CreateMockWrite(connect, 0),
8171 CreateMockWrite(wrapped_get, 2),
8172 CreateMockWrite(window_update_get_resp, 6),
8173 CreateMockWrite(window_update_body, 7),
8174 };
8175
8176 MockRead spdy_reads[] = {
8177 CreateMockRead(conn_resp, 1, ASYNC),
8178 MockRead(ASYNC, ERR_IO_PENDING, 3),
8179 CreateMockRead(wrapped_get_resp, 4, ASYNC),
8180 CreateMockRead(wrapped_body, 5, ASYNC),
8181 MockRead(ASYNC, 0, 8),
8182 };
8183
8184 SequencedSocketData spdy_data(spdy_reads, spdy_writes);
8185 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
8186
8187 SSLSocketDataProvider ssl(ASYNC, OK);
8188 ssl.next_proto = kProtoHTTP2;
8189 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
8190 SSLSocketDataProvider ssl2(ASYNC, OK);
8191 ssl2.next_proto = kProtoHTTP2;
8192 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
8193
8194 TestCompletionCallback callback1;
8195
8196 int rv = trans.Start(&request, callback1.callback(),
8197 NetLogWithSource::Make(NetLogSourceType::NONE));
8198 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
8199
8200 // Allow the SpdyProxyClientSocket's write callback to complete.
8201 base::RunLoop().RunUntilIdle();
8202 // Now allow the read of the response to complete.
8203 spdy_data.Resume();
8204 rv = callback1.WaitForResult();
8205 EXPECT_THAT(rv, IsOk());
8206
8207 LoadTimingInfo load_timing_info;
8208 EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info));
8209 TestLoadTimingNotReused(load_timing_info, CONNECT_TIMING_HAS_SSL_TIMES);
8210
8211 const HttpResponseInfo* response = trans.GetResponseInfo();
8212 ASSERT_TRUE(response);
8213 ASSERT_TRUE(response->headers);
8214 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
8215
8216 std::string response_data;
8217 ASSERT_THAT(ReadTransaction(&trans, &response_data), IsOk());
8218 EXPECT_EQ(kUploadData, response_data);
8219 }
8220
8221 // Test a SPDY CONNECT for an HTTPS (non-SPDY) endpoint through an HTTPS
8222 // (non-SPDY) proxy and HTTPS (SPDY) proxy chain (HTTPS -> SPDY -> HTTPS).
TEST_P(HttpNetworkTransactionTest,HttpsNestedProxyMixedConnectSpdy)8223 TEST_P(HttpNetworkTransactionTest, HttpsNestedProxyMixedConnectSpdy) {
8224 HttpRequestInfo request;
8225 request.method = "GET";
8226 request.url = GURL("https://www.example.org/");
8227 request.traffic_annotation =
8228 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
8229
8230 // Configure a nested proxy.
8231 const ProxyServer kProxyServer1{ProxyServer::SCHEME_HTTPS,
8232 HostPortPair("proxy1.test", 70)};
8233 const ProxyServer kProxyServer2{ProxyServer::SCHEME_HTTPS,
8234 HostPortPair("proxy2.test", 71)};
8235 const ProxyChain kNestedProxyChain{{kProxyServer1, kProxyServer2}};
8236
8237 ProxyList proxy_list;
8238 proxy_list.AddProxyChain(kNestedProxyChain);
8239 ProxyConfig proxy_config = ProxyConfig::CreateForTesting(proxy_list);
8240
8241 session_deps_.proxy_resolution_service =
8242 ConfiguredProxyResolutionService::CreateFixedForTest(
8243 ProxyConfigWithAnnotation(proxy_config,
8244 TRAFFIC_ANNOTATION_FOR_TESTS));
8245 session_deps_.net_log = NetLog::Get();
8246 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
8247
8248 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
8249
8250 // CONNECT to proxy2.test:71 via HTTP.
8251 const char kProxy2Connect[] =
8252 "CONNECT proxy2.test:71 HTTP/1.1\r\n"
8253 "Host: proxy2.test:71\r\n"
8254 "Proxy-Connection: keep-alive\r\n\r\n";
8255
8256 const char kProxy2ConnectResp[] =
8257 "HTTP/1.1 200 Connection Established\r\n\r\n";
8258
8259 // CONNECT to www.example.org:443 via SPDY.
8260 spdy::SpdySerializedFrame endpoint_connect(spdy_util_.ConstructSpdyConnect(
8261 nullptr, 0, 1, HttpProxyConnectJob::kH2QuicTunnelPriority,
8262 HostPortPair("www.example.org", 443)));
8263
8264 spdy::SpdySerializedFrame endpoint_connect_resp(
8265 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
8266
8267 // fetch https://www.example.org/ via HTTP.
8268 // Since this request and response are sent over the tunnel established
8269 // previously, from a socket-perspective these need to be wrapped as data
8270 // frames.
8271 const char kGet[] =
8272 "GET / HTTP/1.1\r\n"
8273 "Host: www.example.org\r\n"
8274 "Connection: keep-alive\r\n\r\n";
8275 spdy::SpdySerializedFrame wrapped_get(
8276 spdy_util_.ConstructSpdyDataFrame(1, kGet, false));
8277
8278 const char kResp[] =
8279 "HTTP/1.1 200 OK\r\n"
8280 "Content-Length: 10\r\n\r\n";
8281 spdy::SpdySerializedFrame wrapped_get_resp(
8282 spdy_util_.ConstructSpdyDataFrame(1, kResp, false));
8283
8284 const char kRespData[] = "1234567890";
8285 spdy::SpdySerializedFrame wrapped_body(
8286 spdy_util_.ConstructSpdyDataFrame(1, kRespData, false));
8287
8288 MockWrite socket_writes[] = {
8289 MockWrite(ASYNC, 0, kProxy2Connect),
8290 CreateMockWrite(endpoint_connect, 2),
8291 CreateMockWrite(wrapped_get, 4),
8292 };
8293
8294 MockRead socket_reads[] = {
8295 MockRead(ASYNC, 1, kProxy2ConnectResp),
8296 CreateMockRead(endpoint_connect_resp, 3, ASYNC),
8297 CreateMockRead(wrapped_get_resp, 5, ASYNC),
8298 CreateMockRead(wrapped_body, 6, ASYNC),
8299 MockRead(ASYNC, 0, 7),
8300 };
8301
8302 SequencedSocketData socket_data(socket_reads, socket_writes);
8303 session_deps_.socket_factory->AddSocketDataProvider(&socket_data);
8304
8305 SSLSocketDataProvider ssl(ASYNC, OK);
8306 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
8307 SSLSocketDataProvider ssl2(ASYNC, OK);
8308 ssl2.next_proto = kProtoHTTP2;
8309 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
8310 SSLSocketDataProvider ssl3(ASYNC, OK);
8311 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl3);
8312
8313 TestCompletionCallback callback1;
8314
8315 int rv = trans.Start(&request, callback1.callback(),
8316 NetLogWithSource::Make(NetLogSourceType::NONE));
8317 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
8318
8319 rv = callback1.WaitForResult();
8320 ASSERT_THAT(rv, IsOk());
8321
8322 LoadTimingInfo load_timing_info;
8323 EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info));
8324 TestLoadTimingNotReused(load_timing_info, CONNECT_TIMING_HAS_SSL_TIMES);
8325
8326 const HttpResponseInfo* response = trans.GetResponseInfo();
8327 ASSERT_TRUE(response);
8328 ASSERT_TRUE(response->headers);
8329 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
8330
8331 std::string response_data;
8332 ASSERT_THAT(ReadTransaction(&trans, &response_data), IsOk());
8333 EXPECT_EQ(kRespData, response_data);
8334 }
8335
8336 // Test an HTTP CONNECT for an HTTPS (non-SPDY) endpoint through an HTTPS (SPDY)
8337 // proxy and HTTPS (non-SPDY) proxy chain (SPDY -> HTTPS -> HTTPS).
TEST_P(HttpNetworkTransactionTest,HttpsNestedProxyMixedConnectHttps)8338 TEST_P(HttpNetworkTransactionTest, HttpsNestedProxyMixedConnectHttps) {
8339 HttpRequestInfo request;
8340 request.method = "GET";
8341 request.url = GURL("https://www.example.org/");
8342 request.traffic_annotation =
8343 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
8344
8345 // Configure a nested proxy.
8346 const ProxyServer kProxyServer1{ProxyServer::SCHEME_HTTPS,
8347 HostPortPair("proxy1.test", 70)};
8348 const ProxyServer kProxyServer2{ProxyServer::SCHEME_HTTPS,
8349 HostPortPair("proxy2.test", 71)};
8350 const ProxyChain kNestedProxyChain{{kProxyServer1, kProxyServer2}};
8351
8352 ProxyList proxy_list;
8353 proxy_list.AddProxyChain(kNestedProxyChain);
8354 ProxyConfig proxy_config = ProxyConfig::CreateForTesting(proxy_list);
8355
8356 session_deps_.proxy_resolution_service =
8357 ConfiguredProxyResolutionService::CreateFixedForTest(
8358 ProxyConfigWithAnnotation(proxy_config,
8359 TRAFFIC_ANNOTATION_FOR_TESTS));
8360 session_deps_.net_log = NetLog::Get();
8361 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
8362
8363 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
8364
8365 // CONNECT to proxy2.test:71 via SPDY.
8366 spdy::SpdySerializedFrame proxy2_connect(spdy_util_.ConstructSpdyConnect(
8367 nullptr, 0, 1, HttpProxyConnectJob::kH2QuicTunnelPriority,
8368 kProxyServer2.host_port_pair()));
8369
8370 spdy::SpdySerializedFrame proxy2_connect_resp(
8371 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
8372
8373 // CONNECT to www.example.org:443 via HTTPS.
8374 const char kEndpointConnect[] =
8375 "CONNECT www.example.org:443 HTTP/1.1\r\n"
8376 "Host: www.example.org:443\r\n"
8377 "Proxy-Connection: keep-alive\r\n\r\n";
8378
8379 const char kEndpointConnectResp[] =
8380 "HTTP/1.1 200 Connection Established\r\n\r\n";
8381
8382 // Since this request and response are sent over the tunnel established
8383 // previously, from a socket-perspective these need to be wrapped as data
8384 // frames.
8385 spdy::SpdySerializedFrame wrapped_endpoint_connect(
8386 spdy_util_.ConstructSpdyDataFrame(1, kEndpointConnect, false));
8387 spdy::SpdySerializedFrame wrapped_endpoint_connect_resp(
8388 spdy_util_.ConstructSpdyDataFrame(1, kEndpointConnectResp, false));
8389
8390 // fetch https://www.example.org/ via HTTP.
8391 // Since this request will go over the SPDY tunnel, it needs to be wrapped as
8392 // well.
8393 const char kGet[] =
8394 "GET / HTTP/1.1\r\n"
8395 "Host: www.example.org\r\n"
8396 "Connection: keep-alive\r\n\r\n";
8397 spdy::SpdySerializedFrame wrapped_get(
8398 spdy_util_.ConstructSpdyDataFrame(1, kGet, false));
8399
8400 const char kResp[] =
8401 "HTTP/1.1 200 OK\r\n"
8402 "Content-Length: 10\r\n\r\n";
8403 spdy::SpdySerializedFrame wrapped_get_resp(
8404 spdy_util_.ConstructSpdyDataFrame(1, kResp, false));
8405
8406 const char kRespData[] = "1234567890";
8407 spdy::SpdySerializedFrame wrapped_body(
8408 spdy_util_.ConstructSpdyDataFrame(1, kRespData, false));
8409
8410 MockWrite spdy_writes[] = {
8411 CreateMockWrite(proxy2_connect, 0),
8412 CreateMockWrite(wrapped_endpoint_connect, 2),
8413 CreateMockWrite(wrapped_get, 4),
8414 };
8415
8416 MockRead spdy_reads[] = {
8417 CreateMockRead(proxy2_connect_resp, 1, ASYNC),
8418 CreateMockRead(wrapped_endpoint_connect_resp, 3, ASYNC),
8419 CreateMockRead(wrapped_get_resp, 5, ASYNC),
8420 CreateMockRead(wrapped_body, 6, ASYNC),
8421 MockRead(ASYNC, 0, 7),
8422 };
8423
8424 SequencedSocketData spdy_data(spdy_reads, spdy_writes);
8425 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
8426
8427 SSLSocketDataProvider ssl(ASYNC, OK);
8428 ssl.next_proto = kProtoHTTP2;
8429 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
8430 SSLSocketDataProvider ssl2(ASYNC, OK);
8431 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
8432 SSLSocketDataProvider ssl3(ASYNC, OK);
8433 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl3);
8434
8435 TestCompletionCallback callback1;
8436
8437 int rv = trans.Start(&request, callback1.callback(),
8438 NetLogWithSource::Make(NetLogSourceType::NONE));
8439 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
8440
8441 rv = callback1.WaitForResult();
8442 ASSERT_THAT(rv, IsOk());
8443
8444 LoadTimingInfo load_timing_info;
8445 EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info));
8446 TestLoadTimingNotReused(load_timing_info, CONNECT_TIMING_HAS_SSL_TIMES);
8447
8448 const HttpResponseInfo* response = trans.GetResponseInfo();
8449 ASSERT_TRUE(response);
8450 ASSERT_TRUE(response->headers);
8451 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
8452
8453 std::string response_data;
8454 ASSERT_THAT(ReadTransaction(&trans, &response_data), IsOk());
8455 EXPECT_EQ(kRespData, response_data);
8456 }
8457
8458 // Test a SPDY CONNECT failure through an HTTPS (SPDY) proxy
8459 // (SPDY -> HTTPS/SPDY).
TEST_P(HttpNetworkTransactionTest,HttpsProxySpdyConnectFailure)8460 TEST_P(HttpNetworkTransactionTest, HttpsProxySpdyConnectFailure) {
8461 HttpRequestInfo request;
8462 request.method = "GET";
8463 request.url = GURL("https://www.example.org/");
8464 request.traffic_annotation =
8465 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
8466
8467 // Configure against https proxy server "proxy:70".
8468 session_deps_.proxy_resolution_service =
8469 ConfiguredProxyResolutionService::CreateFixedForTest(
8470 "https://proxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
8471 session_deps_.net_log = NetLog::Get();
8472 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
8473
8474 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
8475
8476 // CONNECT to www.example.org:443 via SPDY.
8477 spdy::SpdySerializedFrame connect(spdy_util_.ConstructSpdyConnect(
8478 nullptr, 0, 1, HttpProxyConnectJob::kH2QuicTunnelPriority,
8479 HostPortPair("www.example.org", 443)));
8480 spdy::SpdySerializedFrame rst(
8481 spdy_util_.ConstructSpdyRstStream(1, spdy::ERROR_CODE_CANCEL));
8482
8483 MockWrite spdy_writes[] = {
8484 CreateMockWrite(connect, 0),
8485 CreateMockWrite(rst, 2),
8486 };
8487
8488 spdy::SpdySerializedFrame resp(spdy_util_.ConstructSpdyReplyError(1));
8489 MockRead spdy_reads[] = {
8490 CreateMockRead(resp, 1, ASYNC),
8491 // Pause instead of triggering a connection close so that it's more clear
8492 // which action is causing the tunnel error (the endpoint connect error
8493 // above).
8494 MockRead(ASYNC, ERR_IO_PENDING, 3),
8495 MockRead(ASYNC, 0, 4),
8496 };
8497
8498 SequencedSocketData spdy_data(spdy_reads, spdy_writes);
8499 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
8500
8501 SSLSocketDataProvider ssl(ASYNC, OK);
8502 ssl.next_proto = kProtoHTTP2;
8503 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
8504
8505 TestCompletionCallback callback1;
8506
8507 int rv = trans.Start(&request, callback1.callback(),
8508 NetLogWithSource::Make(NetLogSourceType::NONE));
8509 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
8510
8511 rv = callback1.WaitForResult();
8512 EXPECT_THAT(rv, IsError(ERR_TUNNEL_CONNECTION_FAILED));
8513
8514 // TODO(juliatuttle): Anything else to check here?
8515 }
8516
8517 // Test a SPDY CONNECT failure through two HTTPS (SPDY) proxies where the
8518 // connection to the first proxy fails (SPDY -> HTTPS/SPDY -> HTTPS/SPDY).
TEST_P(HttpNetworkTransactionTest,HttpsNestedProxySpdyConnectFirstProxyFailure)8519 TEST_P(HttpNetworkTransactionTest,
8520 HttpsNestedProxySpdyConnectFirstProxyFailure) {
8521 HttpRequestInfo request;
8522 request.method = "GET";
8523 request.url = GURL("https://www.example.org/");
8524 request.traffic_annotation =
8525 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
8526
8527 // Configure a nested proxy.
8528 const ProxyServer kProxyServer1{ProxyServer::SCHEME_HTTPS,
8529 HostPortPair("proxy1.test", 70)};
8530 const ProxyServer kProxyServer2{ProxyServer::SCHEME_HTTPS,
8531 HostPortPair("proxy2.test", 71)};
8532 const ProxyChain kNestedProxyChain{{kProxyServer1, kProxyServer2}};
8533
8534 ProxyList proxy_list;
8535 proxy_list.AddProxyChain(kNestedProxyChain);
8536 ProxyConfig proxy_config = ProxyConfig::CreateForTesting(proxy_list);
8537
8538 session_deps_.proxy_resolution_service =
8539 ConfiguredProxyResolutionService::CreateFixedForTest(
8540 ProxyConfigWithAnnotation(proxy_config,
8541 TRAFFIC_ANNOTATION_FOR_TESTS));
8542 session_deps_.net_log = NetLog::Get();
8543 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
8544
8545 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
8546
8547 // CONNECT to proxy2.test:71 via SPDY.
8548 spdy::SpdySerializedFrame proxy2_connect(spdy_util_.ConstructSpdyConnect(
8549 nullptr, 0, 1, HttpProxyConnectJob::kH2QuicTunnelPriority,
8550 kProxyServer2.host_port_pair()));
8551 spdy::SpdySerializedFrame proxy2_connect_error_resp(
8552 spdy_util_.ConstructSpdyReplyError(1));
8553
8554 spdy::SpdySerializedFrame rst(
8555 spdy_util_.ConstructSpdyRstStream(1, spdy::ERROR_CODE_CANCEL));
8556
8557 MockWrite spdy_writes[] = {
8558 CreateMockWrite(proxy2_connect, 0),
8559 CreateMockWrite(rst, 2),
8560 };
8561 MockRead spdy_reads[] = {
8562 CreateMockRead(proxy2_connect_error_resp, 1, ASYNC),
8563 // Pause instead of triggering a connection close so that it's more clear
8564 // which action is causing the tunnel error (the endpoint connect error
8565 // above).
8566 MockRead(ASYNC, ERR_IO_PENDING, 3),
8567 MockRead(ASYNC, 0, 4),
8568 };
8569
8570 SequencedSocketData spdy_data(spdy_reads, spdy_writes);
8571 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
8572
8573 SSLSocketDataProvider ssl(ASYNC, OK);
8574 ssl.next_proto = kProtoHTTP2;
8575 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
8576
8577 TestCompletionCallback callback1;
8578
8579 int rv = trans.Start(&request, callback1.callback(),
8580 NetLogWithSource::Make(NetLogSourceType::NONE));
8581 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
8582
8583 rv = callback1.WaitForResult();
8584 EXPECT_THAT(rv, IsError(ERR_TUNNEL_CONNECTION_FAILED));
8585 }
8586
8587 // Test a SPDY CONNECT failure through two HTTPS (SPDY) proxies where the
8588 // connection to the second proxy fails (SPDY -> SPDY -> HTTPS/SPDY).
TEST_P(HttpNetworkTransactionTest,HttpsNestedProxySpdyConnectSecondProxyFailure)8589 TEST_P(HttpNetworkTransactionTest,
8590 HttpsNestedProxySpdyConnectSecondProxyFailure) {
8591 HttpRequestInfo request;
8592 request.method = "GET";
8593 request.url = GURL("https://www.example.org/");
8594 request.traffic_annotation =
8595 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
8596
8597 // Configure a nested proxy.
8598 const ProxyServer kProxyServer1{ProxyServer::SCHEME_HTTPS,
8599 HostPortPair("proxy1.test", 70)};
8600 const ProxyServer kProxyServer2{ProxyServer::SCHEME_HTTPS,
8601 HostPortPair("proxy2.test", 71)};
8602 const ProxyChain kNestedProxyChain{{kProxyServer1, kProxyServer2}};
8603
8604 ProxyList proxy_list;
8605 proxy_list.AddProxyChain(kNestedProxyChain);
8606 ProxyConfig proxy_config = ProxyConfig::CreateForTesting(proxy_list);
8607
8608 session_deps_.proxy_resolution_service =
8609 std::make_unique<ConfiguredProxyResolutionService>(
8610 std::make_unique<ProxyConfigServiceFixed>(ProxyConfigWithAnnotation(
8611 proxy_config, TRAFFIC_ANNOTATION_FOR_TESTS)),
8612 /*resolver_factory=*/nullptr,
8613 /*net_log=*/nullptr, /*quick_check_enabled=*/true);
8614 session_deps_.net_log = NetLog::Get();
8615 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
8616
8617 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
8618
8619 // CONNECT to proxy2.test:71 via SPDY.
8620 spdy::SpdySerializedFrame proxy2_connect(spdy_util_.ConstructSpdyConnect(
8621 nullptr, 0, 1, HttpProxyConnectJob::kH2QuicTunnelPriority,
8622 kProxyServer2.host_port_pair()));
8623
8624 spdy::SpdySerializedFrame proxy2_connect_resp(
8625 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
8626
8627 // Need to use a new `SpdyTestUtil()` so that the stream parent ID of this
8628 // request is calculated correctly.
8629 SpdyTestUtil new_spdy_util;
8630 // CONNECT to www.example.org:443 via SPDY.
8631 spdy::SpdySerializedFrame endpoint_connect(new_spdy_util.ConstructSpdyConnect(
8632 nullptr, 0, 1, HttpProxyConnectJob::kH2QuicTunnelPriority,
8633 HostPortPair("www.example.org", 443)));
8634 spdy::SpdySerializedFrame rst(
8635 new_spdy_util.ConstructSpdyRstStream(1, spdy::ERROR_CODE_CANCEL));
8636
8637 // Since this request and response are sent over the tunnel established
8638 // previously, from a socket-perspective these need to be wrapped as data
8639 // frames.
8640 spdy::SpdySerializedFrame wrapped_endpoint_connect(
8641 spdy_util_.ConstructSpdyDataFrame(1, endpoint_connect, false));
8642 spdy::SpdySerializedFrame wrapped_rst(
8643 spdy_util_.ConstructSpdyDataFrame(1, rst, false));
8644
8645 spdy::SpdySerializedFrame endpoint_connect_error_resp(
8646 new_spdy_util.ConstructSpdyReplyError(1));
8647 spdy::SpdySerializedFrame wrapped_endpoint_connect_error_resp(
8648 spdy_util_.ConstructSpdyDataFrame(1, endpoint_connect_error_resp, false));
8649
8650 MockWrite spdy_writes[] = {
8651 CreateMockWrite(proxy2_connect, 0),
8652 CreateMockWrite(wrapped_endpoint_connect, 2),
8653 CreateMockWrite(wrapped_rst, 5),
8654 };
8655
8656 MockRead spdy_reads[] = {
8657 CreateMockRead(proxy2_connect_resp, 1, ASYNC),
8658 // TODO(https://crbug.com/497228): We have to manually delay this read so
8659 // that the higher-level SPDY stream doesn't get notified of an available
8660 // read before the write it initiated (the second CONNECT) finishes,
8661 // triggering a DCHECK.
8662 MockRead(ASYNC, ERR_IO_PENDING, 3),
8663 CreateMockRead(wrapped_endpoint_connect_error_resp, 4, ASYNC),
8664 // Pause instead of triggering a connection close so that it's more clear
8665 // which action is causing the tunnel error (the endpoint connect error
8666 // above).
8667 MockRead(ASYNC, ERR_IO_PENDING, 6),
8668 MockRead(ASYNC, 0, 7),
8669 };
8670
8671 SequencedSocketData spdy_data(spdy_reads, spdy_writes);
8672 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
8673
8674 SSLSocketDataProvider ssl(ASYNC, OK);
8675 ssl.next_proto = kProtoHTTP2;
8676 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
8677 SSLSocketDataProvider ssl2(ASYNC, OK);
8678 ssl2.next_proto = kProtoHTTP2;
8679 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
8680
8681 TestCompletionCallback callback1;
8682
8683 int rv = trans.Start(&request, callback1.callback(),
8684 NetLogWithSource::Make(NetLogSourceType::NONE));
8685 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
8686
8687 spdy_data.RunUntilPaused();
8688 base::RunLoop().RunUntilIdle();
8689 spdy_data.Resume();
8690
8691 rv = callback1.WaitForResult();
8692 EXPECT_THAT(rv, IsError(ERR_TUNNEL_CONNECTION_FAILED));
8693 }
8694
8695 // This method creates a tunnel using `chain1`, proxies an HTTP GET request
8696 // through it to ensure that it has been created successfully, and then creates
8697 // another tunnel using `chain2` to check whether a new socket is used for it.
8698 // This is used to test that no unexpected socket reuse occurs between different
8699 // proxy chains.
HttpsNestedProxyNoSocketReuseHelper(const net::ProxyChain & chain1,const net::ProxyChain & chain2)8700 void HttpNetworkTransactionTestBase::HttpsNestedProxyNoSocketReuseHelper(
8701 const net::ProxyChain& chain1,
8702 const net::ProxyChain& chain2) {
8703 ASSERT_NE(chain1, chain2);
8704
8705 session_deps_.proxy_delegate = std::make_unique<TestProxyDelegate>();
8706 auto* proxy_delegate =
8707 static_cast<TestProxyDelegate*>(session_deps_.proxy_delegate.get());
8708 proxy_delegate->set_proxy_chain(chain1);
8709
8710 HttpRequestInfo request;
8711 request.method = "GET";
8712 request.url = GURL("http://www.example.org/");
8713 request.traffic_annotation =
8714 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
8715
8716 session_deps_.proxy_resolution_service =
8717 ConfiguredProxyResolutionService::CreateFixedForTest(
8718 "https://not-used:70", TRAFFIC_ANNOTATION_FOR_TESTS);
8719 session_deps_.proxy_resolution_service->SetProxyDelegate(proxy_delegate);
8720 session_deps_.net_log = NetLog::Get();
8721 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
8722
8723 std::vector<SSLSocketDataProvider> ssl_socket_data_providers;
8724 std::vector<std::string> connects;
8725 // Allocate enough space in each of these so that the address of each entry
8726 // will not change after insertion.
8727 ssl_socket_data_providers.reserve(chain1.length() + chain2.length());
8728 connects.reserve(chain1.length() - 1 + chain2.length() - 1);
8729
8730 std::vector<MockWrite> data_writes1;
8731 std::vector<MockRead> data_reads1;
8732
8733 for (size_t proxy_index = 1; proxy_index < chain1.length(); ++proxy_index) {
8734 const auto& proxy_host_port_pair_string =
8735 chain1.GetProxyServer(proxy_index).host_port_pair().ToString();
8736 connects.push_back(
8737 base::StringPrintf("CONNECT %s HTTP/1.1\r\n"
8738 "Host: %s\r\n"
8739 "Proxy-Connection: keep-alive\r\n\r\n",
8740 proxy_host_port_pair_string.c_str(),
8741 proxy_host_port_pair_string.c_str()));
8742 data_writes1.emplace_back(connects.back().c_str());
8743 data_reads1.emplace_back("HTTP/1.1 200 Connection Established\r\n\r\n");
8744 }
8745
8746 if (chain1.is_multi_proxy()) {
8747 // Since this is a multi-proxy chain, CONNECT to the endpoint.
8748 data_writes1.emplace_back(
8749 "CONNECT www.example.org:80 HTTP/1.1\r\n"
8750 "Host: www.example.org:80\r\n"
8751 "Proxy-Connection: keep-alive\r\n\r\n");
8752 data_reads1.emplace_back("HTTP/1.1 200 Connection Established\r\n\r\n");
8753
8754 // Make the request to the endpoint.
8755 data_writes1.emplace_back(
8756 "GET / HTTP/1.1\r\n"
8757 "Host: www.example.org\r\n"
8758 "Connection: keep-alive\r\n\r\n");
8759 } else {
8760 // For a single-proxy chain, use GET.
8761 data_writes1.emplace_back(
8762 "GET http://www.example.org/ HTTP/1.1\r\n"
8763 "Host: www.example.org\r\n"
8764 "Proxy-Connection: keep-alive\r\n\r\n");
8765 }
8766
8767 data_reads1.emplace_back("HTTP/1.1 200 OK\r\n");
8768 data_reads1.emplace_back(SYNCHRONOUS, OK);
8769
8770 StaticSocketDataProvider data1(data_reads1, data_writes1);
8771 session_deps_.socket_factory->AddSocketDataProvider(&data1);
8772
8773 for (size_t proxy_index = 0; proxy_index < chain1.length(); ++proxy_index) {
8774 ssl_socket_data_providers.emplace_back(ASYNC, OK);
8775 session_deps_.socket_factory->AddSSLSocketDataProvider(
8776 &ssl_socket_data_providers.back());
8777 }
8778
8779 TestCompletionCallback callback1;
8780
8781 HttpNetworkTransaction trans1(DEFAULT_PRIORITY, session.get());
8782
8783 int rv = trans1.Start(&request, callback1.callback(),
8784 NetLogWithSource::Make(NetLogSourceType::NONE));
8785 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
8786
8787 rv = callback1.WaitForResult();
8788 EXPECT_THAT(rv, IsOk());
8789
8790 const HttpResponseInfo* response = trans1.GetResponseInfo();
8791 ASSERT_TRUE(response);
8792 EXPECT_EQ(200, response->headers->response_code());
8793 EXPECT_EQ(chain1, response->proxy_chain);
8794
8795 // Now use the second proxy chain. We expect that it will use a new
8796 // socket, so to test this we will create a new socket data provider and
8797 // expect that this gets used instead of the one created above for the
8798 // first transaction.
8799 proxy_delegate->set_proxy_chain(chain2);
8800
8801 std::vector<MockWrite> data_writes2;
8802 std::vector<MockRead> data_reads2;
8803
8804 for (size_t proxy_index = 1; proxy_index < chain2.length(); ++proxy_index) {
8805 const auto& proxy_host_port_pair_string =
8806 chain2.GetProxyServer(proxy_index).host_port_pair().ToString();
8807 connects.push_back(
8808 base::StringPrintf("CONNECT %s HTTP/1.1\r\n"
8809 "Host: %s\r\n"
8810 "Proxy-Connection: keep-alive\r\n\r\n",
8811 proxy_host_port_pair_string.c_str(),
8812 proxy_host_port_pair_string.c_str()));
8813 data_writes2.emplace_back(connects.back().c_str());
8814 data_reads2.emplace_back("HTTP/1.1 200 Connection Established\r\n\r\n");
8815 }
8816
8817 if (chain2.is_multi_proxy()) {
8818 // Since this is a multi-proxy chain, CONNECT to the endpoint.
8819 data_writes2.emplace_back(
8820 "CONNECT www.example.org:80 HTTP/1.1\r\n"
8821 "Host: www.example.org:80\r\n"
8822 "Proxy-Connection: keep-alive\r\n\r\n");
8823 data_reads2.emplace_back("HTTP/1.1 200 Connection Established\r\n\r\n");
8824
8825 // Make the request to the endpoint.
8826 data_writes2.emplace_back(
8827 "GET / HTTP/1.1\r\n"
8828 "Host: www.example.org\r\n"
8829 "Connection: keep-alive\r\n\r\n");
8830 } else {
8831 // For a single-proxy chain, use GET.
8832 data_writes2.emplace_back(
8833 "GET http://www.example.org/ HTTP/1.1\r\n"
8834 "Host: www.example.org\r\n"
8835 "Proxy-Connection: keep-alive\r\n\r\n");
8836 }
8837 data_reads2.emplace_back("HTTP/1.1 200 OK\r\n");
8838 data_reads2.emplace_back(SYNCHRONOUS, OK);
8839
8840 StaticSocketDataProvider data2(data_reads2, data_writes2);
8841 session_deps_.socket_factory->AddSocketDataProvider(&data2);
8842
8843 for (size_t proxy_index = 0; proxy_index < chain2.length(); ++proxy_index) {
8844 ssl_socket_data_providers.emplace_back(ASYNC, OK);
8845 session_deps_.socket_factory->AddSSLSocketDataProvider(
8846 &ssl_socket_data_providers.back());
8847 }
8848
8849 TestCompletionCallback callback2;
8850 HttpNetworkTransaction trans2(DEFAULT_PRIORITY, session.get());
8851
8852 rv = trans2.Start(&request, callback2.callback(),
8853 NetLogWithSource::Make(NetLogSourceType::NONE));
8854 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
8855
8856 rv = callback2.WaitForResult();
8857 EXPECT_THAT(rv, IsOk());
8858
8859 response = trans2.GetResponseInfo();
8860 ASSERT_TRUE(response);
8861 EXPECT_EQ(200, response->headers->response_code());
8862 EXPECT_EQ(chain2, response->proxy_chain);
8863
8864 EXPECT_TRUE(data1.AllReadDataConsumed());
8865 EXPECT_TRUE(data1.AllWriteDataConsumed());
8866 EXPECT_TRUE(data2.AllReadDataConsumed());
8867 EXPECT_TRUE(data2.AllWriteDataConsumed());
8868 }
8869
8870 // If we have established a proxy tunnel through a two hop proxy and then
8871 // establish a tunnel through only the first hop, ensure that socket re-use does
8872 // not occur (HTTPS A -> HTTPS B != HTTPS A).
TEST_P(HttpNetworkTransactionTest,HttpsNestedProxyNoSocketReuseFirstHop)8873 TEST_P(HttpNetworkTransactionTest, HttpsNestedProxyNoSocketReuseFirstHop) {
8874 const ProxyServer kProxyServer1{ProxyServer::SCHEME_HTTPS,
8875 HostPortPair("proxy1.test", 70)};
8876 const ProxyServer kProxyServer2{ProxyServer::SCHEME_HTTPS,
8877 HostPortPair("proxy2.test", 71)};
8878 const ProxyChain kNestedProxyChain{{kProxyServer1, kProxyServer2}};
8879
8880 const ProxyChain kFirstHopOnlyChain{{kProxyServer1}};
8881 HttpsNestedProxyNoSocketReuseHelper(kNestedProxyChain, kFirstHopOnlyChain);
8882 }
8883
8884 // If we have established a proxy tunnel through a two hop proxy and then
8885 // establish a tunnel through only the second hop, ensure that socket re-use
8886 // does not occur (HTTPS A -> HTTPS B != HTTPS B).
TEST_P(HttpNetworkTransactionTest,HttpsNestedProxyNoSocketReuseSecondHop)8887 TEST_P(HttpNetworkTransactionTest, HttpsNestedProxyNoSocketReuseSecondHop) {
8888 const ProxyServer kProxyServer1{ProxyServer::SCHEME_HTTPS,
8889 HostPortPair("proxy1.test", 70)};
8890 const ProxyServer kProxyServer2{ProxyServer::SCHEME_HTTPS,
8891 HostPortPair("proxy2.test", 71)};
8892 const ProxyChain kNestedProxyChain{{kProxyServer1, kProxyServer2}};
8893
8894 const ProxyChain kSecondHopOnlyChain{{kProxyServer2}};
8895
8896 HttpsNestedProxyNoSocketReuseHelper(kNestedProxyChain, kSecondHopOnlyChain);
8897 }
8898
8899 // If we have established a proxy tunnel through a two hop proxy and then
8900 // establish a tunnel through the same proxies with the order reversed, ensure
8901 // that socket re-use does not occur (HTTPS A -> HTTPS B != HTTPS B -> HTTPS A).
TEST_P(HttpNetworkTransactionTest,HttpsNestedProxyNoSocketReuseReversedChain)8902 TEST_P(HttpNetworkTransactionTest, HttpsNestedProxyNoSocketReuseReversedChain) {
8903 const ProxyServer kProxyServer1{ProxyServer::SCHEME_HTTPS,
8904 HostPortPair("proxy1.test", 70)};
8905 const ProxyServer kProxyServer2{ProxyServer::SCHEME_HTTPS,
8906 HostPortPair("proxy2.test", 71)};
8907 const ProxyChain kNestedProxyChain{{kProxyServer1, kProxyServer2}};
8908
8909 const ProxyChain kReversedChain{{kProxyServer2, kProxyServer1}};
8910
8911 HttpsNestedProxyNoSocketReuseHelper(kNestedProxyChain, kReversedChain);
8912 }
8913
8914 // If we have established a proxy tunnel through a two hop proxy using SPDY,
8915 // ensure that socket reuse occurs as expected. Specifically, for:
8916 // (SPDY A -> SPDY B -> HTTPS Endpoint),
8917 // (SPDY A -> HTTPS Endpoint) should send the endpoint CONNECT to
8918 // the existing SPDY A socket but for:
8919 // (SPDY B -> HTTPS Endpoint), the SPDY A -> SPDY B socket should not be used.
TEST_P(HttpNetworkTransactionTest,HttpsNestedProxySpdySocketReuseDifferentChains)8920 TEST_P(HttpNetworkTransactionTest,
8921 HttpsNestedProxySpdySocketReuseDifferentChains) {
8922 HttpRequestInfo request;
8923 request.method = "GET";
8924 request.url = GURL("https://www.example.org/");
8925 request.traffic_annotation =
8926 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
8927
8928 // Configure a nested proxy.
8929 const ProxyServer kProxyServer1{ProxyServer::SCHEME_HTTPS,
8930 HostPortPair("proxy1.test", 70)};
8931 const ProxyServer kProxyServer2{ProxyServer::SCHEME_HTTPS,
8932 HostPortPair("proxy2.test", 71)};
8933 const ProxyChain kNestedProxyChain{{kProxyServer1, kProxyServer2}};
8934 const ProxyChain kFirstHopOnlyChain{{kProxyServer1}};
8935 const ProxyChain kSecondHopOnlyChain{{kProxyServer1}};
8936
8937 session_deps_.proxy_delegate = std::make_unique<TestProxyDelegate>();
8938 auto* proxy_delegate =
8939 static_cast<TestProxyDelegate*>(session_deps_.proxy_delegate.get());
8940 proxy_delegate->set_proxy_chain(kNestedProxyChain);
8941
8942 session_deps_.proxy_resolution_service =
8943 ConfiguredProxyResolutionService::CreateFixedForTest(
8944 "https://not-used:70", TRAFFIC_ANNOTATION_FOR_TESTS);
8945 session_deps_.proxy_resolution_service->SetProxyDelegate(proxy_delegate);
8946
8947 session_deps_.net_log = NetLog::Get();
8948 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
8949
8950 // CONNECT to proxy2.test:71 via SPDY.
8951 spdy::SpdySerializedFrame proxy2_connect(spdy_util_.ConstructSpdyConnect(
8952 nullptr, 0, 1, HttpProxyConnectJob::kH2QuicTunnelPriority,
8953 kProxyServer2.host_port_pair()));
8954
8955 spdy::SpdySerializedFrame proxy2_connect_resp(
8956 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
8957
8958 // CONNECT to www.example.org:443 via SPDY.
8959 // Need to use a new `SpdyTestUtil()` so that the stream parent ID of this
8960 // CONNECT is calculated correctly.
8961 SpdyTestUtil new_spdy_util;
8962 spdy::SpdySerializedFrame endpoint_connect(new_spdy_util.ConstructSpdyConnect(
8963 nullptr, 0, 1, HttpProxyConnectJob::kH2QuicTunnelPriority,
8964 HostPortPair("www.example.org", 443)));
8965
8966 // Since this request and response are sent over the tunnel established
8967 // previously, from a socket-perspective these need to be wrapped as data
8968 // frames.
8969 spdy::SpdySerializedFrame wrapped_endpoint_connect(
8970 spdy_util_.ConstructWrappedSpdyFrame(endpoint_connect, 1));
8971
8972 spdy::SpdySerializedFrame endpoint_connect_resp(
8973 new_spdy_util.ConstructSpdyGetReply(nullptr, 0, 1));
8974 spdy::SpdySerializedFrame wrapped_endpoint_connect_resp(
8975 spdy_util_.ConstructWrappedSpdyFrame(endpoint_connect_resp, 1));
8976
8977 // fetch https://www.example.org/ via HTTP.
8978 // Since this request will go over two tunnels, it needs to be double-wrapped.
8979 const char kGet[] =
8980 "GET / HTTP/1.1\r\n"
8981 "Host: www.example.org\r\n"
8982 "Connection: keep-alive\r\n\r\n";
8983 spdy::SpdySerializedFrame wrapped_get(
8984 new_spdy_util.ConstructSpdyDataFrame(1, kGet, false));
8985 spdy::SpdySerializedFrame wrapped_wrapped_get(
8986 spdy_util_.ConstructWrappedSpdyFrame(wrapped_get, 1));
8987
8988 const char kResp[] =
8989 "HTTP/1.1 200 OK\r\n"
8990 "Content-Length: 10\r\n\r\n";
8991 spdy::SpdySerializedFrame wrapped_get_resp(
8992 new_spdy_util.ConstructSpdyDataFrame(1, kResp, false));
8993 spdy::SpdySerializedFrame wrapped_wrapped_get_resp(
8994 spdy_util_.ConstructWrappedSpdyFrame(wrapped_get_resp, 1));
8995
8996 const char kTrans1RespData[] = "1234567890";
8997 spdy::SpdySerializedFrame wrapped_body(
8998 new_spdy_util.ConstructSpdyDataFrame(1, kTrans1RespData, false));
8999 spdy::SpdySerializedFrame wrapped_wrapped_body(
9000 spdy_util_.ConstructWrappedSpdyFrame(wrapped_body, 1));
9001
9002 const char kTrans2RespData[] = "abcdefghij";
9003 spdy::SpdySerializedFrame second_trans_endpoint_connect(
9004 spdy_util_.ConstructSpdyConnect(
9005 nullptr, 0, 3, HttpProxyConnectJob::kH2QuicTunnelPriority,
9006 HostPortPair("www.example.org", 443)));
9007 spdy::SpdySerializedFrame second_trans_endpoint_connect_resp(
9008 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 3));
9009 spdy::SpdySerializedFrame second_trans_wrapped_get(
9010 new_spdy_util.ConstructSpdyDataFrame(3, kGet, false));
9011 spdy::SpdySerializedFrame second_trans_wrapped_get_resp(
9012 new_spdy_util.ConstructSpdyDataFrame(3, kResp, false));
9013 spdy::SpdySerializedFrame second_trans_wrapped_body(
9014 new_spdy_util.ConstructSpdyDataFrame(3, kTrans2RespData, false));
9015
9016 MockWrite spdy_writes1[] = {
9017 CreateMockWrite(proxy2_connect, 0),
9018 CreateMockWrite(wrapped_endpoint_connect, 2),
9019 CreateMockWrite(wrapped_wrapped_get, 5),
9020 // For the second transaction, we expect the endpoint connect on this
9021 // socket.
9022 CreateMockWrite(second_trans_endpoint_connect, 8),
9023 CreateMockWrite(second_trans_wrapped_get, 10),
9024
9025 };
9026
9027 MockRead spdy_reads1[] = {
9028 CreateMockRead(proxy2_connect_resp, 1, ASYNC),
9029 // TODO(https://crbug.com/497228): We have to manually delay this read so
9030 // that the higher-level SPDY stream doesn't get notified of an available
9031 // read before the write it initiated (the second CONNECT) finishes,
9032 // triggering a DCHECK.
9033 MockRead(ASYNC, ERR_IO_PENDING, 3),
9034 CreateMockRead(wrapped_endpoint_connect_resp, 4, ASYNC),
9035 CreateMockRead(wrapped_wrapped_get_resp, 6, ASYNC),
9036 CreateMockRead(wrapped_wrapped_body, 7, ASYNC),
9037 CreateMockRead(second_trans_endpoint_connect_resp, 9),
9038 CreateMockRead(second_trans_wrapped_get_resp, 11, ASYNC),
9039 CreateMockRead(second_trans_wrapped_body, 12, ASYNC),
9040 MockRead(ASYNC, 0, 13),
9041 };
9042
9043 SequencedSocketData spdy_data1(spdy_reads1, spdy_writes1);
9044 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data1);
9045
9046 SSLSocketDataProvider ssl(ASYNC, OK);
9047 ssl.next_proto = kProtoHTTP2;
9048 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
9049 SSLSocketDataProvider ssl2(ASYNC, OK);
9050 ssl2.next_proto = kProtoHTTP2;
9051 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
9052 SSLSocketDataProvider ssl3(ASYNC, OK);
9053 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl3);
9054
9055 TestCompletionCallback callback1;
9056 HttpNetworkTransaction trans1(DEFAULT_PRIORITY, session.get());
9057
9058 int rv = trans1.Start(&request, callback1.callback(),
9059 NetLogWithSource::Make(NetLogSourceType::NONE));
9060 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
9061
9062 spdy_data1.RunUntilPaused();
9063 base::RunLoop().RunUntilIdle();
9064 spdy_data1.Resume();
9065
9066 rv = callback1.WaitForResult();
9067 ASSERT_THAT(rv, IsOk());
9068
9069 const HttpResponseInfo* response = trans1.GetResponseInfo();
9070 ASSERT_TRUE(response);
9071 ASSERT_TRUE(response->headers);
9072 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
9073 EXPECT_EQ(kNestedProxyChain, response->proxy_chain);
9074
9075 std::string response_data;
9076 ASSERT_THAT(ReadTransaction(&trans1, &response_data), IsOk());
9077 EXPECT_EQ(kTrans1RespData, response_data);
9078
9079 // Now use a proxy chain consisting of only the first proxy. We expect that it
9080 // will re-use the existing socket to the proxy, so we will look for the reads
9081 // and writes associated with this in the same SocketDataProvider used by the
9082 // first transaction.
9083 proxy_delegate->set_proxy_chain(kFirstHopOnlyChain);
9084
9085 SSLSocketDataProvider ssl4(ASYNC, OK);
9086 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl4);
9087
9088 TestCompletionCallback callback2;
9089 HttpNetworkTransaction trans2(DEFAULT_PRIORITY, session.get());
9090
9091 rv = trans2.Start(&request, callback2.callback(),
9092 NetLogWithSource::Make(NetLogSourceType::NONE));
9093 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
9094
9095 rv = callback2.WaitForResult();
9096 ASSERT_THAT(rv, IsOk());
9097
9098 response = trans2.GetResponseInfo();
9099 ASSERT_TRUE(response);
9100 ASSERT_TRUE(response->headers);
9101 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
9102 EXPECT_EQ(kFirstHopOnlyChain, response->proxy_chain);
9103
9104 ASSERT_THAT(ReadTransaction(&trans2, &response_data), IsOk());
9105 EXPECT_EQ(kTrans2RespData, response_data);
9106
9107 // Now use a proxy chain consisting of only the second proxy. We expect that
9108 // it will not re-use the existing socket to the first proxy, so we will look
9109 // for the reads and writes associated with this in a new SocketDataProvider.
9110 proxy_delegate->set_proxy_chain(kSecondHopOnlyChain);
9111
9112 // CONNECT to www.example.org:443 via SPDY.
9113 SpdyTestUtil third_spdy_util;
9114 spdy::SpdySerializedFrame third_trans_endpoint_connect(
9115 third_spdy_util.ConstructSpdyConnect(
9116 nullptr, 0, 1, HttpProxyConnectJob::kH2QuicTunnelPriority,
9117 HostPortPair("www.example.org", 443)));
9118
9119 spdy::SpdySerializedFrame third_trans_endpoint_connect_resp(
9120 third_spdy_util.ConstructSpdyGetReply(nullptr, 0, 1));
9121
9122 // fetch https://www.example.org/ via HTTP.
9123 spdy::SpdySerializedFrame third_trans_wrapped_get(
9124 third_spdy_util.ConstructSpdyDataFrame(1, kGet, false));
9125
9126 spdy::SpdySerializedFrame third_trans_wrapped_get_resp(
9127 third_spdy_util.ConstructSpdyDataFrame(1, kResp, false));
9128
9129 const char kTrans3RespData[] = "!@#$%^&*()";
9130 spdy::SpdySerializedFrame third_trans_wrapped_body(
9131 third_spdy_util.ConstructSpdyDataFrame(1, kTrans3RespData, false));
9132
9133 MockWrite spdy_writes2[] = {
9134 CreateMockWrite(third_trans_endpoint_connect, 0),
9135 CreateMockWrite(third_trans_wrapped_get, 2),
9136 };
9137
9138 MockRead spdy_reads2[] = {
9139 CreateMockRead(third_trans_endpoint_connect_resp, 1, ASYNC),
9140 CreateMockRead(third_trans_wrapped_get_resp, 3, ASYNC),
9141 CreateMockRead(third_trans_wrapped_body, 4, ASYNC),
9142 MockRead(ASYNC, 0, 5),
9143 };
9144
9145 SequencedSocketData spdy_data2(spdy_reads2, spdy_writes2);
9146 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data2);
9147
9148 SSLSocketDataProvider ssl5(ASYNC, OK);
9149 ssl5.next_proto = kProtoHTTP2;
9150 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl5);
9151
9152 SSLSocketDataProvider ssl6(ASYNC, OK);
9153 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl6);
9154
9155 TestCompletionCallback callback3;
9156 HttpNetworkTransaction trans3(DEFAULT_PRIORITY, session.get());
9157
9158 rv = trans3.Start(&request, callback3.callback(),
9159 NetLogWithSource::Make(NetLogSourceType::NONE));
9160 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
9161
9162 rv = callback3.WaitForResult();
9163 ASSERT_THAT(rv, IsOk());
9164
9165 response = trans3.GetResponseInfo();
9166 ASSERT_TRUE(response);
9167 ASSERT_TRUE(response->headers);
9168 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
9169 EXPECT_EQ(kFirstHopOnlyChain, response->proxy_chain);
9170
9171 ASSERT_THAT(ReadTransaction(&trans3, &response_data), IsOk());
9172 EXPECT_EQ(kTrans3RespData, response_data);
9173
9174 EXPECT_EQ(proxy_delegate->on_before_tunnel_request_call_count(), 4u);
9175
9176 EXPECT_TRUE(spdy_data1.AllReadDataConsumed());
9177 EXPECT_TRUE(spdy_data1.AllWriteDataConsumed());
9178 EXPECT_TRUE(spdy_data2.AllReadDataConsumed());
9179 EXPECT_TRUE(spdy_data2.AllWriteDataConsumed());
9180 }
9181
9182 // If we have established a proxy tunnel through a two-hop proxy using SPDY,
9183 // ensure that socket reuse occurs as expected for two different requests (test
9184 // that there is only one CONNECT for the second proxy in the chain).
TEST_P(HttpNetworkTransactionTest,HttpsNestedProxySpdySocketReuseDifferentRequests)9185 TEST_P(HttpNetworkTransactionTest,
9186 HttpsNestedProxySpdySocketReuseDifferentRequests) {
9187 HttpRequestInfo request1;
9188 request1.method = "GET";
9189 request1.url = GURL("https://www.example.org/");
9190 request1.traffic_annotation =
9191 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
9192
9193 const ProxyServer kProxyServer1{ProxyServer::SCHEME_HTTPS,
9194 HostPortPair("proxy1.test", 70)};
9195 const ProxyServer kProxyServer2{ProxyServer::SCHEME_HTTPS,
9196 HostPortPair("proxy2.test", 71)};
9197 const ProxyChain kNestedProxyChain{{kProxyServer1, kProxyServer2}};
9198
9199 session_deps_.proxy_delegate = std::make_unique<TestProxyDelegate>();
9200 auto* proxy_delegate =
9201 static_cast<TestProxyDelegate*>(session_deps_.proxy_delegate.get());
9202 proxy_delegate->set_proxy_chain(kNestedProxyChain);
9203
9204 session_deps_.proxy_resolution_service =
9205 ConfiguredProxyResolutionService::CreateFixedForTest(
9206 "https://not-used:70", TRAFFIC_ANNOTATION_FOR_TESTS);
9207 session_deps_.proxy_resolution_service->SetProxyDelegate(proxy_delegate);
9208
9209 session_deps_.net_log = NetLog::Get();
9210 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
9211
9212 // CONNECT to proxy2.test:71 via SPDY.
9213 spdy::SpdySerializedFrame proxy2_connect(spdy_util_.ConstructSpdyConnect(
9214 nullptr, 0, 1, HttpProxyConnectJob::kH2QuicTunnelPriority,
9215 kProxyServer2.host_port_pair()));
9216
9217 spdy::SpdySerializedFrame proxy2_connect_resp(
9218 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
9219
9220 // CONNECT to www.example.org:443 via SPDY.
9221 // Need to use a new `SpdyTestUtil()` so that the stream parent ID of this
9222 // CONNECT is calculated correctly.
9223 SpdyTestUtil new_spdy_util;
9224 spdy::SpdySerializedFrame endpoint_connect(new_spdy_util.ConstructSpdyConnect(
9225 nullptr, 0, 1, HttpProxyConnectJob::kH2QuicTunnelPriority,
9226 HostPortPair("www.example.org", 443)));
9227
9228 // Since the first request and response are sent over the tunnel established
9229 // previously, from a socket-perspective these need to be wrapped as data
9230 // frames.
9231 spdy::SpdySerializedFrame wrapped_endpoint_connect(
9232 spdy_util_.ConstructWrappedSpdyFrame(endpoint_connect, 1));
9233
9234 spdy::SpdySerializedFrame endpoint_connect_resp(
9235 new_spdy_util.ConstructSpdyGetReply(nullptr, 0, 1));
9236 spdy::SpdySerializedFrame wrapped_endpoint_connect_resp(
9237 spdy_util_.ConstructWrappedSpdyFrame(endpoint_connect_resp, 1));
9238
9239 // fetch https://www.example.org/ via HTTP.
9240 // Since the first request will go over two tunnels, it needs to be
9241 // double-wrapped.
9242 const char kGet1[] =
9243 "GET / HTTP/1.1\r\n"
9244 "Host: www.example.org\r\n"
9245 "Connection: keep-alive\r\n\r\n";
9246 spdy::SpdySerializedFrame wrapped_get(
9247 new_spdy_util.ConstructSpdyDataFrame(1, kGet1, false));
9248 spdy::SpdySerializedFrame wrapped_wrapped_get(
9249 spdy_util_.ConstructWrappedSpdyFrame(wrapped_get, 1));
9250
9251 const char kResp[] =
9252 "HTTP/1.1 200 OK\r\n"
9253 "Content-Length: 10\r\n\r\n";
9254 spdy::SpdySerializedFrame wrapped_get_resp(
9255 new_spdy_util.ConstructSpdyDataFrame(1, kResp, false));
9256 spdy::SpdySerializedFrame wrapped_wrapped_get_resp(
9257 spdy_util_.ConstructWrappedSpdyFrame(wrapped_get_resp, 1));
9258
9259 const char kTrans1RespData[] = "1234567890";
9260 spdy::SpdySerializedFrame wrapped_body(
9261 new_spdy_util.ConstructSpdyDataFrame(1, kTrans1RespData, false));
9262 spdy::SpdySerializedFrame wrapped_wrapped_body(
9263 spdy_util_.ConstructWrappedSpdyFrame(wrapped_body, 1));
9264
9265 // CONNECT to www.example.com:443 via SPDY.
9266 spdy::SpdySerializedFrame second_trans_endpoint_connect(
9267 new_spdy_util.ConstructSpdyConnect(
9268 nullptr, 0, 3, HttpProxyConnectJob::kH2QuicTunnelPriority,
9269 HostPortPair("www.example.com", 443)));
9270 spdy::SpdySerializedFrame second_trans_wrapped_endpoint_connect(
9271 spdy_util_.ConstructWrappedSpdyFrame(second_trans_endpoint_connect, 1));
9272
9273 spdy::SpdySerializedFrame second_trans_endpoint_connect_resp(
9274 new_spdy_util.ConstructSpdyGetReply(nullptr, 0, 3));
9275 spdy::SpdySerializedFrame second_trans_wrapped_endpoint_connect_resp(
9276 spdy_util_.ConstructWrappedSpdyFrame(second_trans_endpoint_connect_resp,
9277 1));
9278
9279 // fetch https://www.example.com/2 via HTTP.
9280 const char kGet2[] =
9281 "GET /2 HTTP/1.1\r\n"
9282 "Host: www.example.com\r\n"
9283 "Connection: keep-alive\r\n\r\n";
9284 SpdyTestUtil second_trans_spdy_util;
9285 spdy::SpdySerializedFrame second_trans_wrapped_get(
9286 second_trans_spdy_util.ConstructSpdyDataFrame(3, kGet2, false));
9287 spdy::SpdySerializedFrame second_trans_wrapped_wrapped_get(
9288 spdy_util_.ConstructWrappedSpdyFrame(second_trans_wrapped_get, 1));
9289
9290 spdy::SpdySerializedFrame second_trans_wrapped_get_resp(
9291 second_trans_spdy_util.ConstructSpdyDataFrame(3, kResp, false));
9292 spdy::SpdySerializedFrame second_trans_wrapped_wrapped_get_resp(
9293 spdy_util_.ConstructWrappedSpdyFrame(second_trans_wrapped_get_resp, 1));
9294
9295 const char kTrans2RespData[] = "abcdefghij";
9296 spdy::SpdySerializedFrame second_trans_wrapped_body(
9297 second_trans_spdy_util.ConstructSpdyDataFrame(3, kTrans2RespData, false));
9298 spdy::SpdySerializedFrame second_trans_wrapped_wrapped_body(
9299 spdy_util_.ConstructWrappedSpdyFrame(second_trans_wrapped_body, 1));
9300
9301 MockWrite spdy_writes1[] = {
9302 CreateMockWrite(proxy2_connect, 0),
9303 CreateMockWrite(wrapped_endpoint_connect, 2),
9304 CreateMockWrite(wrapped_wrapped_get, 5),
9305 // For the second transaction, we expect the endpoint connect on this
9306 // socket with no duplicated proxy2 CONNECT.
9307 CreateMockWrite(second_trans_wrapped_endpoint_connect, 8),
9308 CreateMockWrite(second_trans_wrapped_wrapped_get, 11),
9309 };
9310
9311 MockRead spdy_reads1[] = {
9312 CreateMockRead(proxy2_connect_resp, 1, ASYNC),
9313 // TODO(https://crbug.com/497228): We have to manually delay this read so
9314 // that the higher-level SPDY stream doesn't get notified of an available
9315 // read before the write it initiated (the second CONNECT) finishes,
9316 // triggering a DCHECK.
9317 MockRead(ASYNC, ERR_IO_PENDING, 3),
9318 CreateMockRead(wrapped_endpoint_connect_resp, 4, ASYNC),
9319 CreateMockRead(wrapped_wrapped_get_resp, 6, ASYNC),
9320 CreateMockRead(wrapped_wrapped_body, 7, ASYNC),
9321 // TODO(https://crbug.com/497228): We have to manually delay this read so
9322 // that the higher-level SPDY stream doesn't get notified of an available
9323 // read before the write it initiated (the second CONNECT) finishes,
9324 // triggering a DCHECK.
9325 MockRead(ASYNC, ERR_IO_PENDING, 9),
9326 CreateMockRead(second_trans_wrapped_endpoint_connect_resp, 10),
9327 CreateMockRead(second_trans_wrapped_wrapped_get_resp, 12),
9328 CreateMockRead(second_trans_wrapped_wrapped_body, 13),
9329 MockRead(ASYNC, 0, 14),
9330 };
9331
9332 SequencedSocketData spdy_data1(spdy_reads1, spdy_writes1);
9333 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data1);
9334
9335 SSLSocketDataProvider ssl(ASYNC, OK);
9336 ssl.next_proto = kProtoHTTP2;
9337 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
9338 SSLSocketDataProvider ssl2(ASYNC, OK);
9339 ssl2.next_proto = kProtoHTTP2;
9340 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
9341 SSLSocketDataProvider ssl3(ASYNC, OK);
9342 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl3);
9343
9344 TestCompletionCallback callback1;
9345 HttpNetworkTransaction trans1(DEFAULT_PRIORITY, session.get());
9346
9347 int rv = trans1.Start(&request1, callback1.callback(),
9348 NetLogWithSource::Make(NetLogSourceType::NONE));
9349 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
9350
9351 spdy_data1.RunUntilPaused();
9352 base::RunLoop().RunUntilIdle();
9353 spdy_data1.Resume();
9354
9355 rv = callback1.WaitForResult();
9356 ASSERT_THAT(rv, IsOk());
9357
9358 const HttpResponseInfo* response = trans1.GetResponseInfo();
9359 ASSERT_TRUE(response);
9360 ASSERT_TRUE(response->headers);
9361 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
9362 EXPECT_EQ(kNestedProxyChain, response->proxy_chain);
9363
9364 std::string response_data;
9365 ASSERT_THAT(ReadTransaction(&trans1, &response_data), IsOk());
9366 EXPECT_EQ(kTrans1RespData, response_data);
9367
9368 HttpRequestInfo request2;
9369 request2.method = "GET";
9370 request2.url = GURL("https://www.example.com/2");
9371 request2.traffic_annotation =
9372 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
9373
9374 SSLSocketDataProvider ssl4(ASYNC, OK);
9375 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl4);
9376
9377 TestCompletionCallback callback2;
9378 HttpNetworkTransaction trans2(DEFAULT_PRIORITY, session.get());
9379
9380 rv = trans2.Start(&request2, callback2.callback(),
9381 NetLogWithSource::Make(NetLogSourceType::NONE));
9382 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
9383
9384 spdy_data1.RunUntilPaused();
9385 base::RunLoop().RunUntilIdle();
9386 spdy_data1.Resume();
9387
9388 rv = callback2.WaitForResult();
9389 ASSERT_THAT(rv, IsOk());
9390
9391 response = trans2.GetResponseInfo();
9392 ASSERT_TRUE(response);
9393 ASSERT_TRUE(response->headers);
9394 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
9395 EXPECT_EQ(kNestedProxyChain, response->proxy_chain);
9396
9397 ASSERT_THAT(ReadTransaction(&trans2, &response_data), IsOk());
9398 EXPECT_EQ(kTrans2RespData, response_data);
9399 }
9400
9401 // Ensure that socket reuse occurs after an error from a SPDY connection through
9402 // the nested proxy.
TEST_P(HttpNetworkTransactionTest,HttpsNestedProxySpdySocketReuseAfterError)9403 TEST_P(HttpNetworkTransactionTest, HttpsNestedProxySpdySocketReuseAfterError) {
9404 const ProxyServer kProxyServer1{ProxyServer::SCHEME_HTTPS,
9405 HostPortPair("proxy1.test", 70)};
9406 const ProxyServer kProxyServer2{ProxyServer::SCHEME_HTTPS,
9407 HostPortPair("proxy2.test", 71)};
9408 const ProxyChain kNestedProxyChain{{kProxyServer1, kProxyServer2}};
9409
9410 ProxyList proxy_list;
9411 proxy_list.AddProxyChain(kNestedProxyChain);
9412 ProxyConfig proxy_config = ProxyConfig::CreateForTesting(proxy_list);
9413
9414 session_deps_.proxy_resolution_service =
9415 ConfiguredProxyResolutionService::CreateFixedForTest(
9416 ProxyConfigWithAnnotation(proxy_config,
9417 TRAFFIC_ANNOTATION_FOR_TESTS));
9418 session_deps_.net_log = NetLog::Get();
9419 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
9420
9421 // CONNECT to proxy2.test:71 via SPDY.
9422 spdy::SpdySerializedFrame proxy2_connect(spdy_util_.ConstructSpdyConnect(
9423 nullptr, 0, 1, HttpProxyConnectJob::kH2QuicTunnelPriority,
9424 kProxyServer2.host_port_pair()));
9425
9426 spdy::SpdySerializedFrame proxy2_connect_resp(
9427 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
9428
9429 // CONNECT to www.example.org:443 via SPDY.
9430 // Need to use a new `SpdyTestUtil()` so that the stream parent ID of this
9431 // CONNECT is calculated correctly.
9432 SpdyTestUtil new_spdy_util;
9433 spdy::SpdySerializedFrame endpoint_connect(new_spdy_util.ConstructSpdyConnect(
9434 nullptr, 0, 1, HttpProxyConnectJob::kH2QuicTunnelPriority,
9435 HostPortPair("www.example.org", 443)));
9436
9437 // Since this request and response are sent over the tunnel established
9438 // previously, from a socket-perspective these need to be wrapped as data
9439 // frames.
9440 spdy::SpdySerializedFrame wrapped_endpoint_connect(
9441 spdy_util_.ConstructWrappedSpdyFrame(endpoint_connect, 1));
9442
9443 spdy::SpdySerializedFrame endpoint_connect_resp(
9444 new_spdy_util.ConstructSpdyGetReply(nullptr, 0, 1));
9445 spdy::SpdySerializedFrame wrapped_endpoint_connect_resp(
9446 spdy_util_.ConstructWrappedSpdyFrame(endpoint_connect_resp, 1));
9447
9448 spdy::SpdySerializedFrame rst(
9449 new_spdy_util.ConstructSpdyRstStream(1, spdy::ERROR_CODE_CANCEL));
9450 spdy::SpdySerializedFrame wrapped_rst(
9451 spdy_util_.ConstructWrappedSpdyFrame(rst, 1));
9452
9453 new_spdy_util.UpdateWithStreamDestruction(1);
9454 spdy::SpdySerializedFrame attempt2_endpoint_connect(
9455 new_spdy_util.ConstructSpdyConnect(
9456 nullptr, 0, 3, HttpProxyConnectJob::kH2QuicTunnelPriority,
9457 HostPortPair("www.example.org", 443)));
9458 spdy::SpdySerializedFrame attempt2_wrapped_endpoint_connect(
9459 spdy_util_.ConstructWrappedSpdyFrame(attempt2_endpoint_connect, 1));
9460
9461 spdy::SpdySerializedFrame attempt2_endpoint_connect_resp(
9462 new_spdy_util.ConstructSpdyGetReply(nullptr, 0, 3));
9463 spdy::SpdySerializedFrame attempt2_wrapped_endpoint_connect_resp(
9464 spdy_util_.ConstructWrappedSpdyFrame(attempt2_endpoint_connect_resp, 1));
9465
9466 // fetch https://www.example.org/ via HTTPS.
9467 // Since this request will go over two tunnels, it needs to be double-wrapped.
9468 const char kGet[] =
9469 "GET / HTTP/1.1\r\n"
9470 "Host: www.example.org\r\n"
9471 "Connection: keep-alive\r\n\r\n";
9472 SpdyTestUtil attempt2_spdy_util(/*use_priority_header=*/true);
9473 spdy::SpdySerializedFrame attempt2_wrapped_get(
9474 attempt2_spdy_util.ConstructSpdyDataFrame(3, kGet, false));
9475 spdy::SpdySerializedFrame attempt2_wrapped_wrapped_get(
9476 spdy_util_.ConstructWrappedSpdyFrame(attempt2_wrapped_get, 1));
9477
9478 const char kResp[] =
9479 "HTTP/1.1 200 OK\r\n"
9480 "Content-Length: 10\r\n\r\n";
9481 spdy::SpdySerializedFrame attempt2_wrapped_get_resp(
9482 attempt2_spdy_util.ConstructSpdyDataFrame(3, kResp, false));
9483 spdy::SpdySerializedFrame attempt2_wrapped_wrapped_get_resp(
9484 spdy_util_.ConstructWrappedSpdyFrame(attempt2_wrapped_get_resp, 1));
9485
9486 const char kRespData[] = "1234567890";
9487 spdy::SpdySerializedFrame attempt2_wrapped_body(
9488 attempt2_spdy_util.ConstructSpdyDataFrame(3, kRespData, false));
9489 spdy::SpdySerializedFrame attempt2_wrapped_wrapped_body(
9490 spdy_util_.ConstructWrappedSpdyFrame(attempt2_wrapped_body, 1));
9491
9492 MockWrite spdy_writes[] = {
9493 CreateMockWrite(proxy2_connect, 0),
9494 CreateMockWrite(wrapped_endpoint_connect, 2),
9495 CreateMockWrite(wrapped_rst, 5),
9496 CreateMockWrite(attempt2_wrapped_endpoint_connect, 6),
9497 CreateMockWrite(attempt2_wrapped_wrapped_get, 9),
9498 };
9499
9500 MockRead spdy_reads[] = {
9501 CreateMockRead(proxy2_connect_resp, 1, ASYNC),
9502 // TODO(https://crbug.com/497228): We have to manually delay this read so
9503 // that the higher-level SPDY stream doesn't get notified of an available
9504 // read before the write it initiated (the second CONNECT) finishes,
9505 // triggering a DCHECK.
9506 MockRead(ASYNC, ERR_IO_PENDING, 3),
9507 CreateMockRead(wrapped_endpoint_connect_resp, 4, ASYNC),
9508 // The SSL socket error should occur here.
9509 MockRead(ASYNC, ERR_IO_PENDING, 7),
9510 CreateMockRead(attempt2_wrapped_endpoint_connect_resp, 8, ASYNC),
9511 CreateMockRead(attempt2_wrapped_wrapped_get_resp, 10, ASYNC),
9512 CreateMockRead(attempt2_wrapped_wrapped_body, 11, ASYNC),
9513 MockRead(ASYNC, 0, 12),
9514 };
9515
9516 SequencedSocketData spdy_data(spdy_reads, spdy_writes);
9517 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
9518
9519 SSLSocketDataProvider ssl(ASYNC, OK);
9520 ssl.next_proto = kProtoHTTP2;
9521 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
9522
9523 SSLSocketDataProvider ssl2(ASYNC, OK);
9524 ssl2.next_proto = kProtoHTTP2;
9525 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
9526
9527 auto cert_request_info_proxy = base::MakeRefCounted<SSLCertRequestInfo>();
9528 cert_request_info_proxy->host_and_port = kProxyServer1.host_port_pair();
9529
9530 SSLSocketDataProvider ssl3(ASYNC, ERR_SSL_CLIENT_AUTH_CERT_NEEDED);
9531 ssl3.cert_request_info = cert_request_info_proxy;
9532 ssl3.expected_send_client_cert = false;
9533 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl3);
9534
9535 HttpRequestInfo request1;
9536 request1.method = "GET";
9537 request1.url = GURL("https://www.example.org/");
9538 request1.traffic_annotation =
9539 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
9540
9541 TestCompletionCallback callback1;
9542
9543 HttpNetworkTransaction trans1(DEFAULT_PRIORITY, session.get());
9544
9545 int rv = trans1.Start(&request1, callback1.callback(),
9546 NetLogWithSource::Make(NetLogSourceType::NONE));
9547 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
9548
9549 spdy_data.RunUntilPaused();
9550 base::RunLoop().RunUntilIdle();
9551 spdy_data.Resume();
9552
9553 rv = callback1.WaitForResult();
9554 ASSERT_THAT(rv, IsError(ERR_SSL_CLIENT_AUTH_CERT_NEEDED));
9555
9556 SSLSocketDataProvider ssl4(ASYNC, OK);
9557 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl4);
9558
9559 TestCompletionCallback callback2;
9560
9561 HttpNetworkTransaction trans2(DEFAULT_PRIORITY, session.get());
9562
9563 rv = trans2.Start(&request1, callback2.callback(),
9564 NetLogWithSource::Make(NetLogSourceType::NONE));
9565 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
9566
9567 spdy_data.RunUntilPaused();
9568 base::RunLoop().RunUntilIdle();
9569 spdy_data.Resume();
9570
9571 rv = callback2.WaitForResult();
9572 ASSERT_THAT(rv, IsOk());
9573
9574 const HttpResponseInfo* response = trans2.GetResponseInfo();
9575 ASSERT_TRUE(response);
9576 ASSERT_TRUE(response->headers);
9577 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
9578
9579 std::string response_data;
9580 ASSERT_THAT(ReadTransaction(&trans2, &response_data), IsOk());
9581 EXPECT_EQ(kRespData, response_data);
9582 }
9583
9584 // Test the case where a proxied H2 session doesn't exist when an auth challenge
9585 // is observed, but does exist by the time auth credentials are provided. In
9586 // this case, auth and SSL are fully negotated on the second request, but then
9587 // the socket is discarded to use the shared session.
TEST_P(HttpNetworkTransactionTest,ProxiedH2SessionAppearsDuringAuth)9588 TEST_P(HttpNetworkTransactionTest, ProxiedH2SessionAppearsDuringAuth) {
9589 ProxyConfig proxy_config;
9590 proxy_config.set_auto_detect(true);
9591 proxy_config.set_pac_url(GURL("http://fooproxyurl"));
9592
9593 CapturingProxyResolver capturing_proxy_resolver;
9594 capturing_proxy_resolver.set_proxy_chain(
9595 ProxyChain(ProxyServer::SCHEME_HTTP, HostPortPair("myproxy", 70)));
9596 session_deps_.proxy_resolution_service =
9597 std::make_unique<ConfiguredProxyResolutionService>(
9598 std::make_unique<ProxyConfigServiceFixed>(ProxyConfigWithAnnotation(
9599 proxy_config, TRAFFIC_ANNOTATION_FOR_TESTS)),
9600 std::make_unique<CapturingProxyResolverFactory>(
9601 &capturing_proxy_resolver),
9602 nullptr, /*quick_check_enabled=*/true);
9603
9604 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
9605
9606 const char kMyUrl[] = "https://www.example.org/";
9607 spdy::SpdySerializedFrame get(spdy_util_.ConstructSpdyGet(kMyUrl, 1, LOWEST));
9608 spdy::SpdySerializedFrame get_resp(
9609 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
9610 spdy::SpdySerializedFrame body(spdy_util_.ConstructSpdyDataFrame(1, true));
9611
9612 spdy_util_.UpdateWithStreamDestruction(1);
9613 spdy::SpdySerializedFrame get2(
9614 spdy_util_.ConstructSpdyGet(kMyUrl, 3, LOWEST));
9615 spdy::SpdySerializedFrame get_resp2(
9616 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 3));
9617 spdy::SpdySerializedFrame body2(spdy_util_.ConstructSpdyDataFrame(3, true));
9618
9619 MockWrite auth_challenge_writes[] = {
9620 MockWrite(ASYNC, 0,
9621 "CONNECT www.example.org:443 HTTP/1.1\r\n"
9622 "Host: www.example.org:443\r\n"
9623 "Proxy-Connection: keep-alive\r\n\r\n"),
9624 MockWrite(ASYNC, 2,
9625 "CONNECT www.example.org:443 HTTP/1.1\r\n"
9626 "Host: www.example.org:443\r\n"
9627 "Proxy-Connection: keep-alive\r\n\r\n"),
9628 };
9629
9630 MockRead auth_challenge_reads[] = {
9631 MockRead(ASYNC, 1,
9632 "HTTP/1.1 407 Authentication Required\r\n"
9633 "Content-Length: 0\r\n"
9634 "Proxy-Connection: close\r\n"
9635 "Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n\r\n"),
9636 };
9637
9638 MockWrite spdy_writes[] = {
9639 MockWrite(ASYNC, 0,
9640 "CONNECT www.example.org:443 HTTP/1.1\r\n"
9641 "Host: www.example.org:443\r\n"
9642 "Proxy-Connection: keep-alive\r\n"
9643 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
9644 CreateMockWrite(get, 2),
9645 CreateMockWrite(get2, 5),
9646 };
9647
9648 MockRead spdy_reads[] = {
9649 MockRead(ASYNC, 1, "HTTP/1.1 200 OK\r\n\r\n"),
9650 CreateMockRead(get_resp, 3, ASYNC),
9651 CreateMockRead(body, 4, ASYNC),
9652 CreateMockRead(get_resp2, 6, ASYNC),
9653 CreateMockRead(body2, 7, ASYNC),
9654
9655 MockRead(SYNCHRONOUS, ERR_IO_PENDING, 8),
9656 };
9657
9658 MockWrite auth_response_writes_discarded_socket[] = {
9659 MockWrite(ASYNC, 0,
9660 "CONNECT www.example.org:443 HTTP/1.1\r\n"
9661 "Host: www.example.org:443\r\n"
9662 "Proxy-Connection: keep-alive\r\n"
9663 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
9664 };
9665
9666 MockRead auth_response_reads_discarded_socket[] = {
9667 MockRead(ASYNC, 1, "HTTP/1.1 200 OK\r\n\r\n"),
9668 };
9669
9670 SequencedSocketData auth_challenge1(auth_challenge_reads,
9671 auth_challenge_writes);
9672 session_deps_.socket_factory->AddSocketDataProvider(&auth_challenge1);
9673
9674 SequencedSocketData auth_challenge2(auth_challenge_reads,
9675 auth_challenge_writes);
9676 session_deps_.socket_factory->AddSocketDataProvider(&auth_challenge2);
9677
9678 SequencedSocketData spdy_data(spdy_reads, spdy_writes);
9679 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
9680
9681 SequencedSocketData auth_response_discarded_socket(
9682 auth_response_reads_discarded_socket,
9683 auth_response_writes_discarded_socket);
9684 session_deps_.socket_factory->AddSocketDataProvider(
9685 &auth_response_discarded_socket);
9686
9687 SSLSocketDataProvider ssl(ASYNC, OK);
9688 ssl.next_proto = kProtoHTTP2;
9689 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
9690
9691 SSLSocketDataProvider ssl2(ASYNC, OK);
9692 ssl2.next_proto = kProtoHTTP2;
9693 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
9694
9695 TestCompletionCallback callback;
9696 std::string response_data;
9697
9698 // Run first request until an auth challenge is observed.
9699 HttpRequestInfo request1;
9700 request1.method = "GET";
9701 request1.url = GURL(kMyUrl);
9702 request1.traffic_annotation =
9703 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
9704 HttpNetworkTransaction trans1(LOWEST, session.get());
9705 int rv = trans1.Start(&request1, callback.callback(), NetLogWithSource());
9706 EXPECT_THAT(callback.GetResult(rv), IsOk());
9707 const HttpResponseInfo* response = trans1.GetResponseInfo();
9708 ASSERT_TRUE(response);
9709 ASSERT_TRUE(response->headers);
9710 EXPECT_EQ(407, response->headers->response_code());
9711 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
9712 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge));
9713
9714 // Run second request until an auth challenge is observed.
9715 HttpRequestInfo request2;
9716 request2.method = "GET";
9717 request2.url = GURL(kMyUrl);
9718 request2.traffic_annotation =
9719 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
9720 HttpNetworkTransaction trans2(LOWEST, session.get());
9721 rv = trans2.Start(&request2, callback.callback(), NetLogWithSource());
9722 EXPECT_THAT(callback.GetResult(rv), IsOk());
9723 response = trans2.GetResponseInfo();
9724 ASSERT_TRUE(response);
9725 ASSERT_TRUE(response->headers);
9726 EXPECT_EQ(407, response->headers->response_code());
9727 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
9728 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge));
9729
9730 // Now provide credentials for the first request, and wait for it to complete.
9731 rv = trans1.RestartWithAuth(AuthCredentials(kFoo, kBar), callback.callback());
9732 rv = callback.GetResult(rv);
9733 EXPECT_THAT(rv, IsOk());
9734 response = trans1.GetResponseInfo();
9735 ASSERT_TRUE(response);
9736 ASSERT_TRUE(response->headers);
9737 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
9738 ASSERT_THAT(ReadTransaction(&trans1, &response_data), IsOk());
9739 EXPECT_EQ(kUploadData, response_data);
9740
9741 // Now provide credentials for the second request. It should notice the
9742 // existing session, and reuse it.
9743 rv = trans2.RestartWithAuth(AuthCredentials(kFoo, kBar), callback.callback());
9744 EXPECT_THAT(callback.GetResult(rv), IsOk());
9745 response = trans2.GetResponseInfo();
9746 ASSERT_TRUE(response);
9747 ASSERT_TRUE(response->headers);
9748 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
9749 ASSERT_THAT(ReadTransaction(&trans2, &response_data), IsOk());
9750 EXPECT_EQ(kUploadData, response_data);
9751 }
9752
9753 // Test load timing in the case of two HTTPS (non-SPDY) requests through a SPDY
9754 // HTTPS Proxy to different servers.
TEST_P(HttpNetworkTransactionTest,HttpsProxySpdyConnectHttpsLoadTimingTwoRequestsTwoServers)9755 TEST_P(HttpNetworkTransactionTest,
9756 HttpsProxySpdyConnectHttpsLoadTimingTwoRequestsTwoServers) {
9757 // Configure against https proxy server "proxy:70".
9758 session_deps_.proxy_resolution_service =
9759 ConfiguredProxyResolutionService::CreateFixedForTest(
9760 "https://proxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
9761 session_deps_.net_log = NetLog::Get();
9762 std::unique_ptr<HttpNetworkSession> session(
9763 SpdySessionDependencies::SpdyCreateSession(&session_deps_));
9764
9765 HttpRequestInfo request1;
9766 request1.method = "GET";
9767 request1.url = GURL("https://www.example.org/");
9768 request1.load_flags = 0;
9769 request1.traffic_annotation =
9770 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
9771
9772 HttpRequestInfo request2;
9773 request2.method = "GET";
9774 request2.url = GURL("https://mail.example.org/");
9775 request2.load_flags = 0;
9776 request2.traffic_annotation =
9777 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
9778
9779 // CONNECT to www.example.org:443 via SPDY.
9780 spdy::SpdySerializedFrame connect1(spdy_util_.ConstructSpdyConnect(
9781 nullptr, 0, 1, HttpProxyConnectJob::kH2QuicTunnelPriority,
9782 HostPortPair("www.example.org", 443)));
9783 spdy::SpdySerializedFrame conn_resp1(
9784 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
9785
9786 // Fetch https://www.example.org/ via HTTP.
9787 const char kGet1[] =
9788 "GET / HTTP/1.1\r\n"
9789 "Host: www.example.org\r\n"
9790 "Connection: keep-alive\r\n\r\n";
9791 spdy::SpdySerializedFrame wrapped_get1(
9792 spdy_util_.ConstructSpdyDataFrame(1, kGet1, false));
9793 const char kResp1[] =
9794 "HTTP/1.1 200 OK\r\n"
9795 "Content-Length: 1\r\n\r\n";
9796 spdy::SpdySerializedFrame wrapped_get_resp1(
9797 spdy_util_.ConstructSpdyDataFrame(1, kResp1, false));
9798 spdy::SpdySerializedFrame wrapped_body1(
9799 spdy_util_.ConstructSpdyDataFrame(1, "1", false));
9800
9801 // CONNECT to mail.example.org:443 via SPDY.
9802 spdy::Http2HeaderBlock connect2_block;
9803 connect2_block[spdy::kHttp2MethodHeader] = "CONNECT";
9804 connect2_block[spdy::kHttp2AuthorityHeader] = "mail.example.org:443";
9805 spdy::SpdySerializedFrame connect2(spdy_util_.ConstructSpdyHeaders(
9806 3, std::move(connect2_block), HttpProxyConnectJob::kH2QuicTunnelPriority,
9807 false));
9808
9809 spdy::SpdySerializedFrame conn_resp2(
9810 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 3));
9811
9812 // Fetch https://mail.example.org/ via HTTP.
9813 const char kGet2[] =
9814 "GET / HTTP/1.1\r\n"
9815 "Host: mail.example.org\r\n"
9816 "Connection: keep-alive\r\n\r\n";
9817 spdy::SpdySerializedFrame wrapped_get2(
9818 spdy_util_.ConstructSpdyDataFrame(3, kGet2, false));
9819 const char kResp2[] =
9820 "HTTP/1.1 200 OK\r\n"
9821 "Content-Length: 2\r\n\r\n";
9822 spdy::SpdySerializedFrame wrapped_get_resp2(
9823 spdy_util_.ConstructSpdyDataFrame(3, kResp2, false));
9824 spdy::SpdySerializedFrame wrapped_body2(
9825 spdy_util_.ConstructSpdyDataFrame(3, "22", false));
9826
9827 MockWrite spdy_writes[] = {
9828 CreateMockWrite(connect1, 0),
9829 CreateMockWrite(wrapped_get1, 2),
9830 CreateMockWrite(connect2, 5),
9831 CreateMockWrite(wrapped_get2, 7),
9832 };
9833
9834 MockRead spdy_reads[] = {
9835 CreateMockRead(conn_resp1, 1, ASYNC),
9836 CreateMockRead(wrapped_get_resp1, 3, ASYNC),
9837 CreateMockRead(wrapped_body1, 4, ASYNC),
9838 CreateMockRead(conn_resp2, 6, ASYNC),
9839 CreateMockRead(wrapped_get_resp2, 8, ASYNC),
9840 CreateMockRead(wrapped_body2, 9, ASYNC),
9841 MockRead(ASYNC, 0, 10),
9842 };
9843
9844 SequencedSocketData spdy_data(spdy_reads, spdy_writes);
9845 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
9846
9847 SSLSocketDataProvider ssl(ASYNC, OK);
9848 ssl.next_proto = kProtoHTTP2;
9849 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
9850 SSLSocketDataProvider ssl2(ASYNC, OK);
9851 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
9852 SSLSocketDataProvider ssl3(ASYNC, OK);
9853 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl3);
9854
9855 TestCompletionCallback callback;
9856
9857 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
9858 int rv = trans.Start(&request1, callback.callback(), NetLogWithSource());
9859 EXPECT_THAT(callback.GetResult(rv), IsOk());
9860
9861 LoadTimingInfo load_timing_info;
9862 EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info));
9863 TestLoadTimingNotReused(load_timing_info, CONNECT_TIMING_HAS_SSL_TIMES);
9864
9865 const HttpResponseInfo* response = trans.GetResponseInfo();
9866 ASSERT_TRUE(response);
9867 ASSERT_TRUE(response->headers);
9868 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
9869
9870 std::string response_data;
9871 auto buf = base::MakeRefCounted<IOBufferWithSize>(256);
9872 rv = trans.Read(buf.get(), 256, callback.callback());
9873 EXPECT_EQ(1, callback.GetResult(rv));
9874
9875 HttpNetworkTransaction trans2(DEFAULT_PRIORITY, session.get());
9876 rv = trans2.Start(&request2, callback.callback(), NetLogWithSource());
9877 EXPECT_THAT(callback.GetResult(rv), IsOk());
9878
9879 LoadTimingInfo load_timing_info2;
9880 EXPECT_TRUE(trans2.GetLoadTimingInfo(&load_timing_info2));
9881 // Even though the SPDY connection is reused, a new tunnelled connection has
9882 // to be created, so the socket's load timing looks like a fresh connection.
9883 TestLoadTimingNotReused(load_timing_info2, CONNECT_TIMING_HAS_SSL_TIMES);
9884
9885 // The requests should have different IDs, since they each are using their own
9886 // separate stream.
9887 EXPECT_NE(load_timing_info.socket_log_id, load_timing_info2.socket_log_id);
9888
9889 rv = trans2.Read(buf.get(), 256, callback.callback());
9890 EXPECT_EQ(2, callback.GetResult(rv));
9891 }
9892
9893 // Test load timing in the case of two HTTPS (non-SPDY) requests through a SPDY
9894 // HTTPS Proxy to the same server.
TEST_P(HttpNetworkTransactionTest,HttpsProxySpdyConnectHttpsLoadTimingTwoRequestsSameServer)9895 TEST_P(HttpNetworkTransactionTest,
9896 HttpsProxySpdyConnectHttpsLoadTimingTwoRequestsSameServer) {
9897 // Configure against https proxy server "proxy:70".
9898 session_deps_.proxy_resolution_service =
9899 ConfiguredProxyResolutionService::CreateFixedForTest(
9900 "https://proxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
9901 session_deps_.net_log = NetLog::Get();
9902 std::unique_ptr<HttpNetworkSession> session(
9903 SpdySessionDependencies::SpdyCreateSession(&session_deps_));
9904
9905 HttpRequestInfo request1;
9906 request1.method = "GET";
9907 request1.url = GURL("https://www.example.org/");
9908 request1.load_flags = 0;
9909 request1.traffic_annotation =
9910 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
9911
9912 HttpRequestInfo request2;
9913 request2.method = "GET";
9914 request2.url = GURL("https://www.example.org/2");
9915 request2.load_flags = 0;
9916 request2.traffic_annotation =
9917 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
9918
9919 // CONNECT to www.example.org:443 via SPDY.
9920 spdy::SpdySerializedFrame connect1(spdy_util_.ConstructSpdyConnect(
9921 nullptr, 0, 1, HttpProxyConnectJob::kH2QuicTunnelPriority,
9922 HostPortPair("www.example.org", 443)));
9923 spdy::SpdySerializedFrame conn_resp1(
9924 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
9925
9926 // Fetch https://www.example.org/ via HTTP.
9927 const char kGet1[] =
9928 "GET / HTTP/1.1\r\n"
9929 "Host: www.example.org\r\n"
9930 "Connection: keep-alive\r\n\r\n";
9931 spdy::SpdySerializedFrame wrapped_get1(
9932 spdy_util_.ConstructSpdyDataFrame(1, kGet1, false));
9933 const char kResp1[] =
9934 "HTTP/1.1 200 OK\r\n"
9935 "Content-Length: 1\r\n\r\n";
9936 spdy::SpdySerializedFrame wrapped_get_resp1(
9937 spdy_util_.ConstructSpdyDataFrame(1, kResp1, false));
9938 spdy::SpdySerializedFrame wrapped_body1(
9939 spdy_util_.ConstructSpdyDataFrame(1, "1", false));
9940
9941 // Fetch https://www.example.org/2 via HTTP.
9942 const char kGet2[] =
9943 "GET /2 HTTP/1.1\r\n"
9944 "Host: www.example.org\r\n"
9945 "Connection: keep-alive\r\n\r\n";
9946 spdy::SpdySerializedFrame wrapped_get2(
9947 spdy_util_.ConstructSpdyDataFrame(1, kGet2, false));
9948 const char kResp2[] =
9949 "HTTP/1.1 200 OK\r\n"
9950 "Content-Length: 2\r\n\r\n";
9951 spdy::SpdySerializedFrame wrapped_get_resp2(
9952 spdy_util_.ConstructSpdyDataFrame(1, kResp2, false));
9953 spdy::SpdySerializedFrame wrapped_body2(
9954 spdy_util_.ConstructSpdyDataFrame(1, "22", false));
9955
9956 MockWrite spdy_writes[] = {
9957 CreateMockWrite(connect1, 0),
9958 CreateMockWrite(wrapped_get1, 2),
9959 CreateMockWrite(wrapped_get2, 5),
9960 };
9961
9962 MockRead spdy_reads[] = {
9963 CreateMockRead(conn_resp1, 1, ASYNC),
9964 CreateMockRead(wrapped_get_resp1, 3, ASYNC),
9965 CreateMockRead(wrapped_body1, 4, SYNCHRONOUS),
9966 CreateMockRead(wrapped_get_resp2, 6, ASYNC),
9967 CreateMockRead(wrapped_body2, 7, SYNCHRONOUS),
9968 MockRead(ASYNC, 0, 8),
9969 };
9970
9971 SequencedSocketData spdy_data(spdy_reads, spdy_writes);
9972 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
9973
9974 SSLSocketDataProvider ssl(ASYNC, OK);
9975 ssl.next_proto = kProtoHTTP2;
9976 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
9977 SSLSocketDataProvider ssl2(ASYNC, OK);
9978 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
9979
9980 TestCompletionCallback callback;
9981
9982 auto trans =
9983 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
9984 int rv = trans->Start(&request1, callback.callback(), NetLogWithSource());
9985 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
9986
9987 rv = callback.WaitForResult();
9988 EXPECT_THAT(rv, IsOk());
9989
9990 LoadTimingInfo load_timing_info;
9991 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
9992 TestLoadTimingNotReused(load_timing_info, CONNECT_TIMING_HAS_SSL_TIMES);
9993
9994 const HttpResponseInfo* response = trans->GetResponseInfo();
9995 ASSERT_TRUE(response);
9996 ASSERT_TRUE(response->headers);
9997 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
9998
9999 std::string response_data;
10000 auto buf = base::MakeRefCounted<IOBufferWithSize>(256);
10001 EXPECT_EQ(1, trans->Read(buf.get(), 256, callback.callback()));
10002 trans.reset();
10003
10004 auto trans2 =
10005 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
10006 rv = trans2->Start(&request2, callback.callback(), NetLogWithSource());
10007 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
10008
10009 rv = callback.WaitForResult();
10010 EXPECT_THAT(rv, IsOk());
10011
10012 LoadTimingInfo load_timing_info2;
10013 EXPECT_TRUE(trans2->GetLoadTimingInfo(&load_timing_info2));
10014 TestLoadTimingReused(load_timing_info2);
10015
10016 // The requests should have the same ID.
10017 EXPECT_EQ(load_timing_info.socket_log_id, load_timing_info2.socket_log_id);
10018
10019 EXPECT_EQ(2, trans2->Read(buf.get(), 256, callback.callback()));
10020 }
10021
10022 // Test load timing in the case of of two HTTP requests through a SPDY HTTPS
10023 // Proxy to different servers.
TEST_P(HttpNetworkTransactionTest,HttpsProxySpdyLoadTimingTwoHttpRequests)10024 TEST_P(HttpNetworkTransactionTest, HttpsProxySpdyLoadTimingTwoHttpRequests) {
10025 // Configure against https proxy server "proxy:70".
10026 session_deps_.proxy_resolution_service =
10027 ConfiguredProxyResolutionService::CreateFixedForTest(
10028 "https://proxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
10029 session_deps_.net_log = NetLog::Get();
10030 std::unique_ptr<HttpNetworkSession> session(
10031 SpdySessionDependencies::SpdyCreateSession(&session_deps_));
10032
10033 HttpRequestInfo request1;
10034 request1.method = "GET";
10035 request1.url = GURL("http://www.example.org/");
10036 request1.load_flags = 0;
10037 request1.traffic_annotation =
10038 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
10039
10040 HttpRequestInfo request2;
10041 request2.method = "GET";
10042 request2.url = GURL("http://mail.example.org/");
10043 request2.load_flags = 0;
10044 request2.traffic_annotation =
10045 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
10046
10047 // http://www.example.org/
10048 spdy::Http2HeaderBlock headers(
10049 spdy_util_.ConstructGetHeaderBlockForProxy("http://www.example.org/"));
10050 spdy::SpdySerializedFrame get1(
10051 spdy_util_.ConstructSpdyHeaders(1, std::move(headers), LOWEST, true));
10052 spdy::SpdySerializedFrame get_resp1(
10053 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
10054 spdy::SpdySerializedFrame body1(
10055 spdy_util_.ConstructSpdyDataFrame(1, "1", true));
10056 spdy_util_.UpdateWithStreamDestruction(1);
10057
10058 // http://mail.example.org/
10059 spdy::Http2HeaderBlock headers2(
10060 spdy_util_.ConstructGetHeaderBlockForProxy("http://mail.example.org/"));
10061 spdy::SpdySerializedFrame get2(
10062 spdy_util_.ConstructSpdyHeaders(3, std::move(headers2), LOWEST, true));
10063 spdy::SpdySerializedFrame get_resp2(
10064 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 3));
10065 spdy::SpdySerializedFrame body2(
10066 spdy_util_.ConstructSpdyDataFrame(3, "22", true));
10067
10068 MockWrite spdy_writes[] = {
10069 CreateMockWrite(get1, 0),
10070 CreateMockWrite(get2, 3),
10071 };
10072
10073 MockRead spdy_reads[] = {
10074 CreateMockRead(get_resp1, 1, ASYNC),
10075 CreateMockRead(body1, 2, ASYNC),
10076 CreateMockRead(get_resp2, 4, ASYNC),
10077 CreateMockRead(body2, 5, ASYNC),
10078 MockRead(ASYNC, 0, 6),
10079 };
10080
10081 SequencedSocketData spdy_data(spdy_reads, spdy_writes);
10082 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
10083
10084 SSLSocketDataProvider ssl(ASYNC, OK);
10085 ssl.next_proto = kProtoHTTP2;
10086 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
10087
10088 TestCompletionCallback callback;
10089
10090 auto trans =
10091 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
10092 int rv = trans->Start(&request1, callback.callback(), NetLogWithSource());
10093 EXPECT_THAT(callback.GetResult(rv), IsOk());
10094
10095 LoadTimingInfo load_timing_info;
10096 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
10097 TestLoadTimingNotReused(load_timing_info,
10098 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY);
10099
10100 const HttpResponseInfo* response = trans->GetResponseInfo();
10101 ASSERT_TRUE(response);
10102 ASSERT_TRUE(response->headers);
10103 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
10104
10105 std::string response_data;
10106 auto buf = base::MakeRefCounted<IOBufferWithSize>(256);
10107 rv = trans->Read(buf.get(), 256, callback.callback());
10108 EXPECT_EQ(1, callback.GetResult(rv));
10109 // Delete the first request, so the second one can reuse the socket.
10110 trans.reset();
10111
10112 HttpNetworkTransaction trans2(DEFAULT_PRIORITY, session.get());
10113 rv = trans2.Start(&request2, callback.callback(), NetLogWithSource());
10114 EXPECT_THAT(callback.GetResult(rv), IsOk());
10115
10116 LoadTimingInfo load_timing_info2;
10117 EXPECT_TRUE(trans2.GetLoadTimingInfo(&load_timing_info2));
10118 TestLoadTimingReused(load_timing_info2);
10119
10120 // The requests should have the same ID.
10121 EXPECT_EQ(load_timing_info.socket_log_id, load_timing_info2.socket_log_id);
10122
10123 rv = trans2.Read(buf.get(), 256, callback.callback());
10124 EXPECT_EQ(2, callback.GetResult(rv));
10125 }
10126
10127 // Test that an HTTP/2 CONNECT through an HTTPS Proxy to a HTTP/2 server and a
10128 // direct (non-proxied) request to the proxy server are not pooled, as that
10129 // would break socket pool isolation.
TEST_P(HttpNetworkTransactionTest,SpdyProxyIsolation1)10130 TEST_P(HttpNetworkTransactionTest, SpdyProxyIsolation1) {
10131 ProxyConfig proxy_config;
10132 proxy_config.set_auto_detect(true);
10133 proxy_config.set_pac_url(GURL("http://fooproxyurl"));
10134
10135 CapturingProxyResolver capturing_proxy_resolver;
10136 session_deps_.proxy_resolution_service =
10137 std::make_unique<ConfiguredProxyResolutionService>(
10138 std::make_unique<ProxyConfigServiceFixed>(ProxyConfigWithAnnotation(
10139 proxy_config, TRAFFIC_ANNOTATION_FOR_TESTS)),
10140 std::make_unique<CapturingProxyResolverFactory>(
10141 &capturing_proxy_resolver),
10142 nullptr, /*quick_check_enabled=*/true);
10143
10144 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
10145
10146 SpdyTestUtil spdy_util1(/*use_priority_header=*/true);
10147 // CONNECT to www.example.org:443 via HTTP/2.
10148 spdy::SpdySerializedFrame connect(spdy_util_.ConstructSpdyConnect(
10149 nullptr, 0, 1, HttpProxyConnectJob::kH2QuicTunnelPriority,
10150 HostPortPair("www.example.org", 443)));
10151 // fetch https://www.example.org/ via HTTP/2.
10152 const char kMyUrl[] = "https://www.example.org/";
10153 spdy::SpdySerializedFrame get(spdy_util1.ConstructSpdyGet(kMyUrl, 1, LOWEST));
10154 spdy::SpdySerializedFrame wrapped_get(
10155 spdy_util_.ConstructWrappedSpdyFrame(get, 1));
10156 spdy::SpdySerializedFrame conn_resp(
10157 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
10158 spdy::SpdySerializedFrame get_resp(
10159 spdy_util1.ConstructSpdyGetReply(nullptr, 0, 1));
10160 spdy::SpdySerializedFrame wrapped_get_resp(
10161 spdy_util_.ConstructWrappedSpdyFrame(get_resp, 1));
10162 spdy::SpdySerializedFrame body(spdy_util1.ConstructSpdyDataFrame(1, true));
10163 spdy::SpdySerializedFrame wrapped_body(
10164 spdy_util_.ConstructWrappedSpdyFrame(body, 1));
10165 spdy::SpdySerializedFrame window_update_get_resp(
10166 spdy_util_.ConstructSpdyWindowUpdate(1, wrapped_get_resp.size()));
10167 spdy::SpdySerializedFrame window_update_body(
10168 spdy_util_.ConstructSpdyWindowUpdate(1, wrapped_body.size()));
10169
10170 MockWrite spdy_writes1[] = {
10171 CreateMockWrite(connect, 0),
10172 CreateMockWrite(wrapped_get, 2),
10173 CreateMockWrite(window_update_get_resp, 6),
10174 CreateMockWrite(window_update_body, 7),
10175 };
10176
10177 MockRead spdy_reads1[] = {
10178 CreateMockRead(conn_resp, 1, ASYNC),
10179 MockRead(ASYNC, ERR_IO_PENDING, 3),
10180 CreateMockRead(wrapped_get_resp, 4, ASYNC),
10181 CreateMockRead(wrapped_body, 5, ASYNC),
10182 MockRead(ASYNC, 0, 8),
10183 };
10184
10185 SequencedSocketData spdy_data1(spdy_reads1, spdy_writes1);
10186 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data1);
10187
10188 // Fetch https://proxy:70/ via HTTP/2. Needs a new SpdyTestUtil, since it uses
10189 // a new pipe.
10190 SpdyTestUtil spdy_util2(/*use_priority_header=*/true);
10191 spdy::SpdySerializedFrame req(
10192 spdy_util2.ConstructSpdyGet("https://proxy:70/", 1, LOWEST));
10193 MockWrite spdy_writes2[] = {CreateMockWrite(req, 0)};
10194
10195 spdy::SpdySerializedFrame resp(
10196 spdy_util2.ConstructSpdyGetReply(nullptr, 0, 1));
10197 spdy::SpdySerializedFrame data(spdy_util2.ConstructSpdyDataFrame(1, true));
10198 MockRead spdy_reads2[] = {
10199 CreateMockRead(resp, 1),
10200 CreateMockRead(data, 2),
10201 MockRead(ASYNC, 0, 3),
10202 };
10203 SequencedSocketData spdy_data2(spdy_reads2, spdy_writes2);
10204 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data2);
10205
10206 SSLSocketDataProvider ssl(ASYNC, OK);
10207 ssl.next_proto = kProtoHTTP2;
10208 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
10209 SSLSocketDataProvider ssl2(ASYNC, OK);
10210 ssl2.next_proto = kProtoHTTP2;
10211 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
10212 SSLSocketDataProvider ssl3(ASYNC, OK);
10213 ssl3.next_proto = kProtoHTTP2;
10214 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl3);
10215
10216 TestCompletionCallback callback;
10217 std::string response_data;
10218
10219 // Make a request using proxy:70 as a HTTP/2 proxy.
10220 capturing_proxy_resolver.set_proxy_chain(
10221 ProxyChain(ProxyServer::SCHEME_HTTPS, HostPortPair("proxy", 70)));
10222 HttpRequestInfo request1;
10223 request1.method = "GET";
10224 request1.url = GURL("https://www.example.org/");
10225 request1.traffic_annotation =
10226 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
10227
10228 HttpNetworkTransaction trans1(LOWEST, session.get());
10229 int rv = trans1.Start(&request1, callback.callback(), NetLogWithSource());
10230 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
10231
10232 // Allow the SpdyProxyClientSocket's write callback to complete.
10233 base::RunLoop().RunUntilIdle();
10234 // Now allow the read of the response to complete.
10235 spdy_data1.Resume();
10236 rv = callback.WaitForResult();
10237 EXPECT_THAT(rv, IsOk());
10238
10239 const HttpResponseInfo* response = trans1.GetResponseInfo();
10240 ASSERT_TRUE(response);
10241 ASSERT_TRUE(response->headers);
10242 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
10243
10244 ASSERT_THAT(ReadTransaction(&trans1, &response_data), IsOk());
10245 EXPECT_EQ(kUploadData, response_data);
10246 RunUntilIdle();
10247
10248 // Make a direct HTTP/2 request to proxy:70.
10249 capturing_proxy_resolver.set_proxy_chain(ProxyChain::Direct());
10250 HttpRequestInfo request2;
10251 request2.method = "GET";
10252 request2.url = GURL("https://proxy:70/");
10253 request2.traffic_annotation =
10254 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
10255 HttpNetworkTransaction trans2(LOWEST, session.get());
10256 EXPECT_THAT(callback.GetResult(trans2.Start(&request2, callback.callback(),
10257 NetLogWithSource())),
10258 IsOk());
10259 ASSERT_THAT(ReadTransaction(&trans2, &response_data), IsOk());
10260 }
10261
10262 // Same as above, but reverse request order, since the code to check for an
10263 // existing session is different for tunnels and direct connections.
TEST_P(HttpNetworkTransactionTest,SpdyProxyIsolation2)10264 TEST_P(HttpNetworkTransactionTest, SpdyProxyIsolation2) {
10265 // Configure against https proxy server "myproxy:80".
10266 ProxyConfig proxy_config;
10267 proxy_config.set_auto_detect(true);
10268 proxy_config.set_pac_url(GURL("http://fooproxyurl"));
10269
10270 CapturingProxyResolver capturing_proxy_resolver;
10271 session_deps_.proxy_resolution_service =
10272 std::make_unique<ConfiguredProxyResolutionService>(
10273 std::make_unique<ProxyConfigServiceFixed>(ProxyConfigWithAnnotation(
10274 proxy_config, TRAFFIC_ANNOTATION_FOR_TESTS)),
10275 std::make_unique<CapturingProxyResolverFactory>(
10276 &capturing_proxy_resolver),
10277 nullptr, /*quick_check_enabled=*/true);
10278
10279 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
10280 // Fetch https://proxy:70/ via HTTP/2.
10281 SpdyTestUtil spdy_util1(/*use_priority_header=*/true);
10282 spdy::SpdySerializedFrame req(
10283 spdy_util1.ConstructSpdyGet("https://proxy:70/", 1, LOWEST));
10284 MockWrite spdy_writes1[] = {CreateMockWrite(req, 0)};
10285
10286 spdy::SpdySerializedFrame resp(
10287 spdy_util1.ConstructSpdyGetReply(nullptr, 0, 1));
10288 spdy::SpdySerializedFrame data(spdy_util1.ConstructSpdyDataFrame(1, true));
10289 MockRead spdy_reads1[] = {
10290 CreateMockRead(resp, 1),
10291 CreateMockRead(data, 2),
10292 MockRead(ASYNC, 0, 3),
10293 };
10294 SequencedSocketData spdy_data1(spdy_reads1, spdy_writes1);
10295 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data1);
10296
10297 SpdyTestUtil spdy_util2(/*use_priority_header=*/true);
10298 // CONNECT to www.example.org:443 via HTTP/2.
10299 spdy::SpdySerializedFrame connect(spdy_util_.ConstructSpdyConnect(
10300 nullptr, 0, 1, HttpProxyConnectJob::kH2QuicTunnelPriority,
10301 HostPortPair("www.example.org", 443)));
10302 // fetch https://www.example.org/ via HTTP/2.
10303 const char kMyUrl[] = "https://www.example.org/";
10304 spdy::SpdySerializedFrame get(spdy_util2.ConstructSpdyGet(kMyUrl, 1, LOWEST));
10305 spdy::SpdySerializedFrame wrapped_get(
10306 spdy_util_.ConstructWrappedSpdyFrame(get, 1));
10307 spdy::SpdySerializedFrame conn_resp(
10308 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
10309 spdy::SpdySerializedFrame get_resp(
10310 spdy_util2.ConstructSpdyGetReply(nullptr, 0, 1));
10311 spdy::SpdySerializedFrame wrapped_get_resp(
10312 spdy_util_.ConstructWrappedSpdyFrame(get_resp, 1));
10313 spdy::SpdySerializedFrame body(spdy_util2.ConstructSpdyDataFrame(1, true));
10314 spdy::SpdySerializedFrame wrapped_body(
10315 spdy_util_.ConstructWrappedSpdyFrame(body, 1));
10316 spdy::SpdySerializedFrame window_update_get_resp(
10317 spdy_util_.ConstructSpdyWindowUpdate(1, wrapped_get_resp.size()));
10318 spdy::SpdySerializedFrame window_update_body(
10319 spdy_util_.ConstructSpdyWindowUpdate(1, wrapped_body.size()));
10320
10321 MockWrite spdy_writes2[] = {
10322 CreateMockWrite(connect, 0),
10323 CreateMockWrite(wrapped_get, 2),
10324 CreateMockWrite(window_update_get_resp, 6),
10325 CreateMockWrite(window_update_body, 7),
10326 };
10327
10328 MockRead spdy_reads2[] = {
10329 CreateMockRead(conn_resp, 1, ASYNC),
10330 MockRead(ASYNC, ERR_IO_PENDING, 3),
10331 CreateMockRead(wrapped_get_resp, 4, ASYNC),
10332 CreateMockRead(wrapped_body, 5, ASYNC),
10333 MockRead(ASYNC, 0, 8),
10334 };
10335
10336 SequencedSocketData spdy_data2(spdy_reads2, spdy_writes2);
10337 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data2);
10338
10339 SSLSocketDataProvider ssl(ASYNC, OK);
10340 ssl.next_proto = kProtoHTTP2;
10341 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
10342 SSLSocketDataProvider ssl2(ASYNC, OK);
10343 ssl2.next_proto = kProtoHTTP2;
10344 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
10345 SSLSocketDataProvider ssl3(ASYNC, OK);
10346 ssl3.next_proto = kProtoHTTP2;
10347 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl3);
10348
10349 TestCompletionCallback callback;
10350 std::string response_data;
10351
10352 // Make a direct HTTP/2 request to proxy:70.
10353 capturing_proxy_resolver.set_proxy_chain(ProxyChain::Direct());
10354 HttpRequestInfo request1;
10355 request1.method = "GET";
10356 request1.url = GURL("https://proxy:70/");
10357 request1.traffic_annotation =
10358 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
10359 HttpNetworkTransaction trans1(LOWEST, session.get());
10360 EXPECT_THAT(callback.GetResult(trans1.Start(&request1, callback.callback(),
10361 NetLogWithSource())),
10362 IsOk());
10363 ASSERT_THAT(ReadTransaction(&trans1, &response_data), IsOk());
10364 RunUntilIdle();
10365
10366 // Make a request using proxy:70 as a HTTP/2 proxy.
10367 capturing_proxy_resolver.set_proxy_chain(
10368 ProxyChain(ProxyServer::SCHEME_HTTPS, HostPortPair("proxy", 70)));
10369 HttpRequestInfo request2;
10370 request2.method = "GET";
10371 request2.url = GURL("https://www.example.org/");
10372 request2.traffic_annotation =
10373 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
10374
10375 HttpNetworkTransaction trans2(LOWEST, session.get());
10376 int rv = trans2.Start(&request2, callback.callback(), NetLogWithSource());
10377 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
10378
10379 // Allow the SpdyProxyClientSocket's write callback to complete.
10380 base::RunLoop().RunUntilIdle();
10381 // Now allow the read of the response to complete.
10382 spdy_data2.Resume();
10383 rv = callback.WaitForResult();
10384 EXPECT_THAT(rv, IsOk());
10385
10386 const HttpResponseInfo* response2 = trans2.GetResponseInfo();
10387 ASSERT_TRUE(response2);
10388 ASSERT_TRUE(response2->headers);
10389 EXPECT_EQ("HTTP/1.1 200", response2->headers->GetStatusLine());
10390
10391 ASSERT_THAT(ReadTransaction(&trans2, &response_data), IsOk());
10392 EXPECT_EQ(kUploadData, response_data);
10393 }
10394
10395 // Test the challenge-response-retry sequence through an HTTPS Proxy
TEST_P(HttpNetworkTransactionTest,HttpsProxyAuthRetry)10396 TEST_P(HttpNetworkTransactionTest, HttpsProxyAuthRetry) {
10397 HttpRequestInfo request;
10398 request.method = "GET";
10399 request.url = GURL("http://www.example.org/");
10400 // when the no authentication data flag is set.
10401 request.privacy_mode = PRIVACY_MODE_ENABLED;
10402 request.traffic_annotation =
10403 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
10404
10405 // Configure against https proxy server "myproxy:70".
10406 session_deps_.proxy_resolution_service =
10407 ConfiguredProxyResolutionService::CreateFixedForTest(
10408 "https://myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
10409 session_deps_.net_log = NetLog::Get();
10410 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
10411
10412 // Since we have proxy, should use full url
10413 MockWrite data_writes1[] = {
10414 MockWrite("GET http://www.example.org/ HTTP/1.1\r\n"
10415 "Host: www.example.org\r\n"
10416 "Proxy-Connection: keep-alive\r\n\r\n"),
10417
10418 // After calling trans.RestartWithAuth(), this is the request we should
10419 // be issuing -- the final header line contains the credentials.
10420 MockWrite("GET http://www.example.org/ HTTP/1.1\r\n"
10421 "Host: www.example.org\r\n"
10422 "Proxy-Connection: keep-alive\r\n"
10423 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
10424 };
10425
10426 // The proxy responds to the GET with a 407, using a persistent
10427 // connection.
10428 MockRead data_reads1[] = {
10429 // No credentials.
10430 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
10431 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
10432 MockRead("Proxy-Connection: keep-alive\r\n"),
10433 MockRead("Content-Length: 0\r\n\r\n"),
10434
10435 MockRead("HTTP/1.1 200 OK\r\n"),
10436 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
10437 MockRead("Content-Length: 100\r\n\r\n"),
10438 MockRead(SYNCHRONOUS, OK),
10439 };
10440
10441 StaticSocketDataProvider data1(data_reads1, data_writes1);
10442 session_deps_.socket_factory->AddSocketDataProvider(&data1);
10443 SSLSocketDataProvider ssl(ASYNC, OK);
10444 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
10445
10446 TestCompletionCallback callback1;
10447
10448 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
10449
10450 int rv = trans.Start(&request, callback1.callback(),
10451 NetLogWithSource::Make(NetLogSourceType::NONE));
10452 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
10453
10454 rv = callback1.WaitForResult();
10455 EXPECT_THAT(rv, IsOk());
10456
10457 LoadTimingInfo load_timing_info;
10458 EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info));
10459 TestLoadTimingNotReused(load_timing_info,
10460 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY);
10461
10462 const HttpResponseInfo* response = trans.GetResponseInfo();
10463 ASSERT_TRUE(response);
10464 ASSERT_TRUE(response->headers);
10465 EXPECT_EQ(407, response->headers->response_code());
10466 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
10467 EXPECT_TRUE(CheckBasicSecureProxyAuth(response->auth_challenge));
10468 EXPECT_FALSE(response->did_use_http_auth);
10469 EXPECT_EQ(PacResultElementToProxyChain("HTTPS myproxy:70"),
10470 response->proxy_chain);
10471
10472 TestCompletionCallback callback2;
10473
10474 rv = trans.RestartWithAuth(AuthCredentials(kFoo, kBar), callback2.callback());
10475 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
10476
10477 rv = callback2.WaitForResult();
10478 EXPECT_THAT(rv, IsOk());
10479
10480 load_timing_info = LoadTimingInfo();
10481 EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info));
10482 // Retrying with HTTP AUTH is considered to be reusing a socket.
10483 TestLoadTimingReused(load_timing_info);
10484
10485 response = trans.GetResponseInfo();
10486 ASSERT_TRUE(response);
10487
10488 EXPECT_TRUE(response->headers->IsKeepAlive());
10489 EXPECT_EQ(200, response->headers->response_code());
10490 EXPECT_EQ(100, response->headers->GetContentLength());
10491 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
10492 EXPECT_TRUE(response->did_use_http_auth);
10493 EXPECT_EQ(PacResultElementToProxyChain("HTTPS myproxy:70"),
10494 response->proxy_chain);
10495
10496 // The password prompt info should not be set.
10497 EXPECT_FALSE(response->auth_challenge.has_value());
10498 }
10499
10500 // Test the challenge-response-retry sequence through an HTTPS Proxy over a
10501 // connection that requires a restart.
TEST_P(HttpNetworkTransactionTest,HttpsProxyAuthRetryNoKeepAlive)10502 TEST_P(HttpNetworkTransactionTest, HttpsProxyAuthRetryNoKeepAlive) {
10503 HttpRequestInfo request;
10504 request.method = "GET";
10505 request.url = GURL("http://www.example.org/");
10506 // when the no authentication data flag is set.
10507 request.privacy_mode = PRIVACY_MODE_ENABLED;
10508 request.traffic_annotation =
10509 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
10510
10511 // Configure against https proxy server "myproxy:70".
10512 session_deps_.proxy_resolution_service =
10513 ConfiguredProxyResolutionService::CreateFixedForTest(
10514 "https://myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
10515 session_deps_.net_log = NetLog::Get();
10516 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
10517
10518 // Since we have proxy, should use full url
10519 MockWrite data_writes1[] = {
10520 MockWrite("GET http://www.example.org/ HTTP/1.1\r\n"
10521 "Host: www.example.org\r\n"
10522 "Proxy-Connection: keep-alive\r\n\r\n"),
10523 };
10524
10525 // The proxy responds to the GET with a 407, using a non-persistent
10526 // connection.
10527 MockRead data_reads1[] = {
10528 // No credentials.
10529 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
10530 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
10531 MockRead("Proxy-Connection: close\r\n"),
10532 MockRead("Content-Length: 0\r\n\r\n"),
10533 };
10534
10535 MockWrite data_writes2[] = {
10536 // After calling trans.RestartWithAuth(), this is the request we should
10537 // be issuing -- the final header line contains the credentials.
10538 MockWrite("GET http://www.example.org/ HTTP/1.1\r\n"
10539 "Host: www.example.org\r\n"
10540 "Proxy-Connection: keep-alive\r\n"
10541 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
10542 };
10543
10544 MockRead data_reads2[] = {
10545 MockRead("HTTP/1.1 200 OK\r\n"),
10546 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
10547 MockRead("Content-Length: 100\r\n\r\n"),
10548 MockRead(SYNCHRONOUS, OK),
10549 };
10550
10551 StaticSocketDataProvider data1(data_reads1, data_writes1);
10552 session_deps_.socket_factory->AddSocketDataProvider(&data1);
10553 StaticSocketDataProvider data2(data_reads2, data_writes2);
10554 session_deps_.socket_factory->AddSocketDataProvider(&data2);
10555
10556 // One per each proxy connection.
10557 SSLSocketDataProvider ssl1(ASYNC, OK);
10558 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl1);
10559 SSLSocketDataProvider ssl2(ASYNC, OK);
10560 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
10561
10562 TestCompletionCallback callback1;
10563
10564 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
10565
10566 int rv = trans.Start(&request, callback1.callback(),
10567 NetLogWithSource::Make(NetLogSourceType::NONE));
10568 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
10569
10570 rv = callback1.WaitForResult();
10571 EXPECT_THAT(rv, IsOk());
10572
10573 LoadTimingInfo load_timing_info;
10574 EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info));
10575 TestLoadTimingNotReused(load_timing_info,
10576 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY);
10577
10578 const HttpResponseInfo* response = trans.GetResponseInfo();
10579 ASSERT_TRUE(response);
10580 ASSERT_TRUE(response->headers);
10581 EXPECT_EQ(407, response->headers->response_code());
10582 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
10583 EXPECT_TRUE(CheckBasicSecureProxyAuth(response->auth_challenge));
10584 EXPECT_FALSE(response->did_use_http_auth);
10585 EXPECT_EQ(PacResultElementToProxyChain("HTTPS myproxy:70"),
10586 response->proxy_chain);
10587
10588 TestCompletionCallback callback2;
10589
10590 rv = trans.RestartWithAuth(AuthCredentials(kFoo, kBar), callback2.callback());
10591 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
10592
10593 rv = callback2.WaitForResult();
10594 EXPECT_THAT(rv, IsOk());
10595
10596 load_timing_info = LoadTimingInfo();
10597 EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info));
10598 TestLoadTimingNotReused(load_timing_info,
10599 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY);
10600
10601 response = trans.GetResponseInfo();
10602 ASSERT_TRUE(response);
10603
10604 EXPECT_TRUE(response->headers->IsKeepAlive());
10605 EXPECT_EQ(200, response->headers->response_code());
10606 EXPECT_EQ(100, response->headers->GetContentLength());
10607 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
10608 EXPECT_TRUE(response->did_use_http_auth);
10609 EXPECT_EQ(PacResultElementToProxyChain("HTTPS myproxy:70"),
10610 response->proxy_chain);
10611
10612 // The password prompt info should not be set.
10613 EXPECT_FALSE(response->auth_challenge.has_value());
10614 }
10615
10616 // Test the challenge-response-retry sequence through an HTTPS Proxy over a
10617 // connection that requires a restart, with a proxy change occurring over the
10618 // restart.
TEST_P(HttpNetworkTransactionTest,HttpsProxyAuthRetryNoKeepAliveChangeProxy)10619 TEST_P(HttpNetworkTransactionTest, HttpsProxyAuthRetryNoKeepAliveChangeProxy) {
10620 const auto proxy_chain1 = PacResultElementToProxyChain("HTTPS myproxy:70");
10621 const auto proxy_chain2 = PacResultElementToProxyChain("HTTPS myproxy2:70");
10622
10623 session_deps_.proxy_delegate = std::make_unique<TestProxyDelegate>();
10624 auto* proxy_delegate =
10625 static_cast<TestProxyDelegate*>(session_deps_.proxy_delegate.get());
10626 proxy_delegate->set_proxy_chain(proxy_chain1);
10627
10628 HttpRequestInfo request;
10629 request.method = "GET";
10630 request.url = GURL("http://www.example.org/");
10631 // when the no authentication data flag is set.
10632 request.privacy_mode = PRIVACY_MODE_ENABLED;
10633 request.traffic_annotation =
10634 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
10635
10636 // Configure against https proxy server "myproxy:70".
10637 session_deps_.proxy_resolution_service =
10638 ConfiguredProxyResolutionService::CreateFixedForTest(
10639 "https://myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
10640 session_deps_.proxy_resolution_service->SetProxyDelegate(proxy_delegate);
10641 session_deps_.net_log = NetLog::Get();
10642 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
10643
10644 // Since we have proxy, should use full url
10645 MockWrite data_writes1[] = {
10646 MockWrite("GET http://www.example.org/ HTTP/1.1\r\n"
10647 "Host: www.example.org\r\n"
10648 "Proxy-Connection: keep-alive\r\n\r\n"),
10649 };
10650
10651 // The proxy responds to the GET with a 407, using a non-persistent
10652 // connection.
10653 MockRead data_reads1[] = {
10654 // No credentials.
10655 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
10656 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
10657 MockRead("Proxy-Connection: close\r\n"),
10658 MockRead("Content-Length: 0\r\n\r\n"),
10659 };
10660
10661 MockWrite data_writes2[] = {
10662 // After calling trans.RestartWithAuth(), this is the request we should
10663 // be issuing -- the final header line contains the credentials.
10664 MockWrite("GET http://www.example.org/ HTTP/1.1\r\n"
10665 "Host: www.example.org\r\n"
10666 "Proxy-Connection: keep-alive\r\n"
10667 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
10668 };
10669
10670 MockRead data_reads2[] = {
10671 MockRead("HTTP/1.1 200 OK\r\n"),
10672 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
10673 MockRead("Content-Length: 100\r\n\r\n"),
10674 MockRead(SYNCHRONOUS, OK),
10675 };
10676
10677 StaticSocketDataProvider data1(data_reads1, data_writes1);
10678 session_deps_.socket_factory->AddSocketDataProvider(&data1);
10679 StaticSocketDataProvider data2(data_reads2, data_writes2);
10680 session_deps_.socket_factory->AddSocketDataProvider(&data2);
10681
10682 // One per each proxy connection.
10683 SSLSocketDataProvider ssl1(ASYNC, OK);
10684 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl1);
10685 SSLSocketDataProvider ssl2(ASYNC, OK);
10686 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
10687
10688 TestCompletionCallback callback1;
10689
10690 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
10691
10692 int rv = trans.Start(&request, callback1.callback(),
10693 NetLogWithSource::Make(NetLogSourceType::NONE));
10694 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
10695
10696 rv = callback1.WaitForResult();
10697 EXPECT_THAT(rv, IsOk());
10698
10699 LoadTimingInfo load_timing_info;
10700 EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info));
10701 TestLoadTimingNotReused(load_timing_info,
10702 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY);
10703
10704 const HttpResponseInfo* response = trans.GetResponseInfo();
10705 ASSERT_TRUE(response);
10706 ASSERT_TRUE(response->headers);
10707 EXPECT_EQ(407, response->headers->response_code());
10708 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
10709 EXPECT_TRUE(CheckBasicSecureProxyAuth(response->auth_challenge));
10710 EXPECT_FALSE(response->did_use_http_auth);
10711 EXPECT_EQ(proxy_chain1, response->proxy_chain);
10712
10713 TestCompletionCallback callback2;
10714
10715 // Configure against https proxy server "myproxy2:70".
10716 proxy_delegate->set_proxy_chain(proxy_chain2);
10717
10718 rv = trans.RestartWithAuth(AuthCredentials(kFoo, kBar), callback2.callback());
10719 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
10720
10721 rv = callback2.WaitForResult();
10722 EXPECT_THAT(rv, IsOk());
10723
10724 load_timing_info = LoadTimingInfo();
10725 EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info));
10726 TestLoadTimingNotReused(load_timing_info,
10727 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY);
10728
10729 response = trans.GetResponseInfo();
10730 ASSERT_TRUE(response);
10731
10732 EXPECT_TRUE(response->headers->IsKeepAlive());
10733 EXPECT_EQ(200, response->headers->response_code());
10734 EXPECT_EQ(100, response->headers->GetContentLength());
10735 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
10736 EXPECT_TRUE(response->did_use_http_auth);
10737 EXPECT_EQ(proxy_chain2, response->proxy_chain);
10738
10739 // The password prompt info should not be set.
10740 EXPECT_FALSE(response->auth_challenge.has_value());
10741 }
10742
10743 // Test the challenge-response-retry sequence through an HTTPS Proxy over a
10744 // connection that requires a restart, with a change to a direct connection
10745 // occurring over the restart.
TEST_P(HttpNetworkTransactionTest,HttpsProxyAuthRetryNoKeepAliveChangeToDirect)10746 TEST_P(HttpNetworkTransactionTest,
10747 HttpsProxyAuthRetryNoKeepAliveChangeToDirect) {
10748 const auto proxy_chain = PacResultElementToProxyChain("HTTPS myproxy:70");
10749 const auto direct = ProxyChain::Direct();
10750
10751 session_deps_.proxy_delegate = std::make_unique<TestProxyDelegate>();
10752 auto* proxy_delegate =
10753 static_cast<TestProxyDelegate*>(session_deps_.proxy_delegate.get());
10754 proxy_delegate->set_proxy_chain(proxy_chain);
10755
10756 HttpRequestInfo request;
10757 request.method = "GET";
10758 request.url = GURL("http://www.example.org/");
10759 // when the no authentication data flag is set.
10760 request.privacy_mode = PRIVACY_MODE_ENABLED;
10761 request.traffic_annotation =
10762 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
10763
10764 // Configure against https proxy server "myproxy:70".
10765 session_deps_.proxy_resolution_service =
10766 ConfiguredProxyResolutionService::CreateFixedForTest(
10767 "https://myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
10768 session_deps_.proxy_resolution_service->SetProxyDelegate(proxy_delegate);
10769 session_deps_.net_log = NetLog::Get();
10770 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
10771
10772 // Since we have proxy, should use full url
10773 MockWrite data_writes1[] = {
10774 MockWrite("GET http://www.example.org/ HTTP/1.1\r\n"
10775 "Host: www.example.org\r\n"
10776 "Proxy-Connection: keep-alive\r\n\r\n"),
10777 };
10778
10779 // The proxy responds to the GET with a 407, using a non-persistent
10780 // connection.
10781 MockRead data_reads1[] = {
10782 // No credentials.
10783 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
10784 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
10785 MockRead("Proxy-Connection: close\r\n"),
10786 MockRead("Content-Length: 0\r\n\r\n"),
10787 };
10788
10789 MockWrite data_writes2[] = {
10790 // After calling trans.RestartWithAuth(), this is the request we should
10791 // be issuing.
10792 MockWrite("GET / HTTP/1.1\r\n"
10793 "Host: www.example.org\r\n"
10794 "Connection: keep-alive\r\n\r\n"),
10795 };
10796
10797 MockRead data_reads2[] = {
10798 MockRead("HTTP/1.1 200 OK\r\n"),
10799 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
10800 MockRead("Content-Length: 100\r\n\r\n"),
10801 MockRead(SYNCHRONOUS, OK),
10802 };
10803
10804 StaticSocketDataProvider data1(data_reads1, data_writes1);
10805 session_deps_.socket_factory->AddSocketDataProvider(&data1);
10806 StaticSocketDataProvider data2(data_reads2, data_writes2);
10807 session_deps_.socket_factory->AddSocketDataProvider(&data2);
10808
10809 // One per each connection.
10810 SSLSocketDataProvider ssl1(ASYNC, OK);
10811 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl1);
10812 SSLSocketDataProvider ssl2(ASYNC, OK);
10813 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
10814
10815 TestCompletionCallback callback1;
10816
10817 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
10818
10819 int rv = trans.Start(&request, callback1.callback(),
10820 NetLogWithSource::Make(NetLogSourceType::NONE));
10821 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
10822
10823 rv = callback1.WaitForResult();
10824 EXPECT_THAT(rv, IsOk());
10825
10826 LoadTimingInfo load_timing_info;
10827 EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info));
10828 TestLoadTimingNotReused(load_timing_info,
10829 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY);
10830
10831 const HttpResponseInfo* response = trans.GetResponseInfo();
10832 ASSERT_TRUE(response);
10833 ASSERT_TRUE(response->headers);
10834 EXPECT_EQ(407, response->headers->response_code());
10835 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
10836 EXPECT_TRUE(CheckBasicSecureProxyAuth(response->auth_challenge));
10837 EXPECT_FALSE(response->did_use_http_auth);
10838 EXPECT_EQ(proxy_chain, response->proxy_chain);
10839
10840 TestCompletionCallback callback2;
10841
10842 // Configure to use a direct connection.
10843 proxy_delegate->set_proxy_chain(direct);
10844
10845 rv = trans.RestartWithAuth(AuthCredentials(kFoo, kBar), callback2.callback());
10846 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
10847
10848 rv = callback2.WaitForResult();
10849 EXPECT_THAT(rv, IsOk());
10850
10851 load_timing_info = LoadTimingInfo();
10852 EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info));
10853 TestLoadTimingNotReused(load_timing_info, CONNECT_TIMING_HAS_DNS_TIMES);
10854
10855 response = trans.GetResponseInfo();
10856 ASSERT_TRUE(response);
10857
10858 EXPECT_TRUE(response->headers->IsKeepAlive());
10859 EXPECT_EQ(200, response->headers->response_code());
10860 EXPECT_EQ(100, response->headers->GetContentLength());
10861 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
10862 EXPECT_FALSE(response->did_use_http_auth);
10863 EXPECT_EQ(direct, response->proxy_chain);
10864
10865 // The password prompt info should not be set.
10866 EXPECT_FALSE(response->auth_challenge.has_value());
10867 }
10868
ConnectStatusHelperWithExpectedStatus(const MockRead & status,int expected_status)10869 void HttpNetworkTransactionTestBase::ConnectStatusHelperWithExpectedStatus(
10870 const MockRead& status,
10871 int expected_status) {
10872 HttpRequestInfo request;
10873 request.method = "GET";
10874 request.url = GURL("https://www.example.org/");
10875 request.traffic_annotation =
10876 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
10877
10878 // Configure against proxy server "myproxy:70".
10879 session_deps_.proxy_resolution_service =
10880 ConfiguredProxyResolutionService::CreateFixedForTest(
10881 "myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
10882 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
10883
10884 // Since we have proxy, should try to establish tunnel.
10885 MockWrite data_writes[] = {
10886 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
10887 "Host: www.example.org:443\r\n"
10888 "Proxy-Connection: keep-alive\r\n\r\n"),
10889 };
10890
10891 MockRead data_reads[] = {
10892 status,
10893 MockRead("Content-Length: 10\r\n\r\n"),
10894 // No response body because the test stops reading here.
10895 MockRead(SYNCHRONOUS, ERR_UNEXPECTED),
10896 };
10897
10898 StaticSocketDataProvider data(data_reads, data_writes);
10899 session_deps_.socket_factory->AddSocketDataProvider(&data);
10900
10901 TestCompletionCallback callback;
10902
10903 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
10904
10905 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
10906 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
10907
10908 rv = callback.WaitForResult();
10909 EXPECT_EQ(expected_status, rv);
10910 }
10911
ConnectStatusHelper(const MockRead & status)10912 void HttpNetworkTransactionTestBase::ConnectStatusHelper(
10913 const MockRead& status) {
10914 ConnectStatusHelperWithExpectedStatus(status, ERR_TUNNEL_CONNECTION_FAILED);
10915 }
10916
TEST_P(HttpNetworkTransactionTest,ConnectStatus100)10917 TEST_P(HttpNetworkTransactionTest, ConnectStatus100) {
10918 ConnectStatusHelper(MockRead("HTTP/1.1 100 Continue\r\n"));
10919 }
10920
TEST_P(HttpNetworkTransactionTest,ConnectStatus101)10921 TEST_P(HttpNetworkTransactionTest, ConnectStatus101) {
10922 ConnectStatusHelper(MockRead("HTTP/1.1 101 Switching Protocols\r\n"));
10923 }
10924
TEST_P(HttpNetworkTransactionTest,ConnectStatus201)10925 TEST_P(HttpNetworkTransactionTest, ConnectStatus201) {
10926 ConnectStatusHelper(MockRead("HTTP/1.1 201 Created\r\n"));
10927 }
10928
TEST_P(HttpNetworkTransactionTest,ConnectStatus202)10929 TEST_P(HttpNetworkTransactionTest, ConnectStatus202) {
10930 ConnectStatusHelper(MockRead("HTTP/1.1 202 Accepted\r\n"));
10931 }
10932
TEST_P(HttpNetworkTransactionTest,ConnectStatus203)10933 TEST_P(HttpNetworkTransactionTest, ConnectStatus203) {
10934 ConnectStatusHelper(
10935 MockRead("HTTP/1.1 203 Non-Authoritative Information\r\n"));
10936 }
10937
TEST_P(HttpNetworkTransactionTest,ConnectStatus204)10938 TEST_P(HttpNetworkTransactionTest, ConnectStatus204) {
10939 ConnectStatusHelper(MockRead("HTTP/1.1 204 No Content\r\n"));
10940 }
10941
TEST_P(HttpNetworkTransactionTest,ConnectStatus205)10942 TEST_P(HttpNetworkTransactionTest, ConnectStatus205) {
10943 ConnectStatusHelper(MockRead("HTTP/1.1 205 Reset Content\r\n"));
10944 }
10945
TEST_P(HttpNetworkTransactionTest,ConnectStatus206)10946 TEST_P(HttpNetworkTransactionTest, ConnectStatus206) {
10947 ConnectStatusHelper(MockRead("HTTP/1.1 206 Partial Content\r\n"));
10948 }
10949
TEST_P(HttpNetworkTransactionTest,ConnectStatus300)10950 TEST_P(HttpNetworkTransactionTest, ConnectStatus300) {
10951 ConnectStatusHelper(MockRead("HTTP/1.1 300 Multiple Choices\r\n"));
10952 }
10953
TEST_P(HttpNetworkTransactionTest,ConnectStatus301)10954 TEST_P(HttpNetworkTransactionTest, ConnectStatus301) {
10955 ConnectStatusHelper(MockRead("HTTP/1.1 301 Moved Permanently\r\n"));
10956 }
10957
TEST_P(HttpNetworkTransactionTest,ConnectStatus302)10958 TEST_P(HttpNetworkTransactionTest, ConnectStatus302) {
10959 ConnectStatusHelper(MockRead("HTTP/1.1 302 Found\r\n"));
10960 }
10961
TEST_P(HttpNetworkTransactionTest,ConnectStatus303)10962 TEST_P(HttpNetworkTransactionTest, ConnectStatus303) {
10963 ConnectStatusHelper(MockRead("HTTP/1.1 303 See Other\r\n"));
10964 }
10965
TEST_P(HttpNetworkTransactionTest,ConnectStatus304)10966 TEST_P(HttpNetworkTransactionTest, ConnectStatus304) {
10967 ConnectStatusHelper(MockRead("HTTP/1.1 304 Not Modified\r\n"));
10968 }
10969
TEST_P(HttpNetworkTransactionTest,ConnectStatus305)10970 TEST_P(HttpNetworkTransactionTest, ConnectStatus305) {
10971 ConnectStatusHelper(MockRead("HTTP/1.1 305 Use Proxy\r\n"));
10972 }
10973
TEST_P(HttpNetworkTransactionTest,ConnectStatus306)10974 TEST_P(HttpNetworkTransactionTest, ConnectStatus306) {
10975 ConnectStatusHelper(MockRead("HTTP/1.1 306\r\n"));
10976 }
10977
TEST_P(HttpNetworkTransactionTest,ConnectStatus307)10978 TEST_P(HttpNetworkTransactionTest, ConnectStatus307) {
10979 ConnectStatusHelper(MockRead("HTTP/1.1 307 Temporary Redirect\r\n"));
10980 }
10981
TEST_P(HttpNetworkTransactionTest,ConnectStatus308)10982 TEST_P(HttpNetworkTransactionTest, ConnectStatus308) {
10983 ConnectStatusHelper(MockRead("HTTP/1.1 308 Permanent Redirect\r\n"));
10984 }
10985
TEST_P(HttpNetworkTransactionTest,ConnectStatus400)10986 TEST_P(HttpNetworkTransactionTest, ConnectStatus400) {
10987 ConnectStatusHelper(MockRead("HTTP/1.1 400 Bad Request\r\n"));
10988 }
10989
TEST_P(HttpNetworkTransactionTest,ConnectStatus401)10990 TEST_P(HttpNetworkTransactionTest, ConnectStatus401) {
10991 ConnectStatusHelper(MockRead("HTTP/1.1 401 Unauthorized\r\n"));
10992 }
10993
TEST_P(HttpNetworkTransactionTest,ConnectStatus402)10994 TEST_P(HttpNetworkTransactionTest, ConnectStatus402) {
10995 ConnectStatusHelper(MockRead("HTTP/1.1 402 Payment Required\r\n"));
10996 }
10997
TEST_P(HttpNetworkTransactionTest,ConnectStatus403)10998 TEST_P(HttpNetworkTransactionTest, ConnectStatus403) {
10999 ConnectStatusHelper(MockRead("HTTP/1.1 403 Forbidden\r\n"));
11000 }
11001
TEST_P(HttpNetworkTransactionTest,ConnectStatus404)11002 TEST_P(HttpNetworkTransactionTest, ConnectStatus404) {
11003 ConnectStatusHelper(MockRead("HTTP/1.1 404 Not Found\r\n"));
11004 }
11005
TEST_P(HttpNetworkTransactionTest,ConnectStatus405)11006 TEST_P(HttpNetworkTransactionTest, ConnectStatus405) {
11007 ConnectStatusHelper(MockRead("HTTP/1.1 405 Method Not Allowed\r\n"));
11008 }
11009
TEST_P(HttpNetworkTransactionTest,ConnectStatus406)11010 TEST_P(HttpNetworkTransactionTest, ConnectStatus406) {
11011 ConnectStatusHelper(MockRead("HTTP/1.1 406 Not Acceptable\r\n"));
11012 }
11013
TEST_P(HttpNetworkTransactionTest,ConnectStatus407)11014 TEST_P(HttpNetworkTransactionTest, ConnectStatus407) {
11015 ConnectStatusHelperWithExpectedStatus(
11016 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
11017 ERR_PROXY_AUTH_UNSUPPORTED);
11018 }
11019
TEST_P(HttpNetworkTransactionTest,ConnectStatus408)11020 TEST_P(HttpNetworkTransactionTest, ConnectStatus408) {
11021 ConnectStatusHelper(MockRead("HTTP/1.1 408 Request Timeout\r\n"));
11022 }
11023
TEST_P(HttpNetworkTransactionTest,ConnectStatus409)11024 TEST_P(HttpNetworkTransactionTest, ConnectStatus409) {
11025 ConnectStatusHelper(MockRead("HTTP/1.1 409 Conflict\r\n"));
11026 }
11027
TEST_P(HttpNetworkTransactionTest,ConnectStatus410)11028 TEST_P(HttpNetworkTransactionTest, ConnectStatus410) {
11029 ConnectStatusHelper(MockRead("HTTP/1.1 410 Gone\r\n"));
11030 }
11031
TEST_P(HttpNetworkTransactionTest,ConnectStatus411)11032 TEST_P(HttpNetworkTransactionTest, ConnectStatus411) {
11033 ConnectStatusHelper(MockRead("HTTP/1.1 411 Length Required\r\n"));
11034 }
11035
TEST_P(HttpNetworkTransactionTest,ConnectStatus412)11036 TEST_P(HttpNetworkTransactionTest, ConnectStatus412) {
11037 ConnectStatusHelper(MockRead("HTTP/1.1 412 Precondition Failed\r\n"));
11038 }
11039
TEST_P(HttpNetworkTransactionTest,ConnectStatus413)11040 TEST_P(HttpNetworkTransactionTest, ConnectStatus413) {
11041 ConnectStatusHelper(MockRead("HTTP/1.1 413 Request Entity Too Large\r\n"));
11042 }
11043
TEST_P(HttpNetworkTransactionTest,ConnectStatus414)11044 TEST_P(HttpNetworkTransactionTest, ConnectStatus414) {
11045 ConnectStatusHelper(MockRead("HTTP/1.1 414 Request-URI Too Long\r\n"));
11046 }
11047
TEST_P(HttpNetworkTransactionTest,ConnectStatus415)11048 TEST_P(HttpNetworkTransactionTest, ConnectStatus415) {
11049 ConnectStatusHelper(MockRead("HTTP/1.1 415 Unsupported Media Type\r\n"));
11050 }
11051
TEST_P(HttpNetworkTransactionTest,ConnectStatus416)11052 TEST_P(HttpNetworkTransactionTest, ConnectStatus416) {
11053 ConnectStatusHelper(
11054 MockRead("HTTP/1.1 416 Requested Range Not Satisfiable\r\n"));
11055 }
11056
TEST_P(HttpNetworkTransactionTest,ConnectStatus417)11057 TEST_P(HttpNetworkTransactionTest, ConnectStatus417) {
11058 ConnectStatusHelper(MockRead("HTTP/1.1 417 Expectation Failed\r\n"));
11059 }
11060
TEST_P(HttpNetworkTransactionTest,ConnectStatus500)11061 TEST_P(HttpNetworkTransactionTest, ConnectStatus500) {
11062 ConnectStatusHelper(MockRead("HTTP/1.1 500 Internal Server Error\r\n"));
11063 }
11064
TEST_P(HttpNetworkTransactionTest,ConnectStatus501)11065 TEST_P(HttpNetworkTransactionTest, ConnectStatus501) {
11066 ConnectStatusHelper(MockRead("HTTP/1.1 501 Not Implemented\r\n"));
11067 }
11068
TEST_P(HttpNetworkTransactionTest,ConnectStatus502)11069 TEST_P(HttpNetworkTransactionTest, ConnectStatus502) {
11070 ConnectStatusHelper(MockRead("HTTP/1.1 502 Bad Gateway\r\n"));
11071 }
11072
TEST_P(HttpNetworkTransactionTest,ConnectStatus503)11073 TEST_P(HttpNetworkTransactionTest, ConnectStatus503) {
11074 ConnectStatusHelper(MockRead("HTTP/1.1 503 Service Unavailable\r\n"));
11075 }
11076
TEST_P(HttpNetworkTransactionTest,ConnectStatus504)11077 TEST_P(HttpNetworkTransactionTest, ConnectStatus504) {
11078 ConnectStatusHelper(MockRead("HTTP/1.1 504 Gateway Timeout\r\n"));
11079 }
11080
TEST_P(HttpNetworkTransactionTest,ConnectStatus505)11081 TEST_P(HttpNetworkTransactionTest, ConnectStatus505) {
11082 ConnectStatusHelper(MockRead("HTTP/1.1 505 HTTP Version Not Supported\r\n"));
11083 }
11084
11085 // Test the flow when both the proxy server AND origin server require
11086 // authentication. Again, this uses basic auth for both since that is
11087 // the simplest to mock.
TEST_P(HttpNetworkTransactionTest,BasicAuthProxyThenServer)11088 TEST_P(HttpNetworkTransactionTest, BasicAuthProxyThenServer) {
11089 HttpRequestInfo request;
11090 request.method = "GET";
11091 request.url = GURL("http://www.example.org/");
11092 request.traffic_annotation =
11093 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
11094
11095 // Configure against proxy server "myproxy:70".
11096 session_deps_.proxy_resolution_service =
11097 ConfiguredProxyResolutionService::CreateFixedForTest(
11098 "myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
11099 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
11100
11101 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
11102
11103 MockWrite data_writes1[] = {
11104 MockWrite("GET http://www.example.org/ HTTP/1.1\r\n"
11105 "Host: www.example.org\r\n"
11106 "Proxy-Connection: keep-alive\r\n\r\n"),
11107 };
11108
11109 MockRead data_reads1[] = {
11110 MockRead("HTTP/1.0 407 Unauthorized\r\n"),
11111 // Give a couple authenticate options (only the middle one is actually
11112 // supported).
11113 MockRead("Proxy-Authenticate: Basic invalid\r\n"), // Malformed.
11114 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
11115 MockRead("Proxy-Authenticate: UNSUPPORTED realm=\"FOO\"\r\n"),
11116 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
11117 // Large content-length -- won't matter, as connection will be reset.
11118 MockRead("Content-Length: 10000\r\n\r\n"),
11119 MockRead(SYNCHRONOUS, ERR_FAILED),
11120 };
11121
11122 // After calling trans.RestartWithAuth() the first time, this is the
11123 // request we should be issuing -- the final header line contains the
11124 // proxy's credentials.
11125 MockWrite data_writes2[] = {
11126 MockWrite("GET http://www.example.org/ HTTP/1.1\r\n"
11127 "Host: www.example.org\r\n"
11128 "Proxy-Connection: keep-alive\r\n"
11129 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
11130 };
11131
11132 // Now the proxy server lets the request pass through to origin server.
11133 // The origin server responds with a 401.
11134 MockRead data_reads2[] = {
11135 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
11136 // Note: We are using the same realm-name as the proxy server. This is
11137 // completely valid, as realms are unique across hosts.
11138 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
11139 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
11140 MockRead("Content-Length: 2000\r\n\r\n"),
11141 MockRead(SYNCHRONOUS, ERR_FAILED), // Won't be reached.
11142 };
11143
11144 // After calling trans.RestartWithAuth() the second time, we should send
11145 // the credentials for both the proxy and origin server.
11146 MockWrite data_writes3[] = {
11147 MockWrite("GET http://www.example.org/ HTTP/1.1\r\n"
11148 "Host: www.example.org\r\n"
11149 "Proxy-Connection: keep-alive\r\n"
11150 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n"
11151 "Authorization: Basic Zm9vMjpiYXIy\r\n\r\n"),
11152 };
11153
11154 // Lastly we get the desired content.
11155 MockRead data_reads3[] = {
11156 MockRead("HTTP/1.0 200 OK\r\n"),
11157 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
11158 MockRead("Content-Length: 100\r\n\r\n"),
11159 MockRead(SYNCHRONOUS, OK),
11160 };
11161
11162 StaticSocketDataProvider data1(data_reads1, data_writes1);
11163 StaticSocketDataProvider data2(data_reads2, data_writes2);
11164 StaticSocketDataProvider data3(data_reads3, data_writes3);
11165 session_deps_.socket_factory->AddSocketDataProvider(&data1);
11166 session_deps_.socket_factory->AddSocketDataProvider(&data2);
11167 session_deps_.socket_factory->AddSocketDataProvider(&data3);
11168
11169 TestCompletionCallback callback1;
11170
11171 int rv = trans.Start(&request, callback1.callback(), NetLogWithSource());
11172 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
11173
11174 rv = callback1.WaitForResult();
11175 EXPECT_THAT(rv, IsOk());
11176
11177 const HttpResponseInfo* response = trans.GetResponseInfo();
11178 ASSERT_TRUE(response);
11179 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge));
11180
11181 TestCompletionCallback callback2;
11182
11183 rv = trans.RestartWithAuth(AuthCredentials(kFoo, kBar), callback2.callback());
11184 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
11185
11186 rv = callback2.WaitForResult();
11187 EXPECT_THAT(rv, IsOk());
11188
11189 response = trans.GetResponseInfo();
11190 ASSERT_TRUE(response);
11191 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge));
11192
11193 TestCompletionCallback callback3;
11194
11195 rv = trans.RestartWithAuth(AuthCredentials(kFoo2, kBar2),
11196 callback3.callback());
11197 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
11198
11199 rv = callback3.WaitForResult();
11200 EXPECT_THAT(rv, IsOk());
11201
11202 response = trans.GetResponseInfo();
11203 EXPECT_FALSE(response->auth_challenge.has_value());
11204 EXPECT_EQ(100, response->headers->GetContentLength());
11205 }
11206
11207 // For the NTLM implementation using SSPI, we skip the NTLM tests since we
11208 // can't hook into its internals to cause it to generate predictable NTLM
11209 // authorization headers.
11210 #if defined(NTLM_PORTABLE)
11211 // The NTLM authentication unit tests are based on known test data from the
11212 // [MS-NLMP] Specification [1]. These tests are primarily of the authentication
11213 // flow rather than the implementation of the NTLM protocol. See net/ntlm
11214 // for the implementation and testing of the protocol.
11215 //
11216 // [1] https://msdn.microsoft.com/en-us/library/cc236621.aspx
11217
11218 // Enter the correct password and authenticate successfully.
TEST_P(HttpNetworkTransactionTest,NTLMAuthV2)11219 TEST_P(HttpNetworkTransactionTest, NTLMAuthV2) {
11220 HttpRequestInfo request;
11221 request.method = "GET";
11222 request.url = GURL("https://server/kids/login.aspx");
11223 request.traffic_annotation =
11224 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
11225
11226 // Ensure load is not disrupted by flags which suppress behaviour specific
11227 // to other auth schemes.
11228 request.load_flags = LOAD_DO_NOT_USE_EMBEDDED_IDENTITY;
11229
11230 HttpAuthNtlmMechanism::ScopedProcSetter proc_setter(
11231 MockGetMSTime, MockGenerateRandom, MockGetHostName);
11232 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
11233
11234 // Generate the NTLM messages based on known test data.
11235 std::string negotiate_msg = base::Base64Encode(std::string_view(
11236 reinterpret_cast<const char*>(ntlm::test::kExpectedNegotiateMsg),
11237 std::size(ntlm::test::kExpectedNegotiateMsg)));
11238 std::string challenge_msg = base::Base64Encode(std::string_view(
11239 reinterpret_cast<const char*>(ntlm::test::kChallengeMsgFromSpecV2),
11240 std::size(ntlm::test::kChallengeMsgFromSpecV2)));
11241 std::string authenticate_msg = base::Base64Encode(std::string_view(
11242 reinterpret_cast<const char*>(
11243 ntlm::test::kExpectedAuthenticateMsgEmptyChannelBindingsV2),
11244 std::size(ntlm::test::kExpectedAuthenticateMsgEmptyChannelBindingsV2)));
11245
11246 MockWrite data_writes1[] = {
11247 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
11248 "Host: server\r\n"
11249 "Connection: keep-alive\r\n\r\n"),
11250 };
11251
11252 MockRead data_reads1[] = {
11253 MockRead("HTTP/1.1 401 Access Denied\r\n"),
11254 // Negotiate and NTLM are often requested together. However, we only want
11255 // to test NTLM. Since Negotiate is preferred over NTLM, we have to skip
11256 // the header that requests Negotiate for this test.
11257 MockRead("WWW-Authenticate: NTLM\r\n"), MockRead("Connection: close\r\n"),
11258 MockRead("Content-Length: 42\r\n"),
11259 MockRead("Content-Type: text/html\r\n\r\n"),
11260 // Missing content -- won't matter, as connection will be reset.
11261 };
11262
11263 MockWrite data_writes2[] = {
11264 // After restarting with a null identity, this is the
11265 // request we should be issuing -- the final header line contains a Type
11266 // 1 message.
11267 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
11268 "Host: server\r\n"
11269 "Connection: keep-alive\r\n"
11270 "Authorization: NTLM "),
11271 MockWrite(negotiate_msg.c_str()),
11272 MockWrite("\r\n\r\n"),
11273
11274 // After calling trans.RestartWithAuth(), we should send a Type 3 message
11275 // (using correct credentials). The second request continues on the
11276 // same connection.
11277 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
11278 "Host: server\r\n"
11279 "Connection: keep-alive\r\n"
11280 "Authorization: NTLM "),
11281 MockWrite(authenticate_msg.c_str()),
11282 MockWrite("\r\n\r\n"),
11283 };
11284
11285 MockRead data_reads2[] = {
11286 // The origin server responds with a Type 2 message.
11287 MockRead("HTTP/1.1 401 Access Denied\r\n"),
11288 MockRead("WWW-Authenticate: NTLM "),
11289 MockRead(challenge_msg.c_str()),
11290 MockRead("\r\n"),
11291 MockRead("Content-Length: 42\r\n"),
11292 MockRead("Content-Type: text/html\r\n\r\n"),
11293 MockRead("You are not authorized to view this page\r\n"),
11294
11295 // Lastly we get the desired content.
11296 MockRead("HTTP/1.1 200 OK\r\n"),
11297 MockRead("Content-Type: text/html; charset=utf-8\r\n"),
11298 MockRead("Content-Length: 14\r\n\r\n"),
11299 MockRead("Please Login\r\n"),
11300 };
11301
11302 StaticSocketDataProvider data1(data_reads1, data_writes1);
11303 StaticSocketDataProvider data2(data_reads2, data_writes2);
11304 session_deps_.socket_factory->AddSocketDataProvider(&data1);
11305 session_deps_.socket_factory->AddSocketDataProvider(&data2);
11306
11307 SSLSocketDataProvider ssl1(ASYNC, OK);
11308 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl1);
11309 SSLSocketDataProvider ssl2(ASYNC, OK);
11310 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
11311
11312 TestCompletionCallback callback1;
11313
11314 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
11315
11316 int rv = trans.Start(&request, callback1.callback(), NetLogWithSource());
11317 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
11318
11319 rv = callback1.WaitForResult();
11320 EXPECT_THAT(rv, IsOk());
11321
11322 EXPECT_FALSE(trans.IsReadyToRestartForAuth());
11323
11324 const HttpResponseInfo* response = trans.GetResponseInfo();
11325 ASSERT_TRUE(response);
11326 EXPECT_TRUE(CheckNTLMServerAuth(response->auth_challenge));
11327
11328 TestCompletionCallback callback2;
11329
11330 rv = trans.RestartWithAuth(
11331 AuthCredentials(ntlm::test::kDomainUserCombined, ntlm::test::kPassword),
11332 callback2.callback());
11333 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
11334
11335 rv = callback2.WaitForResult();
11336 EXPECT_THAT(rv, IsOk());
11337
11338 EXPECT_TRUE(trans.IsReadyToRestartForAuth());
11339
11340 response = trans.GetResponseInfo();
11341 ASSERT_TRUE(response);
11342 EXPECT_FALSE(response->auth_challenge.has_value());
11343
11344 TestCompletionCallback callback3;
11345
11346 rv = trans.RestartWithAuth(AuthCredentials(), callback3.callback());
11347 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
11348
11349 rv = callback3.WaitForResult();
11350 EXPECT_THAT(rv, IsOk());
11351
11352 response = trans.GetResponseInfo();
11353 ASSERT_TRUE(response);
11354 EXPECT_FALSE(response->auth_challenge.has_value());
11355 EXPECT_EQ(14, response->headers->GetContentLength());
11356
11357 std::string response_data;
11358 rv = ReadTransaction(&trans, &response_data);
11359 EXPECT_THAT(rv, IsOk());
11360 EXPECT_EQ("Please Login\r\n", response_data);
11361
11362 EXPECT_TRUE(data1.AllReadDataConsumed());
11363 EXPECT_TRUE(data1.AllWriteDataConsumed());
11364 EXPECT_TRUE(data2.AllReadDataConsumed());
11365 EXPECT_TRUE(data2.AllWriteDataConsumed());
11366 }
11367
11368 // Enter a wrong password, and then the correct one.
TEST_P(HttpNetworkTransactionTest,NTLMAuthV2WrongThenRightPassword)11369 TEST_P(HttpNetworkTransactionTest, NTLMAuthV2WrongThenRightPassword) {
11370 HttpRequestInfo request;
11371 request.method = "GET";
11372 request.url = GURL("https://server/kids/login.aspx");
11373 request.traffic_annotation =
11374 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
11375
11376 HttpAuthNtlmMechanism::ScopedProcSetter proc_setter(
11377 MockGetMSTime, MockGenerateRandom, MockGetHostName);
11378 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
11379
11380 // Generate the NTLM messages based on known test data.
11381 std::string negotiate_msg = base::Base64Encode(std::string_view(
11382 reinterpret_cast<const char*>(ntlm::test::kExpectedNegotiateMsg),
11383 std::size(ntlm::test::kExpectedNegotiateMsg)));
11384 std::string challenge_msg = base::Base64Encode(std::string_view(
11385 reinterpret_cast<const char*>(ntlm::test::kChallengeMsgFromSpecV2),
11386 std::size(ntlm::test::kChallengeMsgFromSpecV2)));
11387 std::string authenticate_msg = base::Base64Encode(std::string_view(
11388 reinterpret_cast<const char*>(
11389 ntlm::test::kExpectedAuthenticateMsgEmptyChannelBindingsV2),
11390 std::size(ntlm::test::kExpectedAuthenticateMsgEmptyChannelBindingsV2)));
11391
11392 // The authenticate message when |kWrongPassword| is sent.
11393 std::string wrong_password_authenticate_msg(
11394 "TlRMTVNTUAADAAAAGAAYAFgAAACKAIoAcAAAAAwADAD6AAAACAAIAAYBAAAQABAADgEAAAAA"
11395 "AABYAAAAA4IIAAAAAAAAAAAAAPknEYqtJQtusopDRSfYzAAAAAAAAAAAAAAAAAAAAAAAAAAA"
11396 "AAAAAOtVz38osnFdRRggUQHUJ3EBAQAAAAAAAIALyP0A1NIBqqqqqqqqqqoAAAAAAgAMAEQA"
11397 "bwBtAGEAaQBuAAEADABTAGUAcgB2AGUAcgAGAAQAAgAAAAoAEAAAAAAAAAAAAAAAAAAAAAAA"
11398 "CQAWAEgAVABUAFAALwBzAGUAcgB2AGUAcgAAAAAAAAAAAEQAbwBtAGEAaQBuAFUAcwBlAHIA"
11399 "QwBPAE0AUABVAFQARQBSAA==");
11400
11401 // Sanity check that it's the same length as the correct authenticate message
11402 // and that it's different.
11403 ASSERT_EQ(authenticate_msg.length(),
11404 wrong_password_authenticate_msg.length());
11405 ASSERT_NE(authenticate_msg, wrong_password_authenticate_msg);
11406
11407 MockWrite data_writes1[] = {
11408 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
11409 "Host: server\r\n"
11410 "Connection: keep-alive\r\n\r\n"),
11411 };
11412
11413 MockRead data_reads1[] = {
11414 MockRead("HTTP/1.1 401 Access Denied\r\n"),
11415 // Negotiate and NTLM are often requested together. However, we only want
11416 // to test NTLM. Since Negotiate is preferred over NTLM, we have to skip
11417 // the header that requests Negotiate for this test.
11418 MockRead("WWW-Authenticate: NTLM\r\n"), MockRead("Connection: close\r\n"),
11419 MockRead("Content-Length: 42\r\n"),
11420 MockRead("Content-Type: text/html\r\n\r\n"),
11421 // Missing content -- won't matter, as connection will be reset.
11422 };
11423
11424 MockWrite data_writes2[] = {
11425 // After restarting with a null identity, this is the
11426 // request we should be issuing -- the final header line contains a Type
11427 // 1 message.
11428 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
11429 "Host: server\r\n"
11430 "Connection: keep-alive\r\n"
11431 "Authorization: NTLM "),
11432 MockWrite(negotiate_msg.c_str()),
11433 MockWrite("\r\n\r\n"),
11434
11435 // After calling trans.RestartWithAuth(), we should send a Type 3 message
11436 // (using incorrect credentials). The second request continues on the
11437 // same connection.
11438 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
11439 "Host: server\r\n"
11440 "Connection: keep-alive\r\n"
11441 "Authorization: NTLM "),
11442 MockWrite(wrong_password_authenticate_msg.c_str()),
11443 MockWrite("\r\n\r\n"),
11444 };
11445
11446 MockRead data_reads2[] = {
11447 // The origin server responds with a Type 2 message.
11448 MockRead("HTTP/1.1 401 Access Denied\r\n"),
11449 MockRead("WWW-Authenticate: NTLM "), MockRead(challenge_msg.c_str()),
11450 MockRead("\r\n"), MockRead("Content-Length: 42\r\n"),
11451 MockRead("Content-Type: text/html\r\n\r\n"),
11452 MockRead("You are not authorized to view this page\r\n"),
11453
11454 // Wrong password.
11455 MockRead("HTTP/1.1 401 Access Denied\r\n"),
11456 MockRead("WWW-Authenticate: NTLM\r\n"), MockRead("Connection: close\r\n"),
11457 MockRead("Content-Length: 42\r\n"),
11458 MockRead("Content-Type: text/html\r\n\r\n"),
11459 // Missing content -- won't matter, as connection will be reset.
11460 };
11461
11462 MockWrite data_writes3[] = {
11463 // After restarting with a null identity, this is the
11464 // request we should be issuing -- the final header line contains a Type
11465 // 1 message.
11466 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
11467 "Host: server\r\n"
11468 "Connection: keep-alive\r\n"
11469 "Authorization: NTLM "),
11470 MockWrite(negotiate_msg.c_str()),
11471 MockWrite("\r\n\r\n"),
11472
11473 // After calling trans.RestartWithAuth(), we should send a Type 3 message
11474 // (the credentials for the origin server). The second request continues
11475 // on the same connection.
11476 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
11477 "Host: server\r\n"
11478 "Connection: keep-alive\r\n"
11479 "Authorization: NTLM "),
11480 MockWrite(authenticate_msg.c_str()),
11481 MockWrite("\r\n\r\n"),
11482 };
11483
11484 MockRead data_reads3[] = {
11485 // The origin server responds with a Type 2 message.
11486 MockRead("HTTP/1.1 401 Access Denied\r\n"),
11487 MockRead("WWW-Authenticate: NTLM "),
11488 MockRead(challenge_msg.c_str()),
11489 MockRead("\r\n"),
11490 MockRead("Content-Length: 42\r\n"),
11491 MockRead("Content-Type: text/html\r\n\r\n"),
11492 MockRead("You are not authorized to view this page\r\n"),
11493
11494 // Lastly we get the desired content.
11495 MockRead("HTTP/1.1 200 OK\r\n"),
11496 MockRead("Content-Type: text/html; charset=utf-8\r\n"),
11497 MockRead("Content-Length: 14\r\n\r\n"),
11498 MockRead("Please Login\r\n"),
11499 };
11500
11501 StaticSocketDataProvider data1(data_reads1, data_writes1);
11502 StaticSocketDataProvider data2(data_reads2, data_writes2);
11503 StaticSocketDataProvider data3(data_reads3, data_writes3);
11504 session_deps_.socket_factory->AddSocketDataProvider(&data1);
11505 session_deps_.socket_factory->AddSocketDataProvider(&data2);
11506 session_deps_.socket_factory->AddSocketDataProvider(&data3);
11507
11508 SSLSocketDataProvider ssl1(ASYNC, OK);
11509 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl1);
11510 SSLSocketDataProvider ssl2(ASYNC, OK);
11511 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
11512 SSLSocketDataProvider ssl3(ASYNC, OK);
11513 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl3);
11514
11515 TestCompletionCallback callback1;
11516
11517 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
11518
11519 int rv = trans.Start(&request, callback1.callback(), NetLogWithSource());
11520 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
11521
11522 rv = callback1.WaitForResult();
11523 EXPECT_THAT(rv, IsOk());
11524
11525 EXPECT_FALSE(trans.IsReadyToRestartForAuth());
11526
11527 const HttpResponseInfo* response = trans.GetResponseInfo();
11528 ASSERT_TRUE(response);
11529 EXPECT_TRUE(CheckNTLMServerAuth(response->auth_challenge));
11530
11531 TestCompletionCallback callback2;
11532
11533 // Enter the wrong password.
11534 rv = trans.RestartWithAuth(
11535 AuthCredentials(ntlm::test::kDomainUserCombined, kWrongPassword),
11536 callback2.callback());
11537 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
11538
11539 rv = callback2.WaitForResult();
11540 EXPECT_THAT(rv, IsOk());
11541
11542 EXPECT_TRUE(trans.IsReadyToRestartForAuth());
11543 TestCompletionCallback callback3;
11544 rv = trans.RestartWithAuth(AuthCredentials(), callback3.callback());
11545 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
11546 rv = callback3.WaitForResult();
11547 EXPECT_THAT(rv, IsOk());
11548 EXPECT_FALSE(trans.IsReadyToRestartForAuth());
11549
11550 response = trans.GetResponseInfo();
11551 ASSERT_TRUE(response);
11552 EXPECT_TRUE(CheckNTLMServerAuth(response->auth_challenge));
11553
11554 TestCompletionCallback callback4;
11555
11556 // Now enter the right password.
11557 rv = trans.RestartWithAuth(
11558 AuthCredentials(ntlm::test::kDomainUserCombined, ntlm::test::kPassword),
11559 callback4.callback());
11560 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
11561
11562 rv = callback4.WaitForResult();
11563 EXPECT_THAT(rv, IsOk());
11564
11565 EXPECT_TRUE(trans.IsReadyToRestartForAuth());
11566
11567 TestCompletionCallback callback5;
11568
11569 // One more roundtrip
11570 rv = trans.RestartWithAuth(AuthCredentials(), callback5.callback());
11571 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
11572
11573 rv = callback5.WaitForResult();
11574 EXPECT_THAT(rv, IsOk());
11575
11576 response = trans.GetResponseInfo();
11577 EXPECT_FALSE(response->auth_challenge.has_value());
11578 EXPECT_EQ(14, response->headers->GetContentLength());
11579
11580 std::string response_data;
11581 rv = ReadTransaction(&trans, &response_data);
11582 EXPECT_THAT(rv, IsOk());
11583 EXPECT_EQ("Please Login\r\n", response_data);
11584
11585 EXPECT_TRUE(data1.AllReadDataConsumed());
11586 EXPECT_TRUE(data1.AllWriteDataConsumed());
11587 EXPECT_TRUE(data2.AllReadDataConsumed());
11588 EXPECT_TRUE(data2.AllWriteDataConsumed());
11589 EXPECT_TRUE(data3.AllReadDataConsumed());
11590 EXPECT_TRUE(data3.AllWriteDataConsumed());
11591 }
11592
11593 // Server requests NTLM authentication, which is not supported over HTTP/2.
11594 // Subsequent request with authorization header should be sent over HTTP/1.1.
TEST_P(HttpNetworkTransactionTest,NTLMOverHttp2)11595 TEST_P(HttpNetworkTransactionTest, NTLMOverHttp2) {
11596 HttpAuthNtlmMechanism::ScopedProcSetter proc_setter(
11597 MockGetMSTime, MockGenerateRandom, MockGetHostName);
11598
11599 const char kUrl[] = "https://server/kids/login.aspx";
11600
11601 HttpRequestInfo request;
11602 request.method = "GET";
11603 request.url = GURL(kUrl);
11604 request.traffic_annotation =
11605 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
11606
11607 // First request without credentials.
11608 spdy::Http2HeaderBlock request_headers0(
11609 spdy_util_.ConstructGetHeaderBlock(kUrl));
11610 spdy::SpdySerializedFrame request0(spdy_util_.ConstructSpdyHeaders(
11611 1, std::move(request_headers0), LOWEST, true));
11612
11613 spdy::Http2HeaderBlock response_headers0;
11614 response_headers0[spdy::kHttp2StatusHeader] = "401";
11615 response_headers0["www-authenticate"] = "NTLM";
11616 spdy::SpdySerializedFrame resp(spdy_util_.ConstructSpdyResponseHeaders(
11617 1, std::move(response_headers0), true));
11618
11619 // Stream 1 is closed.
11620 spdy_util_.UpdateWithStreamDestruction(1);
11621
11622 // Generate the NTLM messages based on known test data.
11623 std::string negotiate_msg = base::Base64Encode(std::string_view(
11624 reinterpret_cast<const char*>(ntlm::test::kExpectedNegotiateMsg),
11625 std::size(ntlm::test::kExpectedNegotiateMsg)));
11626 std::string challenge_msg = base::Base64Encode(std::string_view(
11627 reinterpret_cast<const char*>(ntlm::test::kChallengeMsgFromSpecV2),
11628 std::size(ntlm::test::kChallengeMsgFromSpecV2)));
11629 std::string authenticate_msg = base::Base64Encode(std::string_view(
11630 reinterpret_cast<const char*>(
11631 ntlm::test::kExpectedAuthenticateMsgEmptyChannelBindingsV2),
11632 std::size(ntlm::test::kExpectedAuthenticateMsgEmptyChannelBindingsV2)));
11633
11634 MockWrite writes0[] = {CreateMockWrite(request0, 0)};
11635 MockRead reads0[] = {CreateMockRead(resp, 1),
11636 MockRead(SYNCHRONOUS, ERR_IO_PENDING, 2)};
11637
11638 // Retry yet again using HTTP/1.1.
11639 MockWrite writes1[] = {
11640 // After restarting with a null identity, this is the
11641 // request we should be issuing -- the final header line contains a Type
11642 // 1 message.
11643 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
11644 "Host: server\r\n"
11645 "Connection: keep-alive\r\n"
11646 "Authorization: NTLM "),
11647 MockWrite(negotiate_msg.c_str()),
11648 MockWrite("\r\n\r\n"),
11649
11650 // After calling trans.RestartWithAuth(), we should send a Type 3 message
11651 // (the credentials for the origin server). The second request continues
11652 // on the same connection.
11653 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
11654 "Host: server\r\n"
11655 "Connection: keep-alive\r\n"
11656 "Authorization: NTLM "),
11657 MockWrite(authenticate_msg.c_str()),
11658 MockWrite("\r\n\r\n"),
11659 };
11660
11661 MockRead reads1[] = {
11662 // The origin server responds with a Type 2 message.
11663 MockRead("HTTP/1.1 401 Access Denied\r\n"),
11664 MockRead("WWW-Authenticate: NTLM "),
11665 MockRead(challenge_msg.c_str()),
11666 MockRead("\r\n"),
11667 MockRead("Content-Length: 42\r\n"),
11668 MockRead("Content-Type: text/html\r\n\r\n"),
11669 MockRead("You are not authorized to view this page\r\n"),
11670
11671 // Lastly we get the desired content.
11672 MockRead("HTTP/1.1 200 OK\r\n"),
11673 MockRead("Content-Type: text/html; charset=utf-8\r\n"),
11674 MockRead("Content-Length: 14\r\n\r\n"),
11675 MockRead("Please Login\r\n"),
11676 };
11677 SequencedSocketData data0(reads0, writes0);
11678 StaticSocketDataProvider data1(reads1, writes1);
11679 session_deps_.socket_factory->AddSocketDataProvider(&data0);
11680 session_deps_.socket_factory->AddSocketDataProvider(&data1);
11681
11682 SSLSocketDataProvider ssl0(ASYNC, OK);
11683 ssl0.next_proto = kProtoHTTP2;
11684 ssl0.next_protos_expected_in_ssl_config =
11685 NextProtoVector{kProtoHTTP2, kProtoHTTP11};
11686 SSLSocketDataProvider ssl1(ASYNC, OK);
11687 // When creating the second connection, only HTTP/1.1 should be allowed.
11688 ssl1.next_protos_expected_in_ssl_config = NextProtoVector{kProtoHTTP11};
11689 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl0);
11690 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl1);
11691
11692 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
11693 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
11694
11695 TestCompletionCallback callback1;
11696 int rv = trans.Start(&request, callback1.callback(), NetLogWithSource());
11697 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
11698
11699 rv = callback1.WaitForResult();
11700 EXPECT_THAT(rv, IsOk());
11701
11702 EXPECT_FALSE(trans.IsReadyToRestartForAuth());
11703
11704 const HttpResponseInfo* response = trans.GetResponseInfo();
11705 ASSERT_TRUE(response);
11706 EXPECT_TRUE(CheckNTLMServerAuth(response->auth_challenge));
11707
11708 TestCompletionCallback callback2;
11709
11710 rv = trans.RestartWithAuth(
11711 AuthCredentials(ntlm::test::kDomainUserCombined, ntlm::test::kPassword),
11712 callback2.callback());
11713 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
11714
11715 rv = callback2.WaitForResult();
11716 EXPECT_THAT(rv, IsOk());
11717
11718 EXPECT_TRUE(trans.IsReadyToRestartForAuth());
11719
11720 response = trans.GetResponseInfo();
11721 ASSERT_TRUE(response);
11722 EXPECT_FALSE(response->auth_challenge.has_value());
11723
11724 TestCompletionCallback callback3;
11725
11726 rv = trans.RestartWithAuth(AuthCredentials(), callback3.callback());
11727 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
11728
11729 rv = callback3.WaitForResult();
11730 EXPECT_THAT(rv, IsOk());
11731
11732 response = trans.GetResponseInfo();
11733 ASSERT_TRUE(response);
11734 EXPECT_FALSE(response->auth_challenge.has_value());
11735 EXPECT_EQ(14, response->headers->GetContentLength());
11736
11737 std::string response_data;
11738 rv = ReadTransaction(&trans, &response_data);
11739 EXPECT_THAT(rv, IsOk());
11740 EXPECT_EQ("Please Login\r\n", response_data);
11741
11742 EXPECT_TRUE(data0.AllReadDataConsumed());
11743 EXPECT_TRUE(data0.AllWriteDataConsumed());
11744 EXPECT_TRUE(data1.AllReadDataConsumed());
11745 EXPECT_TRUE(data1.AllWriteDataConsumed());
11746
11747 EXPECT_TRUE(session->http_server_properties()->RequiresHTTP11(
11748 url::SchemeHostPort(request.url), NetworkAnonymizationKey()));
11749 }
11750
11751 // Same as above, but with a host mapping in place. The mapped host is the one
11752 // that should be tagged as requiring HTTP11.
TEST_P(HttpNetworkTransactionTest,NTLMOverHttp2WithHostMapping)11753 TEST_P(HttpNetworkTransactionTest, NTLMOverHttp2WithHostMapping) {
11754 HttpAuthNtlmMechanism::ScopedProcSetter proc_setter(
11755 MockGetMSTime, MockGenerateRandom, MockGetHostName);
11756
11757 const char kUrl[] = "https://server/kids/login.aspx";
11758 const char kMappedUrl[] = "https://server2:12345/kids/login.aspx";
11759 session_deps_.host_mapping_rules.AddRuleFromString(
11760 "MAP server server2:12345");
11761
11762 HttpRequestInfo request;
11763 request.method = "GET";
11764 request.url = GURL(kUrl);
11765 request.traffic_annotation =
11766 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
11767
11768 // First request without credentials.
11769 spdy::Http2HeaderBlock request_headers0(
11770 spdy_util_.ConstructGetHeaderBlock(kUrl));
11771 spdy::SpdySerializedFrame request0(spdy_util_.ConstructSpdyHeaders(
11772 1, std::move(request_headers0), LOWEST, true));
11773
11774 spdy::Http2HeaderBlock response_headers0;
11775 response_headers0[spdy::kHttp2StatusHeader] = "401";
11776 response_headers0["www-authenticate"] = "NTLM";
11777 spdy::SpdySerializedFrame resp(spdy_util_.ConstructSpdyResponseHeaders(
11778 1, std::move(response_headers0), true));
11779
11780 // Stream 1 is closed.
11781 spdy_util_.UpdateWithStreamDestruction(1);
11782
11783 // Generate the NTLM messages based on known test data.
11784 std::string negotiate_msg = base::Base64Encode(std::string_view(
11785 reinterpret_cast<const char*>(ntlm::test::kExpectedNegotiateMsg),
11786 std::size(ntlm::test::kExpectedNegotiateMsg)));
11787 std::string challenge_msg = base::Base64Encode(std::string_view(
11788 reinterpret_cast<const char*>(ntlm::test::kChallengeMsgFromSpecV2),
11789 std::size(ntlm::test::kChallengeMsgFromSpecV2)));
11790 std::string authenticate_msg = base::Base64Encode(std::string_view(
11791 reinterpret_cast<const char*>(
11792 ntlm::test::kExpectedAuthenticateMsgEmptyChannelBindingsV2),
11793 std::size(ntlm::test::kExpectedAuthenticateMsgEmptyChannelBindingsV2)));
11794
11795 MockWrite writes0[] = {CreateMockWrite(request0, 0)};
11796 MockRead reads0[] = {CreateMockRead(resp, 1),
11797 MockRead(SYNCHRONOUS, ERR_IO_PENDING, 2)};
11798
11799 // Retry yet again using HTTP/1.1.
11800 MockWrite writes1[] = {
11801 // After restarting with a null identity, this is the
11802 // request we should be issuing -- the final header line contains a Type
11803 // 1 message.
11804 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
11805 "Host: server\r\n"
11806 "Connection: keep-alive\r\n"
11807 "Authorization: NTLM "),
11808 MockWrite(negotiate_msg.c_str()),
11809 MockWrite("\r\n\r\n"),
11810
11811 // After calling trans.RestartWithAuth(), we should send a Type 3 message
11812 // (the credentials for the origin server). The second request continues
11813 // on the same connection.
11814 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
11815 "Host: server\r\n"
11816 "Connection: keep-alive\r\n"
11817 "Authorization: NTLM "),
11818 MockWrite(authenticate_msg.c_str()),
11819 MockWrite("\r\n\r\n"),
11820 };
11821
11822 MockRead reads1[] = {
11823 // The origin server responds with a Type 2 message.
11824 MockRead("HTTP/1.1 401 Access Denied\r\n"),
11825 MockRead("WWW-Authenticate: NTLM "),
11826 MockRead(challenge_msg.c_str()),
11827 MockRead("\r\n"),
11828 MockRead("Content-Length: 42\r\n"),
11829 MockRead("Content-Type: text/html\r\n\r\n"),
11830 MockRead("You are not authorized to view this page\r\n"),
11831
11832 // Lastly we get the desired content.
11833 MockRead("HTTP/1.1 200 OK\r\n"),
11834 MockRead("Content-Type: text/html; charset=utf-8\r\n"),
11835 MockRead("Content-Length: 14\r\n\r\n"),
11836 MockRead("Please Login\r\n"),
11837 };
11838 SequencedSocketData data0(reads0, writes0);
11839 StaticSocketDataProvider data1(reads1, writes1);
11840 session_deps_.socket_factory->AddSocketDataProvider(&data0);
11841 session_deps_.socket_factory->AddSocketDataProvider(&data1);
11842
11843 SSLSocketDataProvider ssl0(ASYNC, OK);
11844 ssl0.next_proto = kProtoHTTP2;
11845 ssl0.next_protos_expected_in_ssl_config =
11846 NextProtoVector{kProtoHTTP2, kProtoHTTP11};
11847 SSLSocketDataProvider ssl1(ASYNC, OK);
11848 // When creating the second connection, only HTTP/1.1 should be allowed.
11849 ssl1.next_protos_expected_in_ssl_config = NextProtoVector{kProtoHTTP11};
11850 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl0);
11851 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl1);
11852
11853 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
11854 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
11855
11856 TestCompletionCallback callback1;
11857 int rv = trans.Start(&request, callback1.callback(), NetLogWithSource());
11858 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
11859
11860 rv = callback1.WaitForResult();
11861 EXPECT_THAT(rv, IsOk());
11862
11863 EXPECT_FALSE(trans.IsReadyToRestartForAuth());
11864
11865 const HttpResponseInfo* response = trans.GetResponseInfo();
11866 ASSERT_TRUE(response);
11867 EXPECT_TRUE(CheckNTLMServerAuth(response->auth_challenge));
11868
11869 TestCompletionCallback callback2;
11870
11871 rv = trans.RestartWithAuth(
11872 AuthCredentials(ntlm::test::kDomainUserCombined, ntlm::test::kPassword),
11873 callback2.callback());
11874 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
11875
11876 rv = callback2.WaitForResult();
11877 EXPECT_THAT(rv, IsOk());
11878
11879 EXPECT_TRUE(trans.IsReadyToRestartForAuth());
11880
11881 response = trans.GetResponseInfo();
11882 ASSERT_TRUE(response);
11883 EXPECT_FALSE(response->auth_challenge.has_value());
11884
11885 TestCompletionCallback callback3;
11886
11887 rv = trans.RestartWithAuth(AuthCredentials(), callback3.callback());
11888 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
11889
11890 rv = callback3.WaitForResult();
11891 EXPECT_THAT(rv, IsOk());
11892
11893 response = trans.GetResponseInfo();
11894 ASSERT_TRUE(response);
11895 EXPECT_FALSE(response->auth_challenge.has_value());
11896 EXPECT_EQ(14, response->headers->GetContentLength());
11897
11898 std::string response_data;
11899 rv = ReadTransaction(&trans, &response_data);
11900 EXPECT_THAT(rv, IsOk());
11901 EXPECT_EQ("Please Login\r\n", response_data);
11902
11903 EXPECT_TRUE(data0.AllReadDataConsumed());
11904 EXPECT_TRUE(data0.AllWriteDataConsumed());
11905 EXPECT_TRUE(data1.AllReadDataConsumed());
11906 EXPECT_TRUE(data1.AllWriteDataConsumed());
11907
11908 EXPECT_FALSE(session->http_server_properties()->RequiresHTTP11(
11909 url::SchemeHostPort(request.url), NetworkAnonymizationKey()));
11910 EXPECT_TRUE(session->http_server_properties()->RequiresHTTP11(
11911 url::SchemeHostPort(GURL(kMappedUrl)), NetworkAnonymizationKey()));
11912 }
11913
11914 #if BUILDFLAG(ENABLE_WEBSOCKETS)
11915
11916 // Variant of above test using WebSockets.
TEST_P(HttpNetworkTransactionTest,NTLMOverHttp2WithWebsockets)11917 TEST_P(HttpNetworkTransactionTest, NTLMOverHttp2WithWebsockets) {
11918 const GURL kInitialUrl("https://server/");
11919 const GURL kWebSocketUrl("wss://server/");
11920 HttpAuthNtlmMechanism::ScopedProcSetter proc_setter(
11921 MockGetMSTime, MockGenerateRandom, MockGetHostName);
11922
11923 // Initial request establishes an H2 connection, which will then be reused for
11924 // WebSockets. This is needed since WebSockets will reuse H2 connections, but
11925 // it won't create a new one.
11926 spdy::Http2HeaderBlock initial_request_headers(
11927 spdy_util_.ConstructGetHeaderBlock(kInitialUrl.spec()));
11928 spdy::SpdySerializedFrame initial_request(spdy_util_.ConstructSpdyHeaders(
11929 1, std::move(initial_request_headers), DEFAULT_PRIORITY, true));
11930 spdy::SpdySerializedFrame settings_ack(spdy_util_.ConstructSpdySettingsAck());
11931
11932 // Settings frame, indicating WebSockets is supported.
11933 spdy::SettingsMap settings;
11934 settings[spdy::SETTINGS_ENABLE_CONNECT_PROTOCOL] = 1;
11935 spdy::SpdySerializedFrame settings_frame(
11936 spdy_util_.ConstructSpdySettings(settings));
11937
11938 // Response headers for first request. Body is never received, but that
11939 // shouldn't matter for the purposes of this test.
11940 spdy::SpdySerializedFrame initial_response(
11941 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
11942
11943 // First WebSocket request, which has no credentials.
11944 spdy::Http2HeaderBlock websocket_request_headers;
11945 websocket_request_headers[spdy::kHttp2MethodHeader] = "CONNECT";
11946 websocket_request_headers[spdy::kHttp2AuthorityHeader] = "server";
11947 websocket_request_headers[spdy::kHttp2SchemeHeader] = "https";
11948 websocket_request_headers[spdy::kHttp2PathHeader] = "/";
11949 websocket_request_headers[spdy::kHttp2ProtocolHeader] = "websocket";
11950 websocket_request_headers["origin"] = "http://server";
11951 websocket_request_headers["sec-websocket-version"] = "13";
11952 websocket_request_headers["sec-websocket-extensions"] =
11953 "permessage-deflate; client_max_window_bits";
11954 spdy::SpdySerializedFrame websocket_request(spdy_util_.ConstructSpdyHeaders(
11955 3, std::move(websocket_request_headers), MEDIUM, false));
11956
11957 // Auth challenge to WebSocket request.
11958 spdy::Http2HeaderBlock auth_challenge_headers;
11959 auth_challenge_headers[spdy::kHttp2StatusHeader] = "401";
11960 auth_challenge_headers["www-authenticate"] = "NTLM";
11961 spdy::SpdySerializedFrame websocket_auth_challenge(
11962 spdy_util_.ConstructSpdyResponseHeaders(
11963 3, std::move(auth_challenge_headers), true));
11964
11965 MockWrite writes0[] = {CreateMockWrite(initial_request, 0),
11966 CreateMockWrite(settings_ack, 2),
11967 CreateMockWrite(websocket_request, 4),
11968 MockWrite(SYNCHRONOUS, ERR_IO_PENDING, 7)};
11969 MockRead reads0[] = {CreateMockRead(settings_frame, 1),
11970 CreateMockRead(initial_response, 3),
11971 CreateMockRead(websocket_auth_challenge, 5),
11972 MockRead(SYNCHRONOUS, ERR_IO_PENDING, 6)};
11973
11974 // Generate the NTLM messages based on known test data.
11975 std::string negotiate_msg = base::Base64Encode(std::string_view(
11976 reinterpret_cast<const char*>(ntlm::test::kExpectedNegotiateMsg),
11977 std::size(ntlm::test::kExpectedNegotiateMsg)));
11978 std::string challenge_msg = base::Base64Encode(std::string_view(
11979 reinterpret_cast<const char*>(ntlm::test::kChallengeMsgFromSpecV2),
11980 std::size(ntlm::test::kChallengeMsgFromSpecV2)));
11981 std::string authenticate_msg = base::Base64Encode(std::string_view(
11982 reinterpret_cast<const char*>(
11983 ntlm::test::kExpectedAuthenticateMsgEmptyChannelBindingsV2),
11984 std::size(ntlm::test::kExpectedAuthenticateMsgEmptyChannelBindingsV2)));
11985
11986 // Retry yet again using HTTP/1.1.
11987 MockWrite writes1[] = {
11988 // After restarting with a null identity, this is the
11989 // request we should be issuing -- the final header line contains a Type
11990 // 1 message.
11991 MockWrite("GET / HTTP/1.1\r\n"
11992 "Host: server\r\n"
11993 "Connection: Upgrade\r\n"
11994 "Authorization: NTLM "),
11995 MockWrite(negotiate_msg.c_str()),
11996 MockWrite("\r\n"),
11997 MockWrite("Origin: http://server\r\n"
11998 "Sec-WebSocket-Version: 13\r\n"
11999 "Upgrade: websocket\r\n"
12000 "Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n"
12001 "Sec-WebSocket-Extensions: permessage-deflate; "
12002 "client_max_window_bits\r\n\r\n"),
12003
12004 // After calling trans.RestartWithAuth(), we should send a Type 3 message
12005 // (the credentials for the origin server). The second request continues
12006 // on the same connection.
12007 MockWrite("GET / HTTP/1.1\r\n"
12008 "Host: server\r\n"
12009 "Connection: Upgrade\r\n"
12010 "Authorization: NTLM "),
12011 MockWrite(authenticate_msg.c_str()),
12012 MockWrite("\r\n"),
12013 MockWrite("Origin: http://server\r\n"
12014 "Sec-WebSocket-Version: 13\r\n"
12015 "Upgrade: websocket\r\n"
12016 "Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n"
12017 "Sec-WebSocket-Extensions: permessage-deflate; "
12018 "client_max_window_bits\r\n\r\n"),
12019 };
12020
12021 MockRead reads1[] = {
12022 // The origin server responds with a Type 2 message.
12023 MockRead("HTTP/1.1 401 Access Denied\r\n"),
12024 MockRead("WWW-Authenticate: NTLM "),
12025 MockRead(challenge_msg.c_str()),
12026 MockRead("\r\n"),
12027 MockRead("Content-Length: 42\r\n"),
12028 MockRead("Content-Type: text/html\r\n\r\n"),
12029 MockRead("You are not authorized to view this page\r\n"),
12030
12031 // Lastly we get the desired content.
12032 MockRead("HTTP/1.1 101 Switching Protocols\r\n"
12033 "Upgrade: websocket\r\n"
12034 "Connection: Upgrade\r\n"
12035 "Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=\r\n\r\n"),
12036 };
12037 SequencedSocketData data0(reads0, writes0);
12038 session_deps_.socket_factory->AddSocketDataProvider(&data0);
12039 SSLSocketDataProvider ssl0(ASYNC, OK);
12040 ssl0.next_proto = kProtoHTTP2;
12041 ssl0.next_protos_expected_in_ssl_config =
12042 NextProtoVector{kProtoHTTP2, kProtoHTTP11};
12043 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl0);
12044
12045 StaticSocketDataProvider data1(reads1, writes1);
12046 session_deps_.socket_factory->AddSocketDataProvider(&data1);
12047 SSLSocketDataProvider ssl1(ASYNC, OK);
12048 // When creating the second connection, only HTTP/1.1 should be allowed.
12049 ssl1.next_protos_expected_in_ssl_config = NextProtoVector{kProtoHTTP11};
12050 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl1);
12051
12052 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
12053
12054 HttpRequestInfo initial_request_info;
12055 initial_request_info.method = "GET";
12056 initial_request_info.url = kInitialUrl;
12057 initial_request_info.traffic_annotation =
12058 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
12059 HttpNetworkTransaction initial_trans(DEFAULT_PRIORITY, session.get());
12060 TestCompletionCallback initial_callback;
12061 int rv = initial_trans.Start(&initial_request_info,
12062 initial_callback.callback(), NetLogWithSource());
12063 EXPECT_THAT(initial_callback.GetResult(rv), IsOk());
12064
12065 EXPECT_FALSE(session->http_server_properties()->RequiresHTTP11(
12066 url::SchemeHostPort(kInitialUrl), NetworkAnonymizationKey()));
12067
12068 HttpRequestInfo websocket_request_info;
12069 websocket_request_info.method = "GET";
12070 websocket_request_info.url = kWebSocketUrl;
12071 websocket_request_info.traffic_annotation =
12072 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
12073 EXPECT_TRUE(HostPortPair::FromURL(initial_request_info.url)
12074 .Equals(HostPortPair::FromURL(websocket_request_info.url)));
12075 websocket_request_info.extra_headers.SetHeader("Origin", "http://server");
12076 websocket_request_info.extra_headers.SetHeader("Sec-WebSocket-Version", "13");
12077 // The following two headers must be removed by WebSocketHttp2HandshakeStream.
12078 websocket_request_info.extra_headers.SetHeader("Connection", "Upgrade");
12079 websocket_request_info.extra_headers.SetHeader("Upgrade", "websocket");
12080
12081 TestWebSocketHandshakeStreamCreateHelper websocket_stream_create_helper;
12082
12083 HttpNetworkTransaction websocket_trans(MEDIUM, session.get());
12084 websocket_trans.SetWebSocketHandshakeStreamCreateHelper(
12085 &websocket_stream_create_helper);
12086
12087 TestCompletionCallback websocket_callback;
12088 rv = websocket_trans.Start(&websocket_request_info,
12089 websocket_callback.callback(), NetLogWithSource());
12090 EXPECT_THAT(websocket_callback.GetResult(rv), IsOk());
12091
12092 EXPECT_FALSE(websocket_trans.IsReadyToRestartForAuth());
12093
12094 const HttpResponseInfo* response = websocket_trans.GetResponseInfo();
12095 ASSERT_TRUE(response);
12096 EXPECT_TRUE(CheckNTLMServerAuth(response->auth_challenge));
12097
12098 rv = websocket_trans.RestartWithAuth(
12099 AuthCredentials(ntlm::test::kDomainUserCombined, ntlm::test::kPassword),
12100 websocket_callback.callback());
12101 EXPECT_THAT(websocket_callback.GetResult(rv), IsOk());
12102
12103 EXPECT_TRUE(websocket_trans.IsReadyToRestartForAuth());
12104
12105 response = websocket_trans.GetResponseInfo();
12106 ASSERT_TRUE(response);
12107 EXPECT_FALSE(response->auth_challenge.has_value());
12108
12109 rv = websocket_trans.RestartWithAuth(AuthCredentials(),
12110 websocket_callback.callback());
12111 EXPECT_THAT(websocket_callback.GetResult(rv), IsOk());
12112
12113 // The server should have been marked as requiring HTTP/1.1. The important
12114 // part here is that the scheme that requires HTTP/1.1 should be HTTPS, not
12115 // WSS.
12116 EXPECT_TRUE(session->http_server_properties()->RequiresHTTP11(
12117 url::SchemeHostPort(kInitialUrl), NetworkAnonymizationKey()));
12118 }
12119
12120 #endif // BUILDFLAG(ENABLE_WEBSOCKETS)
12121
12122 // Test that, if we have an NTLM proxy and the origin resets the connection, we
12123 // do no retry forever as a result of TLS retries. This is a regression test for
12124 // https://crbug.com/823387. The version interference probe has since been
12125 // removed, but we now have a legacy crypto fallback. (If that fallback is
12126 // removed, this test should be kept but with the expectations tweaked, in case
12127 // future fallbacks are added.)
TEST_P(HttpNetworkTransactionTest,NTLMProxyTLSHandshakeReset)12128 TEST_P(HttpNetworkTransactionTest, NTLMProxyTLSHandshakeReset) {
12129 // The NTLM test data expects the proxy to be named 'server'. The origin is
12130 // https://origin/.
12131 session_deps_.proxy_resolution_service =
12132 ConfiguredProxyResolutionService::CreateFixedFromPacResultForTest(
12133 "PROXY server", TRAFFIC_ANNOTATION_FOR_TESTS);
12134
12135 SSLContextConfig config;
12136 session_deps_.ssl_config_service =
12137 std::make_unique<TestSSLConfigService>(config);
12138
12139 HttpRequestInfo request;
12140 request.method = "GET";
12141 request.url = GURL("https://origin/");
12142 request.traffic_annotation =
12143 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
12144
12145 // Ensure load is not disrupted by flags which suppress behaviour specific
12146 // to other auth schemes.
12147 request.load_flags = LOAD_DO_NOT_USE_EMBEDDED_IDENTITY;
12148
12149 HttpAuthNtlmMechanism::ScopedProcSetter proc_setter(
12150 MockGetMSTime, MockGenerateRandom, MockGetHostName);
12151 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
12152
12153 // Generate the NTLM messages based on known test data.
12154 std::string negotiate_msg = base::Base64Encode(std::string_view(
12155 reinterpret_cast<const char*>(ntlm::test::kExpectedNegotiateMsg),
12156 std::size(ntlm::test::kExpectedNegotiateMsg)));
12157 std::string challenge_msg = base::Base64Encode(std::string_view(
12158 reinterpret_cast<const char*>(ntlm::test::kChallengeMsgFromSpecV2),
12159 std::size(ntlm::test::kChallengeMsgFromSpecV2)));
12160 std::string authenticate_msg = base::Base64Encode(std::string_view(
12161 reinterpret_cast<const char*>(
12162 ntlm::test::kExpectedAuthenticateMsgEmptyChannelBindingsV2),
12163 std::size(ntlm::test::kExpectedAuthenticateMsgEmptyChannelBindingsV2)));
12164
12165 MockWrite data_writes[] = {
12166 // The initial CONNECT request.
12167 MockWrite("CONNECT origin:443 HTTP/1.1\r\n"
12168 "Host: origin:443\r\n"
12169 "Proxy-Connection: keep-alive\r\n\r\n"),
12170
12171 // After restarting with an identity.
12172 MockWrite("CONNECT origin:443 HTTP/1.1\r\n"
12173 "Host: origin:443\r\n"
12174 "Proxy-Connection: keep-alive\r\n"
12175 "Proxy-Authorization: NTLM "),
12176 MockWrite(negotiate_msg.c_str()),
12177 // End headers.
12178 MockWrite("\r\n\r\n"),
12179
12180 // The second restart.
12181 MockWrite("CONNECT origin:443 HTTP/1.1\r\n"
12182 "Host: origin:443\r\n"
12183 "Proxy-Connection: keep-alive\r\n"
12184 "Proxy-Authorization: NTLM "),
12185 MockWrite(authenticate_msg.c_str()),
12186 // End headers.
12187 MockWrite("\r\n\r\n"),
12188 };
12189
12190 MockRead data_reads[] = {
12191 // The initial NTLM response.
12192 MockRead("HTTP/1.1 407 Access Denied\r\n"
12193 "Content-Length: 0\r\n"
12194 "Proxy-Authenticate: NTLM\r\n\r\n"),
12195
12196 // The NTLM challenge message.
12197 MockRead("HTTP/1.1 407 Access Denied\r\n"
12198 "Content-Length: 0\r\n"
12199 "Proxy-Authenticate: NTLM "),
12200 MockRead(challenge_msg.c_str()),
12201 // End headers.
12202 MockRead("\r\n\r\n"),
12203
12204 // Finally the tunnel is established.
12205 MockRead("HTTP/1.1 200 Connected\r\n\r\n"),
12206 };
12207
12208 StaticSocketDataProvider data(data_reads, data_writes);
12209 SSLSocketDataProvider data_ssl(ASYNC, ERR_CONNECTION_RESET);
12210 session_deps_.socket_factory->AddSocketDataProvider(&data);
12211 session_deps_.socket_factory->AddSSLSocketDataProvider(&data_ssl);
12212
12213 StaticSocketDataProvider data2(data_reads, data_writes);
12214 SSLSocketDataProvider data2_ssl(ASYNC, ERR_CONNECTION_RESET);
12215 session_deps_.socket_factory->AddSocketDataProvider(&data2);
12216 session_deps_.socket_factory->AddSSLSocketDataProvider(&data2_ssl);
12217
12218 // Start the transaction. The proxy responds with an NTLM authentication
12219 // request.
12220 TestCompletionCallback callback;
12221 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
12222 int rv = callback.GetResult(
12223 trans.Start(&request, callback.callback(), NetLogWithSource()));
12224
12225 EXPECT_THAT(rv, IsOk());
12226 EXPECT_FALSE(trans.IsReadyToRestartForAuth());
12227 const HttpResponseInfo* response = trans.GetResponseInfo();
12228 ASSERT_TRUE(response);
12229 EXPECT_TRUE(CheckNTLMProxyAuth(response->auth_challenge));
12230
12231 // Configure credentials and restart. The proxy responds with the challenge
12232 // message.
12233 rv = callback.GetResult(trans.RestartWithAuth(
12234 AuthCredentials(ntlm::test::kDomainUserCombined, ntlm::test::kPassword),
12235 callback.callback()));
12236 EXPECT_THAT(rv, IsOk());
12237 EXPECT_TRUE(trans.IsReadyToRestartForAuth());
12238 response = trans.GetResponseInfo();
12239 ASSERT_TRUE(response);
12240 EXPECT_FALSE(response->auth_challenge.has_value());
12241
12242 // Restart once more. The tunnel will be established and the the SSL handshake
12243 // will reset. The fallback will then kick in and restart the process. The
12244 // proxy responds with another NTLM authentiation request, but we don't need
12245 // to provide credentials as the cached ones work.
12246 rv = callback.GetResult(
12247 trans.RestartWithAuth(AuthCredentials(), callback.callback()));
12248 EXPECT_THAT(rv, IsOk());
12249 EXPECT_TRUE(trans.IsReadyToRestartForAuth());
12250 response = trans.GetResponseInfo();
12251 ASSERT_TRUE(response);
12252 EXPECT_FALSE(response->auth_challenge.has_value());
12253
12254 // The proxy responds with the NTLM challenge message.
12255 rv = callback.GetResult(
12256 trans.RestartWithAuth(AuthCredentials(), callback.callback()));
12257 EXPECT_THAT(rv, IsOk());
12258 EXPECT_TRUE(trans.IsReadyToRestartForAuth());
12259 response = trans.GetResponseInfo();
12260 ASSERT_TRUE(response);
12261 EXPECT_FALSE(response->auth_challenge.has_value());
12262
12263 // Send the NTLM authenticate message. The tunnel is established and the
12264 // handshake resets again. We should not retry again.
12265 rv = callback.GetResult(
12266 trans.RestartWithAuth(AuthCredentials(), callback.callback()));
12267 EXPECT_THAT(rv, IsError(ERR_CONNECTION_RESET));
12268 }
12269
12270 #endif // NTLM_PORTABLE
12271
12272 // Test reading a server response which has only headers, and no body.
12273 // After some maximum number of bytes is consumed, the transaction should
12274 // fail with ERR_RESPONSE_HEADERS_TOO_BIG.
TEST_P(HttpNetworkTransactionTest,LargeHeadersNoBody)12275 TEST_P(HttpNetworkTransactionTest, LargeHeadersNoBody) {
12276 HttpRequestInfo request;
12277 request.method = "GET";
12278 request.url = GURL("http://www.example.org/");
12279 request.traffic_annotation =
12280 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
12281
12282 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
12283 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
12284
12285 // Respond with 300 kb of headers (we should fail after 256 kb).
12286 std::string large_headers_string;
12287 FillLargeHeadersString(&large_headers_string, 300 * 1024);
12288
12289 MockRead data_reads[] = {
12290 MockRead("HTTP/1.0 200 OK\r\n"),
12291 MockRead(ASYNC, large_headers_string.data(), large_headers_string.size()),
12292 MockRead("\r\nBODY"),
12293 MockRead(SYNCHRONOUS, OK),
12294 };
12295 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
12296 session_deps_.socket_factory->AddSocketDataProvider(&data);
12297
12298 TestCompletionCallback callback;
12299
12300 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
12301 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
12302
12303 rv = callback.WaitForResult();
12304 EXPECT_THAT(rv, IsError(ERR_RESPONSE_HEADERS_TOO_BIG));
12305 }
12306
12307 // Make sure that we don't try to reuse a TCPClientSocket when failing to
12308 // establish tunnel.
12309 // http://code.google.com/p/chromium/issues/detail?id=3772
TEST_P(HttpNetworkTransactionTest,DontRecycleTransportSocketForSSLTunnel)12310 TEST_P(HttpNetworkTransactionTest, DontRecycleTransportSocketForSSLTunnel) {
12311 HttpRequestInfo request;
12312 request.method = "GET";
12313 request.url = GURL("https://www.example.org/");
12314 request.traffic_annotation =
12315 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
12316
12317 // Configure against proxy server "myproxy:70".
12318 session_deps_.proxy_resolution_service =
12319 ConfiguredProxyResolutionService::CreateFixedForTest(
12320 "myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
12321
12322 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
12323
12324 auto trans =
12325 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
12326
12327 // Since we have proxy, should try to establish tunnel.
12328 MockWrite data_writes1[] = {
12329 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
12330 "Host: www.example.org:443\r\n"
12331 "Proxy-Connection: keep-alive\r\n\r\n"),
12332 };
12333
12334 // The proxy responds to the connect with a 404, using a persistent
12335 // connection. Usually a proxy would return 501 (not implemented),
12336 // or 200 (tunnel established).
12337 MockRead data_reads1[] = {
12338 MockRead("HTTP/1.1 404 Not Found\r\n"),
12339 MockRead("Content-Length: 10\r\n\r\n"),
12340 MockRead(SYNCHRONOUS, ERR_UNEXPECTED),
12341 };
12342
12343 StaticSocketDataProvider data1(data_reads1, data_writes1);
12344 session_deps_.socket_factory->AddSocketDataProvider(&data1);
12345
12346 TestCompletionCallback callback1;
12347
12348 int rv = trans->Start(&request, callback1.callback(), NetLogWithSource());
12349 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
12350
12351 rv = callback1.WaitForResult();
12352 EXPECT_THAT(rv, IsError(ERR_TUNNEL_CONNECTION_FAILED));
12353
12354 // Empty the current queue. This is necessary because idle sockets are
12355 // added to the connection pool asynchronously with a PostTask.
12356 base::RunLoop().RunUntilIdle();
12357
12358 // We now check to make sure the TCPClientSocket was not added back to
12359 // the pool.
12360 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
12361 trans.reset();
12362 base::RunLoop().RunUntilIdle();
12363 // Make sure that the socket didn't get recycled after calling the destructor.
12364 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
12365 }
12366
12367 // Make sure that we recycle a socket after reading all of the response body.
TEST_P(HttpNetworkTransactionTest,RecycleSocket)12368 TEST_P(HttpNetworkTransactionTest, RecycleSocket) {
12369 HttpRequestInfo request;
12370 request.method = "GET";
12371 request.url = GURL("http://www.example.org/");
12372 request.traffic_annotation =
12373 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
12374
12375 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
12376
12377 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
12378
12379 MockRead data_reads[] = {
12380 // A part of the response body is received with the response headers.
12381 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 11\r\n\r\nhel"),
12382 // The rest of the response body is received in two parts.
12383 MockRead("lo"),
12384 MockRead(" world"),
12385 MockRead("junk"), // Should not be read!!
12386 MockRead(SYNCHRONOUS, OK),
12387 };
12388
12389 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
12390 session_deps_.socket_factory->AddSocketDataProvider(&data);
12391
12392 TestCompletionCallback callback;
12393
12394 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
12395 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
12396
12397 rv = callback.WaitForResult();
12398 EXPECT_THAT(rv, IsOk());
12399
12400 const HttpResponseInfo* response = trans.GetResponseInfo();
12401 ASSERT_TRUE(response);
12402
12403 EXPECT_TRUE(response->headers);
12404 std::string status_line = response->headers->GetStatusLine();
12405 EXPECT_EQ("HTTP/1.1 200 OK", status_line);
12406
12407 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
12408
12409 std::string response_data;
12410 rv = ReadTransaction(&trans, &response_data);
12411 EXPECT_THAT(rv, IsOk());
12412 EXPECT_EQ("hello world", response_data);
12413
12414 // Empty the current queue. This is necessary because idle sockets are
12415 // added to the connection pool asynchronously with a PostTask.
12416 base::RunLoop().RunUntilIdle();
12417
12418 // We now check to make sure the socket was added back to the pool.
12419 EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session.get()));
12420 }
12421
12422 // Make sure that we recycle a SSL socket after reading all of the response
12423 // body.
TEST_P(HttpNetworkTransactionTest,RecycleSSLSocket)12424 TEST_P(HttpNetworkTransactionTest, RecycleSSLSocket) {
12425 HttpRequestInfo request;
12426 request.method = "GET";
12427 request.url = GURL("https://www.example.org/");
12428 request.traffic_annotation =
12429 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
12430
12431 MockWrite data_writes[] = {
12432 MockWrite("GET / HTTP/1.1\r\n"
12433 "Host: www.example.org\r\n"
12434 "Connection: keep-alive\r\n\r\n"),
12435 };
12436
12437 MockRead data_reads[] = {
12438 MockRead("HTTP/1.1 200 OK\r\n"),
12439 MockRead("Content-Length: 11\r\n\r\n"),
12440 MockRead("hello world"),
12441 MockRead(SYNCHRONOUS, OK),
12442 };
12443
12444 SSLSocketDataProvider ssl(ASYNC, OK);
12445 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
12446
12447 StaticSocketDataProvider data(data_reads, data_writes);
12448 session_deps_.socket_factory->AddSocketDataProvider(&data);
12449
12450 TestCompletionCallback callback;
12451
12452 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
12453 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
12454
12455 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
12456
12457 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
12458 EXPECT_THAT(callback.WaitForResult(), IsOk());
12459
12460 const HttpResponseInfo* response = trans.GetResponseInfo();
12461 ASSERT_TRUE(response);
12462 ASSERT_TRUE(response->headers);
12463 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
12464
12465 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
12466
12467 std::string response_data;
12468 rv = ReadTransaction(&trans, &response_data);
12469 EXPECT_THAT(rv, IsOk());
12470 EXPECT_EQ("hello world", response_data);
12471
12472 // Empty the current queue. This is necessary because idle sockets are
12473 // added to the connection pool asynchronously with a PostTask.
12474 base::RunLoop().RunUntilIdle();
12475
12476 // We now check to make sure the socket was added back to the pool.
12477 EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session.get()));
12478 }
12479
12480 // Grab a SSL socket, use it, and put it back into the pool. Then, reuse it
12481 // from the pool and make sure that we recover okay.
TEST_P(HttpNetworkTransactionTest,RecycleDeadSSLSocket)12482 TEST_P(HttpNetworkTransactionTest, RecycleDeadSSLSocket) {
12483 HttpRequestInfo request;
12484 request.method = "GET";
12485 request.url = GURL("https://www.example.org/");
12486 request.traffic_annotation =
12487 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
12488
12489 MockWrite data_writes[] = {
12490 MockWrite("GET / HTTP/1.1\r\n"
12491 "Host: www.example.org\r\n"
12492 "Connection: keep-alive\r\n\r\n"),
12493 MockWrite("GET / HTTP/1.1\r\n"
12494 "Host: www.example.org\r\n"
12495 "Connection: keep-alive\r\n\r\n"),
12496 };
12497
12498 MockRead data_reads[] = {
12499 MockRead("HTTP/1.1 200 OK\r\n"), MockRead("Content-Length: 11\r\n\r\n"),
12500 MockRead("hello world"), MockRead(ASYNC, ERR_CONNECTION_CLOSED)};
12501
12502 SSLSocketDataProvider ssl(ASYNC, OK);
12503 SSLSocketDataProvider ssl2(ASYNC, OK);
12504 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
12505 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
12506
12507 StaticSocketDataProvider data(data_reads, data_writes);
12508 StaticSocketDataProvider data2(data_reads, data_writes);
12509 session_deps_.socket_factory->AddSocketDataProvider(&data);
12510 session_deps_.socket_factory->AddSocketDataProvider(&data2);
12511
12512 TestCompletionCallback callback;
12513
12514 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
12515 auto trans =
12516 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
12517
12518 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
12519
12520 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
12521 EXPECT_THAT(callback.WaitForResult(), IsOk());
12522
12523 const HttpResponseInfo* response = trans->GetResponseInfo();
12524 ASSERT_TRUE(response);
12525 ASSERT_TRUE(response->headers);
12526 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
12527
12528 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
12529
12530 std::string response_data;
12531 rv = ReadTransaction(trans.get(), &response_data);
12532 EXPECT_THAT(rv, IsOk());
12533 EXPECT_EQ("hello world", response_data);
12534
12535 // Empty the current queue. This is necessary because idle sockets are
12536 // added to the connection pool asynchronously with a PostTask.
12537 base::RunLoop().RunUntilIdle();
12538
12539 // We now check to make sure the socket was added back to the pool.
12540 EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session.get()));
12541
12542 // Now start the second transaction, which should reuse the previous socket.
12543
12544 trans =
12545 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
12546
12547 rv = trans->Start(&request, callback.callback(), NetLogWithSource());
12548
12549 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
12550 EXPECT_THAT(callback.WaitForResult(), IsOk());
12551
12552 response = trans->GetResponseInfo();
12553 ASSERT_TRUE(response);
12554 ASSERT_TRUE(response->headers);
12555 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
12556
12557 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
12558
12559 rv = ReadTransaction(trans.get(), &response_data);
12560 EXPECT_THAT(rv, IsOk());
12561 EXPECT_EQ("hello world", response_data);
12562
12563 // Empty the current queue. This is necessary because idle sockets are
12564 // added to the connection pool asynchronously with a PostTask.
12565 base::RunLoop().RunUntilIdle();
12566
12567 // We now check to make sure the socket was added back to the pool.
12568 EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session.get()));
12569 }
12570
TEST_P(HttpNetworkTransactionTest,CloseConnectionOnDestruction)12571 TEST_P(HttpNetworkTransactionTest, CloseConnectionOnDestruction) {
12572 enum class TestCase {
12573 kReadHeaders,
12574 kReadPartOfBodyRead,
12575 kReadAllOfBody,
12576 };
12577
12578 for (auto test_case : {TestCase::kReadHeaders, TestCase::kReadPartOfBodyRead,
12579 TestCase::kReadAllOfBody}) {
12580 SCOPED_TRACE(testing::Message()
12581 << "Test case: " << static_cast<int>(test_case));
12582 for (bool close_connection : {false, true}) {
12583 if (test_case != TestCase::kReadAllOfBody || close_connection == false) {
12584 continue;
12585 }
12586 SCOPED_TRACE(testing::Message()
12587 << "Close connection: " << close_connection);
12588
12589 HttpRequestInfo request;
12590 request.method = "GET";
12591 request.url = GURL("http://foo.test/");
12592 request.traffic_annotation =
12593 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
12594
12595 std::unique_ptr<HttpNetworkSession> session(
12596 CreateSession(&session_deps_));
12597
12598 std::unique_ptr<HttpNetworkTransaction> trans =
12599 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY,
12600 session.get());
12601
12602 MockRead data_reads[] = {
12603 // A part of the response body is received with the response headers.
12604 MockRead("HTTP/1.1 200 OK\r\n"
12605 "Content-Length: 11\r\n\r\n"
12606 "hello world"),
12607 MockRead(SYNCHRONOUS, OK),
12608 };
12609
12610 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
12611 session_deps_.socket_factory->AddSocketDataProvider(&data);
12612
12613 TestCompletionCallback callback;
12614
12615 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
12616 EXPECT_THAT(callback.GetResult(rv), IsOk());
12617
12618 const HttpResponseInfo* response = trans->GetResponseInfo();
12619 ASSERT_TRUE(response);
12620
12621 EXPECT_TRUE(response->headers);
12622 std::string status_line = response->headers->GetStatusLine();
12623 EXPECT_EQ("HTTP/1.1 200 OK", status_line);
12624
12625 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
12626
12627 std::string response_data;
12628 switch (test_case) {
12629 case TestCase::kReadHeaders: {
12630 // Already read the headers, nothing else to do.
12631 break;
12632 }
12633
12634 case TestCase::kReadPartOfBodyRead: {
12635 auto buf = base::MakeRefCounted<IOBufferWithSize>(5);
12636 rv = trans->Read(buf.get(), 5, callback.callback());
12637 ASSERT_EQ(5, callback.GetResult(rv));
12638 response_data.assign(buf->data(), 5);
12639 EXPECT_EQ("hello", response_data);
12640 break;
12641 }
12642
12643 case TestCase::kReadAllOfBody: {
12644 rv = ReadTransaction(trans.get(), &response_data);
12645 EXPECT_THAT(rv, IsOk());
12646 EXPECT_EQ("hello world", response_data);
12647 break;
12648 }
12649 }
12650
12651 if (close_connection) {
12652 trans->CloseConnectionOnDestruction();
12653 }
12654 trans.reset();
12655
12656 // Wait for the socket to be drained and added to the socket pool or
12657 // destroyed.
12658 base::RunLoop().RunUntilIdle();
12659
12660 // In the case all the body was read, the socket will have been released
12661 // before the CloseConnectionOnDestruction() call, so will not be
12662 // destroyed.
12663 if (close_connection && test_case != TestCase::kReadAllOfBody) {
12664 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
12665 } else {
12666 EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session.get()));
12667 }
12668 }
12669 }
12670 }
12671
12672 // Grab a socket, use it, and put it back into the pool. Then, make
12673 // low memory notification and ensure the socket pool is flushed.
TEST_P(HttpNetworkTransactionTest,FlushSocketPoolOnLowMemoryNotifications)12674 TEST_P(HttpNetworkTransactionTest, FlushSocketPoolOnLowMemoryNotifications) {
12675 HttpRequestInfo request;
12676 request.method = "GET";
12677 request.url = GURL("http://www.example.org/");
12678 request.load_flags = 0;
12679 request.traffic_annotation =
12680 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
12681
12682 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
12683
12684 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
12685
12686 MockRead data_reads[] = {
12687 // A part of the response body is received with the response headers.
12688 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 11\r\n\r\nhel"),
12689 // The rest of the response body is received in two parts.
12690 MockRead("lo"),
12691 MockRead(" world"),
12692 MockRead("junk"), // Should not be read!!
12693 MockRead(SYNCHRONOUS, OK),
12694 };
12695
12696 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
12697 session_deps_.socket_factory->AddSocketDataProvider(&data);
12698
12699 TestCompletionCallback callback;
12700
12701 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
12702 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
12703
12704 EXPECT_THAT(callback.GetResult(rv), IsOk());
12705
12706 const HttpResponseInfo* response = trans.GetResponseInfo();
12707 ASSERT_TRUE(response);
12708 EXPECT_TRUE(response->headers);
12709 std::string status_line = response->headers->GetStatusLine();
12710 EXPECT_EQ("HTTP/1.1 200 OK", status_line);
12711
12712 // Make memory critical notification and ensure the transaction still has been
12713 // operating right.
12714 base::MemoryPressureListener::NotifyMemoryPressure(
12715 base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_CRITICAL);
12716 base::RunLoop().RunUntilIdle();
12717
12718 // Socket should not be flushed as long as it is not idle.
12719 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
12720
12721 std::string response_data;
12722 rv = ReadTransaction(&trans, &response_data);
12723 EXPECT_THAT(rv, IsOk());
12724 EXPECT_EQ("hello world", response_data);
12725
12726 // Empty the current queue. This is necessary because idle sockets are
12727 // added to the connection pool asynchronously with a PostTask.
12728 base::RunLoop().RunUntilIdle();
12729
12730 // We now check to make sure the socket was added back to the pool.
12731 EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session.get()));
12732
12733 // Idle sockets should be flushed now.
12734 base::MemoryPressureListener::NotifyMemoryPressure(
12735 base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_CRITICAL);
12736 base::RunLoop().RunUntilIdle();
12737
12738 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
12739 }
12740
12741 // Disable idle socket closing on memory pressure.
12742 // Grab a socket, use it, and put it back into the pool. Then, make
12743 // low memory notification and ensure the socket pool is NOT flushed.
TEST_P(HttpNetworkTransactionTest,NoFlushSocketPoolOnLowMemoryNotifications)12744 TEST_P(HttpNetworkTransactionTest, NoFlushSocketPoolOnLowMemoryNotifications) {
12745 HttpRequestInfo request;
12746 request.method = "GET";
12747 request.url = GURL("http://www.example.org/");
12748 request.load_flags = 0;
12749 request.traffic_annotation =
12750 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
12751
12752 // Disable idle socket closing on memory pressure.
12753 session_deps_.disable_idle_sockets_close_on_memory_pressure = true;
12754 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
12755
12756 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
12757
12758 MockRead data_reads[] = {
12759 // A part of the response body is received with the response headers.
12760 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 11\r\n\r\nhel"),
12761 // The rest of the response body is received in two parts.
12762 MockRead("lo"),
12763 MockRead(" world"),
12764 MockRead("junk"), // Should not be read!!
12765 MockRead(SYNCHRONOUS, OK),
12766 };
12767
12768 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
12769 session_deps_.socket_factory->AddSocketDataProvider(&data);
12770
12771 TestCompletionCallback callback;
12772
12773 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
12774 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
12775
12776 EXPECT_THAT(callback.GetResult(rv), IsOk());
12777
12778 const HttpResponseInfo* response = trans.GetResponseInfo();
12779 ASSERT_TRUE(response);
12780 EXPECT_TRUE(response->headers);
12781 std::string status_line = response->headers->GetStatusLine();
12782 EXPECT_EQ("HTTP/1.1 200 OK", status_line);
12783
12784 // Make memory critical notification and ensure the transaction still has been
12785 // operating right.
12786 base::MemoryPressureListener::NotifyMemoryPressure(
12787 base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_CRITICAL);
12788 base::RunLoop().RunUntilIdle();
12789
12790 // Socket should not be flushed as long as it is not idle.
12791 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
12792
12793 std::string response_data;
12794 rv = ReadTransaction(&trans, &response_data);
12795 EXPECT_THAT(rv, IsOk());
12796 EXPECT_EQ("hello world", response_data);
12797
12798 // Empty the current queue. This is necessary because idle sockets are
12799 // added to the connection pool asynchronously with a PostTask.
12800 base::RunLoop().RunUntilIdle();
12801
12802 // We now check to make sure the socket was added back to the pool.
12803 EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session.get()));
12804
12805 // Idle sockets should NOT be flushed on moderate memory pressure.
12806 base::MemoryPressureListener::NotifyMemoryPressure(
12807 base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_MODERATE);
12808 base::RunLoop().RunUntilIdle();
12809
12810 EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session.get()));
12811
12812 // Idle sockets should NOT be flushed on critical memory pressure.
12813 base::MemoryPressureListener::NotifyMemoryPressure(
12814 base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_CRITICAL);
12815 base::RunLoop().RunUntilIdle();
12816
12817 EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session.get()));
12818 }
12819
12820 // Grab an SSL socket, use it, and put it back into the pool. Then, make
12821 // low memory notification and ensure the socket pool is flushed.
TEST_P(HttpNetworkTransactionTest,FlushSSLSocketPoolOnLowMemoryNotifications)12822 TEST_P(HttpNetworkTransactionTest, FlushSSLSocketPoolOnLowMemoryNotifications) {
12823 HttpRequestInfo request;
12824 request.method = "GET";
12825 request.url = GURL("https://www.example.org/");
12826 request.load_flags = 0;
12827 request.traffic_annotation =
12828 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
12829
12830 MockWrite data_writes[] = {
12831 MockWrite("GET / HTTP/1.1\r\n"
12832 "Host: www.example.org\r\n"
12833 "Connection: keep-alive\r\n\r\n"),
12834 };
12835
12836 MockRead data_reads[] = {
12837 MockRead("HTTP/1.1 200 OK\r\n"), MockRead("Content-Length: 11\r\n\r\n"),
12838 MockRead("hello world"), MockRead(ASYNC, ERR_CONNECTION_CLOSED)};
12839
12840 SSLSocketDataProvider ssl(ASYNC, OK);
12841 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
12842
12843 StaticSocketDataProvider data(data_reads, data_writes);
12844 session_deps_.socket_factory->AddSocketDataProvider(&data);
12845
12846 TestCompletionCallback callback;
12847
12848 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
12849 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
12850
12851 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
12852 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
12853
12854 EXPECT_THAT(callback.GetResult(rv), IsOk());
12855
12856 const HttpResponseInfo* response = trans.GetResponseInfo();
12857 ASSERT_TRUE(response);
12858 ASSERT_TRUE(response->headers);
12859 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
12860
12861 // Make memory critical notification and ensure the transaction still has been
12862 // operating right.
12863 base::MemoryPressureListener::NotifyMemoryPressure(
12864 base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_CRITICAL);
12865 base::RunLoop().RunUntilIdle();
12866
12867 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
12868
12869 std::string response_data;
12870 rv = ReadTransaction(&trans, &response_data);
12871 EXPECT_THAT(rv, IsOk());
12872 EXPECT_EQ("hello world", response_data);
12873
12874 // Empty the current queue. This is necessary because idle sockets are
12875 // added to the connection pool asynchronously with a PostTask.
12876 base::RunLoop().RunUntilIdle();
12877
12878 // We now check to make sure the socket was added back to the pool.
12879 EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session.get()));
12880
12881 // Make memory notification once again and ensure idle socket is closed.
12882 base::MemoryPressureListener::NotifyMemoryPressure(
12883 base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_CRITICAL);
12884 base::RunLoop().RunUntilIdle();
12885
12886 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
12887 }
12888
12889 // Make sure that we recycle a socket after a zero-length response.
12890 // http://crbug.com/9880
TEST_P(HttpNetworkTransactionTest,RecycleSocketAfterZeroContentLength)12891 TEST_P(HttpNetworkTransactionTest, RecycleSocketAfterZeroContentLength) {
12892 HttpRequestInfo request;
12893 request.method = "GET";
12894 request.url = GURL(
12895 "http://www.example.org/csi?v=3&s=web&action=&"
12896 "tran=undefined&ei=mAXcSeegAo-SMurloeUN&"
12897 "e=17259,18167,19592,19773,19981,20133,20173,20233&"
12898 "rt=prt.2642,ol.2649,xjs.2951");
12899 request.traffic_annotation =
12900 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
12901
12902 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
12903
12904 MockRead data_reads[] = {
12905 MockRead("HTTP/1.1 204 No Content\r\n"
12906 "Content-Length: 0\r\n"
12907 "Content-Type: text/html\r\n\r\n"),
12908 MockRead("junk"), // Should not be read!!
12909 MockRead(SYNCHRONOUS, OK),
12910 };
12911
12912 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
12913 session_deps_.socket_factory->AddSocketDataProvider(&data);
12914
12915 // Transaction must be created after the MockReads, so it's destroyed before
12916 // them.
12917 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
12918
12919 TestCompletionCallback callback;
12920
12921 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
12922 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
12923
12924 rv = callback.WaitForResult();
12925 EXPECT_THAT(rv, IsOk());
12926
12927 const HttpResponseInfo* response = trans.GetResponseInfo();
12928 ASSERT_TRUE(response);
12929
12930 EXPECT_TRUE(response->headers);
12931 std::string status_line = response->headers->GetStatusLine();
12932 EXPECT_EQ("HTTP/1.1 204 No Content", status_line);
12933
12934 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
12935
12936 std::string response_data;
12937 rv = ReadTransaction(&trans, &response_data);
12938 EXPECT_THAT(rv, IsOk());
12939 EXPECT_EQ("", response_data);
12940
12941 // Empty the current queue. This is necessary because idle sockets are
12942 // added to the connection pool asynchronously with a PostTask.
12943 base::RunLoop().RunUntilIdle();
12944
12945 // We now check to make sure the socket was added back to the pool.
12946 EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session.get()));
12947 }
12948
TEST_P(HttpNetworkTransactionTest,ResendRequestOnWriteBodyError)12949 TEST_P(HttpNetworkTransactionTest, ResendRequestOnWriteBodyError) {
12950 std::vector<std::unique_ptr<UploadElementReader>> element_readers;
12951 element_readers.push_back(
12952 std::make_unique<UploadBytesElementReader>("foo", 3));
12953 ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0);
12954
12955 HttpRequestInfo request[2];
12956 // Transaction 1: a GET request that succeeds. The socket is recycled
12957 // after use.
12958 request[0].method = "GET";
12959 request[0].url = GURL("http://www.google.com/");
12960 request[0].load_flags = 0;
12961 request[0].traffic_annotation =
12962 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
12963 // Transaction 2: a POST request. Reuses the socket kept alive from
12964 // transaction 1. The first attempts fails when writing the POST data.
12965 // This causes the transaction to retry with a new socket. The second
12966 // attempt succeeds.
12967 request[1].method = "POST";
12968 request[1].url = GURL("http://www.google.com/login.cgi");
12969 request[1].upload_data_stream = &upload_data_stream;
12970 request[1].load_flags = 0;
12971 request[1].traffic_annotation =
12972 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
12973
12974 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
12975
12976 // The first socket is used for transaction 1 and the first attempt of
12977 // transaction 2.
12978
12979 // The response of transaction 1.
12980 MockRead data_reads1[] = {
12981 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 11\r\n\r\n"),
12982 MockRead("hello world"),
12983 MockRead(SYNCHRONOUS, OK),
12984 };
12985 // The mock write results of transaction 1 and the first attempt of
12986 // transaction 2.
12987 MockWrite data_writes1[] = {
12988 MockWrite(SYNCHRONOUS, 64), // GET
12989 MockWrite(SYNCHRONOUS, 93), // POST
12990 MockWrite(SYNCHRONOUS, ERR_CONNECTION_ABORTED), // POST data
12991 };
12992 StaticSocketDataProvider data1(data_reads1, data_writes1);
12993
12994 // The second socket is used for the second attempt of transaction 2.
12995
12996 // The response of transaction 2.
12997 MockRead data_reads2[] = {
12998 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 7\r\n\r\n"),
12999 MockRead("welcome"),
13000 MockRead(SYNCHRONOUS, OK),
13001 };
13002 // The mock write results of the second attempt of transaction 2.
13003 MockWrite data_writes2[] = {
13004 MockWrite(SYNCHRONOUS, 93), // POST
13005 MockWrite(SYNCHRONOUS, 3), // POST data
13006 };
13007 StaticSocketDataProvider data2(data_reads2, data_writes2);
13008
13009 session_deps_.socket_factory->AddSocketDataProvider(&data1);
13010 session_deps_.socket_factory->AddSocketDataProvider(&data2);
13011
13012 const char* const kExpectedResponseData[] = {"hello world", "welcome"};
13013
13014 for (int i = 0; i < 2; ++i) {
13015 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
13016
13017 TestCompletionCallback callback;
13018
13019 int rv = trans.Start(&request[i], callback.callback(), NetLogWithSource());
13020 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
13021
13022 rv = callback.WaitForResult();
13023 EXPECT_THAT(rv, IsOk());
13024
13025 const HttpResponseInfo* response = trans.GetResponseInfo();
13026 ASSERT_TRUE(response);
13027
13028 EXPECT_TRUE(response->headers);
13029 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
13030
13031 std::string response_data;
13032 rv = ReadTransaction(&trans, &response_data);
13033 EXPECT_THAT(rv, IsOk());
13034 EXPECT_EQ(kExpectedResponseData[i], response_data);
13035 }
13036 }
13037
13038 // Test the request-challenge-retry sequence for basic auth when there is
13039 // an identity in the URL. The request should be sent as normal, but when
13040 // it fails the identity from the URL is used to answer the challenge.
TEST_P(HttpNetworkTransactionTest,AuthIdentityInURL)13041 TEST_P(HttpNetworkTransactionTest, AuthIdentityInURL) {
13042 HttpRequestInfo request;
13043 request.method = "GET";
13044 request.url = GURL("http://foo:b@[email protected]/");
13045 request.load_flags = LOAD_NORMAL;
13046 request.traffic_annotation =
13047 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
13048
13049 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
13050 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
13051
13052 // The password contains an escaped character -- for this test to pass it
13053 // will need to be unescaped by HttpNetworkTransaction.
13054 EXPECT_EQ("b%40r", request.url.password());
13055
13056 MockWrite data_writes1[] = {
13057 MockWrite("GET / HTTP/1.1\r\n"
13058 "Host: www.example.org\r\n"
13059 "Connection: keep-alive\r\n\r\n"),
13060 };
13061
13062 MockRead data_reads1[] = {
13063 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
13064 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
13065 MockRead("Content-Length: 10\r\n\r\n"),
13066 MockRead(SYNCHRONOUS, ERR_FAILED),
13067 };
13068
13069 // After the challenge above, the transaction will be restarted using the
13070 // identity from the url (foo, b@r) to answer the challenge.
13071 MockWrite data_writes2[] = {
13072 MockWrite("GET / HTTP/1.1\r\n"
13073 "Host: www.example.org\r\n"
13074 "Connection: keep-alive\r\n"
13075 "Authorization: Basic Zm9vOmJAcg==\r\n\r\n"),
13076 };
13077
13078 MockRead data_reads2[] = {
13079 MockRead("HTTP/1.0 200 OK\r\n"),
13080 MockRead("Content-Length: 100\r\n\r\n"),
13081 MockRead(SYNCHRONOUS, OK),
13082 };
13083
13084 StaticSocketDataProvider data1(data_reads1, data_writes1);
13085 StaticSocketDataProvider data2(data_reads2, data_writes2);
13086 session_deps_.socket_factory->AddSocketDataProvider(&data1);
13087 session_deps_.socket_factory->AddSocketDataProvider(&data2);
13088
13089 TestCompletionCallback callback1;
13090 int rv = trans.Start(&request, callback1.callback(), NetLogWithSource());
13091 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
13092 rv = callback1.WaitForResult();
13093 EXPECT_THAT(rv, IsOk());
13094 EXPECT_TRUE(trans.IsReadyToRestartForAuth());
13095
13096 TestCompletionCallback callback2;
13097 rv = trans.RestartWithAuth(AuthCredentials(), callback2.callback());
13098 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
13099 rv = callback2.WaitForResult();
13100 EXPECT_THAT(rv, IsOk());
13101 EXPECT_FALSE(trans.IsReadyToRestartForAuth());
13102
13103 const HttpResponseInfo* response = trans.GetResponseInfo();
13104 ASSERT_TRUE(response);
13105
13106 // There is no challenge info, since the identity in URL worked.
13107 EXPECT_FALSE(response->auth_challenge.has_value());
13108
13109 EXPECT_EQ(100, response->headers->GetContentLength());
13110
13111 // Empty the current queue.
13112 base::RunLoop().RunUntilIdle();
13113 }
13114
13115 // Test the request-challenge-retry sequence for basic auth when there is an
13116 // incorrect identity in the URL. The identity from the URL should be used only
13117 // once.
TEST_P(HttpNetworkTransactionTest,WrongAuthIdentityInURL)13118 TEST_P(HttpNetworkTransactionTest, WrongAuthIdentityInURL) {
13119 HttpRequestInfo request;
13120 request.method = "GET";
13121 // Note: the URL has a username:password in it. The password "baz" is
13122 // wrong (should be "bar").
13123 request.url = GURL("http://foo:[email protected]/");
13124
13125 request.load_flags = LOAD_NORMAL;
13126 request.traffic_annotation =
13127 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
13128
13129 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
13130 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
13131
13132 MockWrite data_writes1[] = {
13133 MockWrite("GET / HTTP/1.1\r\n"
13134 "Host: www.example.org\r\n"
13135 "Connection: keep-alive\r\n\r\n"),
13136 };
13137
13138 MockRead data_reads1[] = {
13139 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
13140 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
13141 MockRead("Content-Length: 10\r\n\r\n"),
13142 MockRead(SYNCHRONOUS, ERR_FAILED),
13143 };
13144
13145 // After the challenge above, the transaction will be restarted using the
13146 // identity from the url (foo, baz) to answer the challenge.
13147 MockWrite data_writes2[] = {
13148 MockWrite("GET / HTTP/1.1\r\n"
13149 "Host: www.example.org\r\n"
13150 "Connection: keep-alive\r\n"
13151 "Authorization: Basic Zm9vOmJheg==\r\n\r\n"),
13152 };
13153
13154 MockRead data_reads2[] = {
13155 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
13156 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
13157 MockRead("Content-Length: 10\r\n\r\n"),
13158 MockRead(SYNCHRONOUS, ERR_FAILED),
13159 };
13160
13161 // After the challenge above, the transaction will be restarted using the
13162 // identity supplied by the user (foo, bar) to answer the challenge.
13163 MockWrite data_writes3[] = {
13164 MockWrite("GET / HTTP/1.1\r\n"
13165 "Host: www.example.org\r\n"
13166 "Connection: keep-alive\r\n"
13167 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
13168 };
13169
13170 MockRead data_reads3[] = {
13171 MockRead("HTTP/1.0 200 OK\r\n"),
13172 MockRead("Content-Length: 100\r\n\r\n"),
13173 MockRead(SYNCHRONOUS, OK),
13174 };
13175
13176 StaticSocketDataProvider data1(data_reads1, data_writes1);
13177 StaticSocketDataProvider data2(data_reads2, data_writes2);
13178 StaticSocketDataProvider data3(data_reads3, data_writes3);
13179 session_deps_.socket_factory->AddSocketDataProvider(&data1);
13180 session_deps_.socket_factory->AddSocketDataProvider(&data2);
13181 session_deps_.socket_factory->AddSocketDataProvider(&data3);
13182
13183 TestCompletionCallback callback1;
13184
13185 int rv = trans.Start(&request, callback1.callback(), NetLogWithSource());
13186 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
13187
13188 rv = callback1.WaitForResult();
13189 EXPECT_THAT(rv, IsOk());
13190
13191 EXPECT_TRUE(trans.IsReadyToRestartForAuth());
13192 TestCompletionCallback callback2;
13193 rv = trans.RestartWithAuth(AuthCredentials(), callback2.callback());
13194 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
13195 rv = callback2.WaitForResult();
13196 EXPECT_THAT(rv, IsOk());
13197 EXPECT_FALSE(trans.IsReadyToRestartForAuth());
13198
13199 const HttpResponseInfo* response = trans.GetResponseInfo();
13200 ASSERT_TRUE(response);
13201 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge));
13202
13203 TestCompletionCallback callback3;
13204 rv = trans.RestartWithAuth(AuthCredentials(kFoo, kBar), callback3.callback());
13205 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
13206 rv = callback3.WaitForResult();
13207 EXPECT_THAT(rv, IsOk());
13208 EXPECT_FALSE(trans.IsReadyToRestartForAuth());
13209
13210 response = trans.GetResponseInfo();
13211 ASSERT_TRUE(response);
13212
13213 // There is no challenge info, since the identity worked.
13214 EXPECT_FALSE(response->auth_challenge.has_value());
13215
13216 EXPECT_EQ(100, response->headers->GetContentLength());
13217
13218 // Empty the current queue.
13219 base::RunLoop().RunUntilIdle();
13220 }
13221
13222 // Test the request-challenge-retry sequence for basic auth when there is a
13223 // correct identity in the URL, but its use is being suppressed. The identity
13224 // from the URL should never be used.
TEST_P(HttpNetworkTransactionTest,AuthIdentityInURLSuppressed)13225 TEST_P(HttpNetworkTransactionTest, AuthIdentityInURLSuppressed) {
13226 HttpRequestInfo request;
13227 request.method = "GET";
13228 request.url = GURL("http://foo:[email protected]/");
13229 request.load_flags = LOAD_DO_NOT_USE_EMBEDDED_IDENTITY;
13230 request.traffic_annotation =
13231 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
13232
13233 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
13234 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
13235
13236 MockWrite data_writes1[] = {
13237 MockWrite("GET / HTTP/1.1\r\n"
13238 "Host: www.example.org\r\n"
13239 "Connection: keep-alive\r\n\r\n"),
13240 };
13241
13242 MockRead data_reads1[] = {
13243 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
13244 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
13245 MockRead("Content-Length: 10\r\n\r\n"),
13246 MockRead(SYNCHRONOUS, ERR_FAILED),
13247 };
13248
13249 // After the challenge above, the transaction will be restarted using the
13250 // identity supplied by the user, not the one in the URL, to answer the
13251 // challenge.
13252 MockWrite data_writes3[] = {
13253 MockWrite("GET / HTTP/1.1\r\n"
13254 "Host: www.example.org\r\n"
13255 "Connection: keep-alive\r\n"
13256 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
13257 };
13258
13259 MockRead data_reads3[] = {
13260 MockRead("HTTP/1.0 200 OK\r\n"),
13261 MockRead("Content-Length: 100\r\n\r\n"),
13262 MockRead(SYNCHRONOUS, OK),
13263 };
13264
13265 StaticSocketDataProvider data1(data_reads1, data_writes1);
13266 StaticSocketDataProvider data3(data_reads3, data_writes3);
13267 session_deps_.socket_factory->AddSocketDataProvider(&data1);
13268 session_deps_.socket_factory->AddSocketDataProvider(&data3);
13269
13270 TestCompletionCallback callback1;
13271 int rv = trans.Start(&request, callback1.callback(), NetLogWithSource());
13272 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
13273 rv = callback1.WaitForResult();
13274 EXPECT_THAT(rv, IsOk());
13275 EXPECT_FALSE(trans.IsReadyToRestartForAuth());
13276
13277 const HttpResponseInfo* response = trans.GetResponseInfo();
13278 ASSERT_TRUE(response);
13279 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge));
13280
13281 TestCompletionCallback callback3;
13282 rv = trans.RestartWithAuth(AuthCredentials(kFoo, kBar), callback3.callback());
13283 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
13284 rv = callback3.WaitForResult();
13285 EXPECT_THAT(rv, IsOk());
13286 EXPECT_FALSE(trans.IsReadyToRestartForAuth());
13287
13288 response = trans.GetResponseInfo();
13289 ASSERT_TRUE(response);
13290
13291 // There is no challenge info, since the identity worked.
13292 EXPECT_FALSE(response->auth_challenge.has_value());
13293 EXPECT_EQ(100, response->headers->GetContentLength());
13294
13295 // Empty the current queue.
13296 base::RunLoop().RunUntilIdle();
13297 }
13298
13299 // Test that previously tried username/passwords for a realm get re-used.
TEST_P(HttpNetworkTransactionTest,BasicAuthCacheAndPreauth)13300 TEST_P(HttpNetworkTransactionTest, BasicAuthCacheAndPreauth) {
13301 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
13302
13303 // Transaction 1: authenticate (foo, bar) on MyRealm1
13304 {
13305 HttpRequestInfo request;
13306 request.method = "GET";
13307 request.url = GURL("http://www.example.org/x/y/z");
13308 request.traffic_annotation =
13309 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
13310
13311 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
13312
13313 MockWrite data_writes1[] = {
13314 MockWrite("GET /x/y/z HTTP/1.1\r\n"
13315 "Host: www.example.org\r\n"
13316 "Connection: keep-alive\r\n\r\n"),
13317 };
13318
13319 MockRead data_reads1[] = {
13320 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
13321 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
13322 MockRead("Content-Length: 10000\r\n\r\n"),
13323 MockRead(SYNCHRONOUS, ERR_FAILED),
13324 };
13325
13326 // Resend with authorization (username=foo, password=bar)
13327 MockWrite data_writes2[] = {
13328 MockWrite("GET /x/y/z HTTP/1.1\r\n"
13329 "Host: www.example.org\r\n"
13330 "Connection: keep-alive\r\n"
13331 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
13332 };
13333
13334 // Sever accepts the authorization.
13335 MockRead data_reads2[] = {
13336 MockRead("HTTP/1.0 200 OK\r\n"),
13337 MockRead("Content-Length: 100\r\n\r\n"),
13338 MockRead(SYNCHRONOUS, OK),
13339 };
13340
13341 StaticSocketDataProvider data1(data_reads1, data_writes1);
13342 StaticSocketDataProvider data2(data_reads2, data_writes2);
13343 session_deps_.socket_factory->AddSocketDataProvider(&data1);
13344 session_deps_.socket_factory->AddSocketDataProvider(&data2);
13345
13346 TestCompletionCallback callback1;
13347
13348 int rv = trans.Start(&request, callback1.callback(), NetLogWithSource());
13349 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
13350
13351 rv = callback1.WaitForResult();
13352 EXPECT_THAT(rv, IsOk());
13353
13354 const HttpResponseInfo* response = trans.GetResponseInfo();
13355 ASSERT_TRUE(response);
13356 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge));
13357
13358 TestCompletionCallback callback2;
13359
13360 rv = trans.RestartWithAuth(AuthCredentials(kFoo, kBar),
13361 callback2.callback());
13362 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
13363
13364 rv = callback2.WaitForResult();
13365 EXPECT_THAT(rv, IsOk());
13366
13367 response = trans.GetResponseInfo();
13368 ASSERT_TRUE(response);
13369 EXPECT_FALSE(response->auth_challenge.has_value());
13370 EXPECT_EQ(100, response->headers->GetContentLength());
13371 }
13372
13373 // ------------------------------------------------------------------------
13374
13375 // Transaction 2: authenticate (foo2, bar2) on MyRealm2
13376 {
13377 HttpRequestInfo request;
13378 request.method = "GET";
13379 // Note that Transaction 1 was at /x/y/z, so this is in the same
13380 // protection space as MyRealm1.
13381 request.url = GURL("http://www.example.org/x/y/a/b");
13382 request.traffic_annotation =
13383 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
13384
13385 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
13386
13387 MockWrite data_writes1[] = {
13388 MockWrite("GET /x/y/a/b HTTP/1.1\r\n"
13389 "Host: www.example.org\r\n"
13390 "Connection: keep-alive\r\n"
13391 // Send preemptive authorization for MyRealm1
13392 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
13393 };
13394
13395 // The server didn't like the preemptive authorization, and
13396 // challenges us for a different realm (MyRealm2).
13397 MockRead data_reads1[] = {
13398 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
13399 MockRead("WWW-Authenticate: Basic realm=\"MyRealm2\"\r\n"),
13400 MockRead("Content-Length: 10000\r\n\r\n"),
13401 MockRead(SYNCHRONOUS, ERR_FAILED),
13402 };
13403
13404 // Resend with authorization for MyRealm2 (username=foo2, password=bar2)
13405 MockWrite data_writes2[] = {
13406 MockWrite("GET /x/y/a/b HTTP/1.1\r\n"
13407 "Host: www.example.org\r\n"
13408 "Connection: keep-alive\r\n"
13409 "Authorization: Basic Zm9vMjpiYXIy\r\n\r\n"),
13410 };
13411
13412 // Sever accepts the authorization.
13413 MockRead data_reads2[] = {
13414 MockRead("HTTP/1.0 200 OK\r\n"),
13415 MockRead("Content-Length: 100\r\n\r\n"),
13416 MockRead(SYNCHRONOUS, OK),
13417 };
13418
13419 StaticSocketDataProvider data1(data_reads1, data_writes1);
13420 StaticSocketDataProvider data2(data_reads2, data_writes2);
13421 session_deps_.socket_factory->AddSocketDataProvider(&data1);
13422 session_deps_.socket_factory->AddSocketDataProvider(&data2);
13423
13424 TestCompletionCallback callback1;
13425
13426 int rv = trans.Start(&request, callback1.callback(), NetLogWithSource());
13427 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
13428
13429 rv = callback1.WaitForResult();
13430 EXPECT_THAT(rv, IsOk());
13431
13432 const HttpResponseInfo* response = trans.GetResponseInfo();
13433 ASSERT_TRUE(response);
13434 ASSERT_TRUE(response->auth_challenge);
13435 EXPECT_FALSE(response->auth_challenge->is_proxy);
13436 EXPECT_EQ("http://www.example.org",
13437 response->auth_challenge->challenger.Serialize());
13438 EXPECT_EQ("MyRealm2", response->auth_challenge->realm);
13439 EXPECT_EQ(kBasicAuthScheme, response->auth_challenge->scheme);
13440
13441 TestCompletionCallback callback2;
13442
13443 rv = trans.RestartWithAuth(AuthCredentials(kFoo2, kBar2),
13444 callback2.callback());
13445 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
13446
13447 rv = callback2.WaitForResult();
13448 EXPECT_THAT(rv, IsOk());
13449
13450 response = trans.GetResponseInfo();
13451 ASSERT_TRUE(response);
13452 EXPECT_FALSE(response->auth_challenge.has_value());
13453 EXPECT_EQ(100, response->headers->GetContentLength());
13454 }
13455
13456 // ------------------------------------------------------------------------
13457
13458 // Transaction 3: Resend a request in MyRealm's protection space --
13459 // succeed with preemptive authorization.
13460 {
13461 HttpRequestInfo request;
13462 request.method = "GET";
13463 request.url = GURL("http://www.example.org/x/y/z2");
13464 request.traffic_annotation =
13465 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
13466
13467 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
13468
13469 MockWrite data_writes1[] = {
13470 MockWrite("GET /x/y/z2 HTTP/1.1\r\n"
13471 "Host: www.example.org\r\n"
13472 "Connection: keep-alive\r\n"
13473 // The authorization for MyRealm1 gets sent preemptively
13474 // (since the url is in the same protection space)
13475 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
13476 };
13477
13478 // Sever accepts the preemptive authorization
13479 MockRead data_reads1[] = {
13480 MockRead("HTTP/1.0 200 OK\r\n"),
13481 MockRead("Content-Length: 100\r\n\r\n"),
13482 MockRead(SYNCHRONOUS, OK),
13483 };
13484
13485 StaticSocketDataProvider data1(data_reads1, data_writes1);
13486 session_deps_.socket_factory->AddSocketDataProvider(&data1);
13487
13488 TestCompletionCallback callback1;
13489
13490 int rv = trans.Start(&request, callback1.callback(), NetLogWithSource());
13491 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
13492
13493 rv = callback1.WaitForResult();
13494 EXPECT_THAT(rv, IsOk());
13495
13496 const HttpResponseInfo* response = trans.GetResponseInfo();
13497 ASSERT_TRUE(response);
13498
13499 EXPECT_FALSE(response->auth_challenge.has_value());
13500 EXPECT_EQ(100, response->headers->GetContentLength());
13501 }
13502
13503 // ------------------------------------------------------------------------
13504
13505 // Transaction 4: request another URL in MyRealm (however the
13506 // url is not known to belong to the protection space, so no pre-auth).
13507 {
13508 HttpRequestInfo request;
13509 request.method = "GET";
13510 request.url = GURL("http://www.example.org/x/1");
13511 request.traffic_annotation =
13512 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
13513
13514 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
13515
13516 MockWrite data_writes1[] = {
13517 MockWrite("GET /x/1 HTTP/1.1\r\n"
13518 "Host: www.example.org\r\n"
13519 "Connection: keep-alive\r\n\r\n"),
13520 };
13521
13522 MockRead data_reads1[] = {
13523 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
13524 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
13525 MockRead("Content-Length: 10000\r\n\r\n"),
13526 MockRead(SYNCHRONOUS, ERR_FAILED),
13527 };
13528
13529 // Resend with authorization from MyRealm's cache.
13530 MockWrite data_writes2[] = {
13531 MockWrite("GET /x/1 HTTP/1.1\r\n"
13532 "Host: www.example.org\r\n"
13533 "Connection: keep-alive\r\n"
13534 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
13535 };
13536
13537 // Sever accepts the authorization.
13538 MockRead data_reads2[] = {
13539 MockRead("HTTP/1.0 200 OK\r\n"),
13540 MockRead("Content-Length: 100\r\n\r\n"),
13541 MockRead(SYNCHRONOUS, OK),
13542 };
13543
13544 StaticSocketDataProvider data1(data_reads1, data_writes1);
13545 StaticSocketDataProvider data2(data_reads2, data_writes2);
13546 session_deps_.socket_factory->AddSocketDataProvider(&data1);
13547 session_deps_.socket_factory->AddSocketDataProvider(&data2);
13548
13549 TestCompletionCallback callback1;
13550
13551 int rv = trans.Start(&request, callback1.callback(), NetLogWithSource());
13552 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
13553
13554 rv = callback1.WaitForResult();
13555 EXPECT_THAT(rv, IsOk());
13556
13557 EXPECT_TRUE(trans.IsReadyToRestartForAuth());
13558 TestCompletionCallback callback2;
13559 rv = trans.RestartWithAuth(AuthCredentials(), callback2.callback());
13560 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
13561 rv = callback2.WaitForResult();
13562 EXPECT_THAT(rv, IsOk());
13563 EXPECT_FALSE(trans.IsReadyToRestartForAuth());
13564
13565 const HttpResponseInfo* response = trans.GetResponseInfo();
13566 ASSERT_TRUE(response);
13567 EXPECT_FALSE(response->auth_challenge.has_value());
13568 EXPECT_EQ(100, response->headers->GetContentLength());
13569 }
13570
13571 // ------------------------------------------------------------------------
13572
13573 // Transaction 5: request a URL in MyRealm, but the server rejects the
13574 // cached identity. Should invalidate and re-prompt.
13575 {
13576 HttpRequestInfo request;
13577 request.method = "GET";
13578 request.url = GURL("http://www.example.org/p/q/t");
13579 request.traffic_annotation =
13580 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
13581
13582 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
13583
13584 MockWrite data_writes1[] = {
13585 MockWrite("GET /p/q/t HTTP/1.1\r\n"
13586 "Host: www.example.org\r\n"
13587 "Connection: keep-alive\r\n\r\n"),
13588 };
13589
13590 MockRead data_reads1[] = {
13591 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
13592 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
13593 MockRead("Content-Length: 10000\r\n\r\n"),
13594 MockRead(SYNCHRONOUS, ERR_FAILED),
13595 };
13596
13597 // Resend with authorization from cache for MyRealm.
13598 MockWrite data_writes2[] = {
13599 MockWrite("GET /p/q/t HTTP/1.1\r\n"
13600 "Host: www.example.org\r\n"
13601 "Connection: keep-alive\r\n"
13602 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
13603 };
13604
13605 // Sever rejects the authorization.
13606 MockRead data_reads2[] = {
13607 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
13608 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
13609 MockRead("Content-Length: 10000\r\n\r\n"),
13610 MockRead(SYNCHRONOUS, ERR_FAILED),
13611 };
13612
13613 // At this point we should prompt for new credentials for MyRealm.
13614 // Restart with username=foo3, password=foo4.
13615 MockWrite data_writes3[] = {
13616 MockWrite("GET /p/q/t HTTP/1.1\r\n"
13617 "Host: www.example.org\r\n"
13618 "Connection: keep-alive\r\n"
13619 "Authorization: Basic Zm9vMzpiYXIz\r\n\r\n"),
13620 };
13621
13622 // Sever accepts the authorization.
13623 MockRead data_reads3[] = {
13624 MockRead("HTTP/1.0 200 OK\r\n"),
13625 MockRead("Content-Length: 100\r\n\r\n"),
13626 MockRead(SYNCHRONOUS, OK),
13627 };
13628
13629 StaticSocketDataProvider data1(data_reads1, data_writes1);
13630 StaticSocketDataProvider data2(data_reads2, data_writes2);
13631 StaticSocketDataProvider data3(data_reads3, data_writes3);
13632 session_deps_.socket_factory->AddSocketDataProvider(&data1);
13633 session_deps_.socket_factory->AddSocketDataProvider(&data2);
13634 session_deps_.socket_factory->AddSocketDataProvider(&data3);
13635
13636 TestCompletionCallback callback1;
13637
13638 int rv = trans.Start(&request, callback1.callback(), NetLogWithSource());
13639 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
13640
13641 rv = callback1.WaitForResult();
13642 EXPECT_THAT(rv, IsOk());
13643
13644 EXPECT_TRUE(trans.IsReadyToRestartForAuth());
13645 TestCompletionCallback callback2;
13646 rv = trans.RestartWithAuth(AuthCredentials(), callback2.callback());
13647 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
13648 rv = callback2.WaitForResult();
13649 EXPECT_THAT(rv, IsOk());
13650 EXPECT_FALSE(trans.IsReadyToRestartForAuth());
13651
13652 const HttpResponseInfo* response = trans.GetResponseInfo();
13653 ASSERT_TRUE(response);
13654 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge));
13655
13656 TestCompletionCallback callback3;
13657
13658 rv = trans.RestartWithAuth(AuthCredentials(kFoo3, kBar3),
13659 callback3.callback());
13660 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
13661
13662 rv = callback3.WaitForResult();
13663 EXPECT_THAT(rv, IsOk());
13664
13665 response = trans.GetResponseInfo();
13666 ASSERT_TRUE(response);
13667 EXPECT_FALSE(response->auth_challenge.has_value());
13668 EXPECT_EQ(100, response->headers->GetContentLength());
13669 }
13670 }
13671
13672 // Tests that nonce count increments when multiple auth attempts
13673 // are started with the same nonce.
TEST_P(HttpNetworkTransactionTest,DigestPreAuthNonceCount)13674 TEST_P(HttpNetworkTransactionTest, DigestPreAuthNonceCount) {
13675 auto digest_factory = std::make_unique<HttpAuthHandlerDigest::Factory>();
13676 auto nonce_generator =
13677 std::make_unique<HttpAuthHandlerDigest::FixedNonceGenerator>(
13678 "0123456789abcdef");
13679 digest_factory->set_nonce_generator(std::move(nonce_generator));
13680 session_deps_.http_auth_handler_factory = std::move(digest_factory);
13681 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
13682
13683 // Transaction 1: authenticate (foo, bar) on MyRealm1
13684 {
13685 HttpRequestInfo request;
13686 request.method = "GET";
13687 request.url = GURL("http://www.example.org/x/y/z");
13688 request.traffic_annotation =
13689 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
13690
13691 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
13692
13693 MockWrite data_writes1[] = {
13694 MockWrite("GET /x/y/z HTTP/1.1\r\n"
13695 "Host: www.example.org\r\n"
13696 "Connection: keep-alive\r\n\r\n"),
13697 };
13698
13699 MockRead data_reads1[] = {
13700 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
13701 MockRead(
13702 "WWW-Authenticate: Digest realm=\"digestive\", nonce=\"OU812\", "
13703 "algorithm=MD5, qop=\"auth\"\r\n\r\n"),
13704 MockRead(SYNCHRONOUS, OK),
13705 };
13706
13707 // Resend with authorization (username=foo, password=bar)
13708 MockWrite data_writes2[] = {
13709 MockWrite(
13710 "GET /x/y/z HTTP/1.1\r\n"
13711 "Host: www.example.org\r\n"
13712 "Connection: keep-alive\r\n"
13713 "Authorization: Digest username=\"foo\", realm=\"digestive\", "
13714 "nonce=\"OU812\", uri=\"/x/y/z\", algorithm=MD5, "
13715 "response=\"03ffbcd30add722589c1de345d7a927f\", qop=auth, "
13716 "nc=00000001, cnonce=\"0123456789abcdef\"\r\n\r\n"),
13717 };
13718
13719 // Sever accepts the authorization.
13720 MockRead data_reads2[] = {
13721 MockRead("HTTP/1.0 200 OK\r\n"),
13722 MockRead(SYNCHRONOUS, OK),
13723 };
13724
13725 StaticSocketDataProvider data1(data_reads1, data_writes1);
13726 StaticSocketDataProvider data2(data_reads2, data_writes2);
13727 session_deps_.socket_factory->AddSocketDataProvider(&data1);
13728 session_deps_.socket_factory->AddSocketDataProvider(&data2);
13729
13730 TestCompletionCallback callback1;
13731
13732 int rv = trans.Start(&request, callback1.callback(), NetLogWithSource());
13733 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
13734
13735 rv = callback1.WaitForResult();
13736 EXPECT_THAT(rv, IsOk());
13737
13738 const HttpResponseInfo* response = trans.GetResponseInfo();
13739 ASSERT_TRUE(response);
13740 EXPECT_TRUE(CheckDigestServerAuth(response->auth_challenge));
13741
13742 TestCompletionCallback callback2;
13743
13744 rv = trans.RestartWithAuth(AuthCredentials(kFoo, kBar),
13745 callback2.callback());
13746 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
13747
13748 rv = callback2.WaitForResult();
13749 EXPECT_THAT(rv, IsOk());
13750
13751 response = trans.GetResponseInfo();
13752 ASSERT_TRUE(response);
13753 EXPECT_FALSE(response->auth_challenge.has_value());
13754 }
13755
13756 // ------------------------------------------------------------------------
13757
13758 // Transaction 2: Request another resource in digestive's protection space.
13759 // This will preemptively add an Authorization header which should have an
13760 // "nc" value of 2 (as compared to 1 in the first use.
13761 {
13762 HttpRequestInfo request;
13763 request.method = "GET";
13764 // Note that Transaction 1 was at /x/y/z, so this is in the same
13765 // protection space as digest.
13766 request.url = GURL("http://www.example.org/x/y/a/b");
13767 request.traffic_annotation =
13768 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
13769
13770 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
13771
13772 MockWrite data_writes1[] = {
13773 MockWrite(
13774 "GET /x/y/a/b HTTP/1.1\r\n"
13775 "Host: www.example.org\r\n"
13776 "Connection: keep-alive\r\n"
13777 "Authorization: Digest username=\"foo\", realm=\"digestive\", "
13778 "nonce=\"OU812\", uri=\"/x/y/a/b\", algorithm=MD5, "
13779 "response=\"d6f9a2c07d1c5df7b89379dca1269b35\", qop=auth, "
13780 "nc=00000002, cnonce=\"0123456789abcdef\"\r\n\r\n"),
13781 };
13782
13783 // Sever accepts the authorization.
13784 MockRead data_reads1[] = {
13785 MockRead("HTTP/1.0 200 OK\r\n"),
13786 MockRead("Content-Length: 100\r\n\r\n"),
13787 MockRead(SYNCHRONOUS, OK),
13788 };
13789
13790 StaticSocketDataProvider data1(data_reads1, data_writes1);
13791 session_deps_.socket_factory->AddSocketDataProvider(&data1);
13792
13793 TestCompletionCallback callback1;
13794
13795 int rv = trans.Start(&request, callback1.callback(), NetLogWithSource());
13796 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
13797
13798 rv = callback1.WaitForResult();
13799 EXPECT_THAT(rv, IsOk());
13800
13801 const HttpResponseInfo* response = trans.GetResponseInfo();
13802 ASSERT_TRUE(response);
13803 EXPECT_FALSE(response->auth_challenge.has_value());
13804 }
13805 }
13806
13807 // Test the ResetStateForRestart() private method.
TEST_P(HttpNetworkTransactionTest,ResetStateForRestart)13808 TEST_P(HttpNetworkTransactionTest, ResetStateForRestart) {
13809 // Create a transaction (the dependencies aren't important).
13810 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
13811 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
13812
13813 // Setup some state (which we expect ResetStateForRestart() will clear).
13814 trans.read_buf_ = base::MakeRefCounted<IOBufferWithSize>(15);
13815 trans.read_buf_len_ = 15;
13816 trans.request_headers_.SetHeader("Authorization", "NTLM");
13817
13818 // Setup state in response_
13819 HttpResponseInfo* response = &trans.response_;
13820 response->auth_challenge = std::nullopt;
13821 response->ssl_info.cert_status = static_cast<CertStatus>(-1); // Nonsensical.
13822 response->response_time = base::Time::Now();
13823 response->was_cached = true; // (Wouldn't ever actually be true...)
13824
13825 // Cause the above state to be reset.
13826 trans.ResetStateForRestart();
13827
13828 // Verify that the state that needed to be reset, has been reset.
13829 EXPECT_FALSE(trans.read_buf_);
13830 EXPECT_EQ(0, trans.read_buf_len_);
13831 EXPECT_TRUE(trans.request_headers_.IsEmpty());
13832 EXPECT_FALSE(response->auth_challenge.has_value());
13833 EXPECT_FALSE(response->headers);
13834 EXPECT_FALSE(response->was_cached);
13835 EXPECT_EQ(0U, response->ssl_info.cert_status);
13836 }
13837
13838 // Test HTTPS connections to a site with a bad certificate
TEST_P(HttpNetworkTransactionTest,HTTPSBadCertificate)13839 TEST_P(HttpNetworkTransactionTest, HTTPSBadCertificate) {
13840 HttpRequestInfo request;
13841 request.method = "GET";
13842 request.url = GURL("https://www.example.org/");
13843 request.traffic_annotation =
13844 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
13845
13846 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
13847 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
13848
13849 MockWrite data_writes[] = {
13850 MockWrite("GET / HTTP/1.1\r\n"
13851 "Host: www.example.org\r\n"
13852 "Connection: keep-alive\r\n\r\n"),
13853 };
13854
13855 MockRead data_reads[] = {
13856 MockRead("HTTP/1.0 200 OK\r\n"),
13857 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
13858 MockRead("Content-Length: 100\r\n\r\n"),
13859 MockRead(SYNCHRONOUS, OK),
13860 };
13861
13862 StaticSocketDataProvider ssl_bad_certificate;
13863 StaticSocketDataProvider data(data_reads, data_writes);
13864 SSLSocketDataProvider ssl_bad(ASYNC, ERR_CERT_AUTHORITY_INVALID);
13865 SSLSocketDataProvider ssl(ASYNC, OK);
13866
13867 session_deps_.socket_factory->AddSocketDataProvider(&ssl_bad_certificate);
13868 session_deps_.socket_factory->AddSocketDataProvider(&data);
13869 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_bad);
13870 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
13871
13872 TestCompletionCallback callback;
13873
13874 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
13875 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
13876
13877 rv = callback.WaitForResult();
13878 EXPECT_THAT(rv, IsError(ERR_CERT_AUTHORITY_INVALID));
13879
13880 rv = trans.RestartIgnoringLastError(callback.callback());
13881 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
13882
13883 rv = callback.WaitForResult();
13884 EXPECT_THAT(rv, IsOk());
13885
13886 const HttpResponseInfo* response = trans.GetResponseInfo();
13887
13888 ASSERT_TRUE(response);
13889 EXPECT_EQ(100, response->headers->GetContentLength());
13890 }
13891
13892 // Test HTTPS connections to a site with a bad certificate, going through a
13893 // proxy
TEST_P(HttpNetworkTransactionTest,HTTPSBadCertificateViaProxy)13894 TEST_P(HttpNetworkTransactionTest, HTTPSBadCertificateViaProxy) {
13895 session_deps_.proxy_resolution_service =
13896 ConfiguredProxyResolutionService::CreateFixedForTest(
13897 "myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
13898
13899 HttpRequestInfo request;
13900 request.method = "GET";
13901 request.url = GURL("https://www.example.org/");
13902 request.traffic_annotation =
13903 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
13904
13905 MockWrite proxy_writes[] = {
13906 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
13907 "Host: www.example.org:443\r\n"
13908 "Proxy-Connection: keep-alive\r\n\r\n"),
13909 };
13910
13911 MockRead proxy_reads[] = {MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
13912 MockRead(SYNCHRONOUS, OK)};
13913
13914 MockWrite data_writes[] = {
13915 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
13916 "Host: www.example.org:443\r\n"
13917 "Proxy-Connection: keep-alive\r\n\r\n"),
13918 MockWrite("GET / HTTP/1.1\r\n"
13919 "Host: www.example.org\r\n"
13920 "Connection: keep-alive\r\n\r\n"),
13921 };
13922
13923 MockRead data_reads[] = {
13924 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
13925 MockRead("HTTP/1.0 200 OK\r\n"),
13926 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
13927 MockRead("Content-Length: 100\r\n\r\n"),
13928 MockRead(SYNCHRONOUS, OK),
13929 };
13930
13931 StaticSocketDataProvider ssl_bad_certificate(proxy_reads, proxy_writes);
13932 StaticSocketDataProvider data(data_reads, data_writes);
13933 SSLSocketDataProvider ssl_bad(ASYNC, ERR_CERT_AUTHORITY_INVALID);
13934 SSLSocketDataProvider ssl(ASYNC, OK);
13935
13936 session_deps_.socket_factory->AddSocketDataProvider(&ssl_bad_certificate);
13937 session_deps_.socket_factory->AddSocketDataProvider(&data);
13938 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_bad);
13939 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
13940
13941 TestCompletionCallback callback;
13942
13943 for (int i = 0; i < 2; i++) {
13944 session_deps_.socket_factory->ResetNextMockIndexes();
13945
13946 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
13947 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
13948
13949 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
13950 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
13951
13952 rv = callback.WaitForResult();
13953 EXPECT_THAT(rv, IsError(ERR_CERT_AUTHORITY_INVALID));
13954
13955 rv = trans.RestartIgnoringLastError(callback.callback());
13956 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
13957
13958 rv = callback.WaitForResult();
13959 EXPECT_THAT(rv, IsOk());
13960
13961 const HttpResponseInfo* response = trans.GetResponseInfo();
13962
13963 ASSERT_TRUE(response);
13964 EXPECT_EQ(100, response->headers->GetContentLength());
13965 }
13966 }
13967
13968 // Test HTTPS connections to a site, going through an HTTPS proxy
TEST_P(HttpNetworkTransactionTest,HTTPSViaHttpsProxy)13969 TEST_P(HttpNetworkTransactionTest, HTTPSViaHttpsProxy) {
13970 session_deps_.proxy_resolution_service =
13971 ConfiguredProxyResolutionService::CreateFixedFromPacResultForTest(
13972 "HTTPS proxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
13973 session_deps_.net_log = net::NetLog::Get();
13974
13975 HttpRequestInfo request;
13976 request.method = "GET";
13977 request.url = GURL("https://www.example.org/");
13978 request.traffic_annotation =
13979 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
13980
13981 MockWrite data_writes[] = {
13982 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
13983 "Host: www.example.org:443\r\n"
13984 "Proxy-Connection: keep-alive\r\n\r\n"),
13985 MockWrite("GET / HTTP/1.1\r\n"
13986 "Host: www.example.org\r\n"
13987 "Connection: keep-alive\r\n\r\n"),
13988 };
13989
13990 MockRead data_reads[] = {
13991 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
13992 MockRead("HTTP/1.1 200 OK\r\n"),
13993 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
13994 MockRead("Content-Length: 100\r\n\r\n"),
13995 MockRead(SYNCHRONOUS, OK),
13996 };
13997
13998 StaticSocketDataProvider data(data_reads, data_writes);
13999 SSLSocketDataProvider proxy_ssl(ASYNC, OK); // SSL to the proxy
14000 SSLSocketDataProvider tunnel_ssl(ASYNC, OK); // SSL through the tunnel
14001
14002 session_deps_.socket_factory->AddSocketDataProvider(&data);
14003 session_deps_.socket_factory->AddSSLSocketDataProvider(&proxy_ssl);
14004 session_deps_.socket_factory->AddSSLSocketDataProvider(&tunnel_ssl);
14005
14006 TestCompletionCallback callback;
14007
14008 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
14009 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
14010
14011 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
14012 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
14013
14014 rv = callback.WaitForResult();
14015 EXPECT_THAT(rv, IsOk());
14016 const HttpResponseInfo* response = trans.GetResponseInfo();
14017
14018 ASSERT_TRUE(response);
14019
14020 ASSERT_EQ(1u, response->proxy_chain.length());
14021 EXPECT_TRUE(response->proxy_chain.GetProxyServer(0).is_https());
14022 EXPECT_TRUE(response->headers->IsKeepAlive());
14023 EXPECT_EQ(200, response->headers->response_code());
14024 EXPECT_EQ(100, response->headers->GetContentLength());
14025 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
14026
14027 LoadTimingInfo load_timing_info;
14028 EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info));
14029 TestLoadTimingNotReusedWithPac(load_timing_info,
14030 CONNECT_TIMING_HAS_SSL_TIMES);
14031 }
14032
14033 // Test that an HTTPS Proxy cannot redirect a CONNECT request for main frames.
TEST_P(HttpNetworkTransactionTest,RedirectOfHttpsConnectViaHttpsProxy)14034 TEST_P(HttpNetworkTransactionTest, RedirectOfHttpsConnectViaHttpsProxy) {
14035 session_deps_.proxy_resolution_service =
14036 ConfiguredProxyResolutionService::CreateFixedFromPacResultForTest(
14037 "HTTPS proxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
14038 session_deps_.net_log = net::NetLog::Get();
14039
14040 const base::TimeDelta kTimeIncrement = base::Seconds(4);
14041 session_deps_.host_resolver->set_ondemand_mode(true);
14042
14043 HttpRequestInfo request;
14044 request.load_flags = LOAD_MAIN_FRAME_DEPRECATED;
14045 request.method = "GET";
14046 request.url = GURL("https://www.example.org/");
14047 request.traffic_annotation =
14048 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
14049
14050 MockWrite data_writes[] = {
14051 MockWrite(ASYNC, 0,
14052 "CONNECT www.example.org:443 HTTP/1.1\r\n"
14053 "Host: www.example.org:443\r\n"
14054 "Proxy-Connection: keep-alive\r\n\r\n"),
14055 };
14056
14057 MockRead data_reads[] = {
14058 // Pause on first read.
14059 MockRead(ASYNC, ERR_IO_PENDING, 1),
14060 MockRead(ASYNC, 2, "HTTP/1.1 302 Redirect\r\n"),
14061 MockRead(ASYNC, 3, "Location: http://login.example.com/\r\n"),
14062 MockRead(ASYNC, 4, "Content-Length: 0\r\n\r\n"),
14063 };
14064
14065 SequencedSocketData data(MockConnect(ASYNC, OK), data_reads, data_writes);
14066 SSLSocketDataProvider proxy_ssl(ASYNC, OK); // SSL to the proxy
14067
14068 session_deps_.socket_factory->AddSocketDataProvider(&data);
14069 session_deps_.socket_factory->AddSSLSocketDataProvider(&proxy_ssl);
14070
14071 TestCompletionCallback callback;
14072
14073 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
14074 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
14075
14076 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
14077 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
14078 EXPECT_TRUE(session_deps_.host_resolver->has_pending_requests());
14079
14080 // Host resolution takes |kTimeIncrement|.
14081 FastForwardBy(kTimeIncrement);
14082 // Resolving the current request with |ResolveNow| will cause the pending
14083 // request to instantly complete, and the async connect will start as well.
14084 session_deps_.host_resolver->ResolveOnlyRequestNow();
14085
14086 // Connecting takes |kTimeIncrement|.
14087 FastForwardBy(kTimeIncrement);
14088 data.RunUntilPaused();
14089
14090 // The server takes |kTimeIncrement| to respond.
14091 FastForwardBy(kTimeIncrement);
14092 data.Resume();
14093
14094 rv = callback.WaitForResult();
14095 EXPECT_THAT(rv, IsError(ERR_TUNNEL_CONNECTION_FAILED));
14096 }
14097
14098 // Test that an HTTPS Proxy cannot redirect a CONNECT request for subresources.
TEST_P(HttpNetworkTransactionTest,RedirectOfHttpsConnectSubresourceViaHttpsProxy)14099 TEST_P(HttpNetworkTransactionTest,
14100 RedirectOfHttpsConnectSubresourceViaHttpsProxy) {
14101 base::HistogramTester histograms;
14102 session_deps_.proxy_resolution_service =
14103 ConfiguredProxyResolutionService::CreateFixedFromPacResultForTest(
14104 "HTTPS proxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
14105 session_deps_.net_log = net::NetLog::Get();
14106
14107 HttpRequestInfo request;
14108 request.method = "GET";
14109 request.url = GURL("https://www.example.org/");
14110 request.traffic_annotation =
14111 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
14112
14113 MockWrite data_writes[] = {
14114 MockWrite(ASYNC, 0,
14115 "CONNECT www.example.org:443 HTTP/1.1\r\n"
14116 "Host: www.example.org:443\r\n"
14117 "Proxy-Connection: keep-alive\r\n\r\n"),
14118 };
14119
14120 MockRead data_reads[] = {
14121 MockRead(ASYNC, 1, "HTTP/1.1 302 Redirect\r\n"),
14122 MockRead(ASYNC, 2, "Location: http://login.example.com/\r\n"),
14123 MockRead(ASYNC, 3, "Content-Length: 0\r\n\r\n"),
14124 };
14125
14126 SequencedSocketData data(MockConnect(ASYNC, OK), data_reads, data_writes);
14127 SSLSocketDataProvider proxy_ssl(ASYNC, OK); // SSL to the proxy
14128
14129 session_deps_.socket_factory->AddSocketDataProvider(&data);
14130 session_deps_.socket_factory->AddSSLSocketDataProvider(&proxy_ssl);
14131
14132 TestCompletionCallback callback;
14133
14134 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
14135 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
14136
14137 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
14138 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
14139
14140 rv = callback.WaitForResult();
14141 EXPECT_THAT(rv, IsError(ERR_TUNNEL_CONNECTION_FAILED));
14142 }
14143
14144 // Test that an HTTPS Proxy which was auto-detected cannot redirect a CONNECT
14145 // request for main frames.
TEST_P(HttpNetworkTransactionTest,RedirectOfHttpsConnectViaAutoDetectedHttpsProxy)14146 TEST_P(HttpNetworkTransactionTest,
14147 RedirectOfHttpsConnectViaAutoDetectedHttpsProxy) {
14148 base::HistogramTester histograms;
14149 session_deps_.proxy_resolution_service = ConfiguredProxyResolutionService::
14150 CreateFixedFromAutoDetectedPacResultForTest("HTTPS proxy:70",
14151 TRAFFIC_ANNOTATION_FOR_TESTS);
14152 session_deps_.net_log = net::NetLog::Get();
14153
14154 HttpRequestInfo request;
14155 request.load_flags = LOAD_MAIN_FRAME_DEPRECATED;
14156 request.method = "GET";
14157 request.url = GURL("https://www.example.org/");
14158 request.traffic_annotation =
14159 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
14160
14161 MockWrite data_writes[] = {
14162 MockWrite(ASYNC, 0,
14163 "CONNECT www.example.org:443 HTTP/1.1\r\n"
14164 "Host: www.example.org:443\r\n"
14165 "Proxy-Connection: keep-alive\r\n\r\n"),
14166 };
14167
14168 MockRead data_reads[] = {
14169 MockRead(ASYNC, 1, "HTTP/1.1 302 Redirect\r\n"),
14170 MockRead(ASYNC, 2, "Location: http://login.example.com/\r\n"),
14171 MockRead(ASYNC, 3, "Content-Length: 0\r\n\r\n"),
14172 };
14173
14174 SequencedSocketData data(MockConnect(ASYNC, OK), data_reads, data_writes);
14175 SSLSocketDataProvider proxy_ssl(ASYNC, OK); // SSL to the proxy
14176
14177 session_deps_.socket_factory->AddSocketDataProvider(&data);
14178 session_deps_.socket_factory->AddSSLSocketDataProvider(&proxy_ssl);
14179
14180 TestCompletionCallback callback;
14181
14182 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
14183 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
14184
14185 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
14186 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
14187
14188 rv = callback.WaitForResult();
14189 EXPECT_THAT(rv, IsError(ERR_TUNNEL_CONNECTION_FAILED));
14190 }
14191
14192 // Tests that an HTTPS (SPDY) Proxy's cannot redirect a CONNECT request for main
14193 // frames.
TEST_P(HttpNetworkTransactionTest,RedirectOfHttpsConnectViaSpdyProxy)14194 TEST_P(HttpNetworkTransactionTest, RedirectOfHttpsConnectViaSpdyProxy) {
14195 base::HistogramTester histograms;
14196 session_deps_.proxy_resolution_service =
14197 ConfiguredProxyResolutionService::CreateFixedForTest(
14198 "https://proxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
14199 session_deps_.net_log = net::NetLog::Get();
14200
14201 const base::TimeDelta kTimeIncrement = base::Seconds(4);
14202 session_deps_.host_resolver->set_ondemand_mode(true);
14203
14204 HttpRequestInfo request;
14205 request.method = "GET";
14206 request.load_flags = LOAD_MAIN_FRAME_DEPRECATED;
14207 request.url = GURL("https://www.example.org/");
14208 request.traffic_annotation =
14209 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
14210
14211 spdy::SpdySerializedFrame conn(spdy_util_.ConstructSpdyConnect(
14212 nullptr, 0, 1, HttpProxyConnectJob::kH2QuicTunnelPriority,
14213 HostPortPair("www.example.org", 443)));
14214 spdy::SpdySerializedFrame goaway(
14215 spdy_util_.ConstructSpdyRstStream(1, spdy::ERROR_CODE_CANCEL));
14216 MockWrite data_writes[] = {
14217 CreateMockWrite(conn, 0, SYNCHRONOUS),
14218 CreateMockWrite(goaway, 3, SYNCHRONOUS),
14219 };
14220
14221 static const char* const kExtraHeaders[] = {
14222 "location",
14223 "http://login.example.com/",
14224 };
14225 spdy::SpdySerializedFrame resp(spdy_util_.ConstructSpdyReplyError(
14226 "302", kExtraHeaders, std::size(kExtraHeaders) / 2, 1));
14227 MockRead data_reads[] = {
14228 // Pause on first read.
14229 MockRead(ASYNC, ERR_IO_PENDING, 1), CreateMockRead(resp, 2),
14230 MockRead(ASYNC, 0, 4), // EOF
14231 };
14232
14233 SequencedSocketData data(MockConnect(ASYNC, OK), data_reads, data_writes);
14234 SSLSocketDataProvider proxy_ssl(ASYNC, OK); // SSL to the proxy
14235 proxy_ssl.next_proto = kProtoHTTP2;
14236
14237 session_deps_.socket_factory->AddSocketDataProvider(&data);
14238 session_deps_.socket_factory->AddSSLSocketDataProvider(&proxy_ssl);
14239
14240 TestCompletionCallback callback;
14241
14242 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
14243 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
14244
14245 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
14246 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
14247 EXPECT_TRUE(session_deps_.host_resolver->has_pending_requests());
14248
14249 // Host resolution takes |kTimeIncrement|.
14250 FastForwardBy(kTimeIncrement);
14251 // Resolving the current request with |ResolveNow| will cause the pending
14252 // request to instantly complete, and the async connect will start as well.
14253 session_deps_.host_resolver->ResolveOnlyRequestNow();
14254
14255 // Connecting takes |kTimeIncrement|.
14256 FastForwardBy(kTimeIncrement);
14257 data.RunUntilPaused();
14258
14259 FastForwardBy(kTimeIncrement);
14260 data.Resume();
14261 rv = callback.WaitForResult();
14262 EXPECT_THAT(rv, IsError(ERR_TUNNEL_CONNECTION_FAILED));
14263 }
14264
14265 // Test that an HTTPS proxy's response to a CONNECT request is filtered.
TEST_P(HttpNetworkTransactionTest,ErrorResponseToHttpsConnectViaHttpsProxy)14266 TEST_P(HttpNetworkTransactionTest, ErrorResponseToHttpsConnectViaHttpsProxy) {
14267 session_deps_.proxy_resolution_service =
14268 ConfiguredProxyResolutionService::CreateFixedForTest(
14269 "https://proxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
14270
14271 HttpRequestInfo request;
14272 request.method = "GET";
14273 request.url = GURL("https://www.example.org/");
14274 request.traffic_annotation =
14275 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
14276
14277 MockWrite data_writes[] = {
14278 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
14279 "Host: www.example.org:443\r\n"
14280 "Proxy-Connection: keep-alive\r\n\r\n"),
14281 };
14282
14283 MockRead data_reads[] = {
14284 MockRead("HTTP/1.1 404 Not Found\r\n"),
14285 MockRead("Content-Length: 23\r\n\r\n"),
14286 MockRead("The host does not exist"),
14287 MockRead(SYNCHRONOUS, OK),
14288 };
14289
14290 StaticSocketDataProvider data(data_reads, data_writes);
14291 SSLSocketDataProvider proxy_ssl(ASYNC, OK); // SSL to the proxy
14292
14293 session_deps_.socket_factory->AddSocketDataProvider(&data);
14294 session_deps_.socket_factory->AddSSLSocketDataProvider(&proxy_ssl);
14295
14296 TestCompletionCallback callback;
14297
14298 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
14299 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
14300
14301 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
14302 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
14303
14304 rv = callback.WaitForResult();
14305 EXPECT_THAT(rv, IsError(ERR_TUNNEL_CONNECTION_FAILED));
14306
14307 // TODO(juliatuttle): Anything else to check here?
14308 }
14309
14310 // Test that a SPDY proxy's response to a CONNECT request is filtered.
TEST_P(HttpNetworkTransactionTest,ErrorResponseToHttpsConnectViaSpdyProxy)14311 TEST_P(HttpNetworkTransactionTest, ErrorResponseToHttpsConnectViaSpdyProxy) {
14312 session_deps_.proxy_resolution_service =
14313 ConfiguredProxyResolutionService::CreateFixedForTest(
14314 "https://proxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
14315
14316 HttpRequestInfo request;
14317 request.method = "GET";
14318 request.url = GURL("https://www.example.org/");
14319 request.traffic_annotation =
14320 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
14321
14322 spdy::SpdySerializedFrame conn(spdy_util_.ConstructSpdyConnect(
14323 nullptr, 0, 1, HttpProxyConnectJob::kH2QuicTunnelPriority,
14324 HostPortPair("www.example.org", 443)));
14325 spdy::SpdySerializedFrame rst(
14326 spdy_util_.ConstructSpdyRstStream(1, spdy::ERROR_CODE_CANCEL));
14327 MockWrite data_writes[] = {
14328 CreateMockWrite(conn, 0),
14329 CreateMockWrite(rst, 3),
14330 };
14331
14332 static const char* const kExtraHeaders[] = {
14333 "location",
14334 "http://login.example.com/",
14335 };
14336 spdy::SpdySerializedFrame resp(spdy_util_.ConstructSpdyReplyError(
14337 "404", kExtraHeaders, std::size(kExtraHeaders) / 2, 1));
14338 spdy::SpdySerializedFrame body(
14339 spdy_util_.ConstructSpdyDataFrame(1, "The host does not exist", true));
14340 MockRead data_reads[] = {
14341 CreateMockRead(resp, 1), CreateMockRead(body, 2),
14342 MockRead(ASYNC, 0, 4), // EOF
14343 };
14344
14345 SequencedSocketData data(data_reads, data_writes);
14346 SSLSocketDataProvider proxy_ssl(ASYNC, OK); // SSL to the proxy
14347 proxy_ssl.next_proto = kProtoHTTP2;
14348
14349 session_deps_.socket_factory->AddSocketDataProvider(&data);
14350 session_deps_.socket_factory->AddSSLSocketDataProvider(&proxy_ssl);
14351
14352 TestCompletionCallback callback;
14353
14354 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
14355 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
14356
14357 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
14358 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
14359
14360 rv = callback.WaitForResult();
14361 EXPECT_THAT(rv, IsError(ERR_TUNNEL_CONNECTION_FAILED));
14362
14363 // TODO(juliatuttle): Anything else to check here?
14364 }
14365
14366 // Test the request-challenge-retry sequence for basic auth, through
14367 // a SPDY proxy over a single SPDY session.
TEST_P(HttpNetworkTransactionTest,BasicAuthSpdyProxy)14368 TEST_P(HttpNetworkTransactionTest, BasicAuthSpdyProxy) {
14369 HttpRequestInfo request;
14370 request.method = "GET";
14371 request.url = GURL("https://www.example.org/");
14372 // when the no authentication data flag is set.
14373 request.privacy_mode = PRIVACY_MODE_ENABLED;
14374 request.traffic_annotation =
14375 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
14376
14377 // Configure against https proxy server "myproxy:70".
14378 session_deps_.proxy_resolution_service =
14379 ConfiguredProxyResolutionService::CreateFixedFromPacResultForTest(
14380 "HTTPS myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
14381 RecordingNetLogObserver net_log_observer;
14382 session_deps_.net_log = NetLog::Get();
14383 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
14384
14385 // Since we have proxy, should try to establish tunnel.
14386 spdy::SpdySerializedFrame req(spdy_util_.ConstructSpdyConnect(
14387 nullptr, 0, 1, HttpProxyConnectJob::kH2QuicTunnelPriority,
14388 HostPortPair("www.example.org", 443)));
14389 spdy::SpdySerializedFrame rst(
14390 spdy_util_.ConstructSpdyRstStream(1, spdy::ERROR_CODE_CANCEL));
14391 spdy_util_.UpdateWithStreamDestruction(1);
14392
14393 // After calling trans.RestartWithAuth(), this is the request we should
14394 // be issuing -- the final header line contains the credentials.
14395 const char* const kAuthCredentials[] = {
14396 "proxy-authorization",
14397 "Basic Zm9vOmJhcg==",
14398 };
14399 spdy::SpdySerializedFrame connect2(spdy_util_.ConstructSpdyConnect(
14400 kAuthCredentials, std::size(kAuthCredentials) / 2, 3,
14401 HttpProxyConnectJob::kH2QuicTunnelPriority,
14402 HostPortPair("www.example.org", 443)));
14403 // fetch https://www.example.org/ via HTTP
14404 const char kGet[] =
14405 "GET / HTTP/1.1\r\n"
14406 "Host: www.example.org\r\n"
14407 "Connection: keep-alive\r\n\r\n";
14408 spdy::SpdySerializedFrame wrapped_get(
14409 spdy_util_.ConstructSpdyDataFrame(3, kGet, false));
14410
14411 MockWrite spdy_writes[] = {
14412 CreateMockWrite(req, 0, ASYNC),
14413 CreateMockWrite(rst, 2, ASYNC),
14414 CreateMockWrite(connect2, 3),
14415 CreateMockWrite(wrapped_get, 5),
14416 };
14417
14418 // The proxy responds to the connect with a 407, using a persistent
14419 // connection.
14420 const char kAuthStatus[] = "407";
14421 const char* const kAuthChallenge[] = {
14422 "proxy-authenticate",
14423 "Basic realm=\"MyRealm1\"",
14424 };
14425 spdy::SpdySerializedFrame conn_auth_resp(spdy_util_.ConstructSpdyReplyError(
14426 kAuthStatus, kAuthChallenge, std::size(kAuthChallenge) / 2, 1));
14427
14428 spdy::SpdySerializedFrame conn_resp(
14429 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 3));
14430 const char kResp[] =
14431 "HTTP/1.1 200 OK\r\n"
14432 "Content-Length: 5\r\n\r\n";
14433
14434 spdy::SpdySerializedFrame wrapped_get_resp(
14435 spdy_util_.ConstructSpdyDataFrame(3, kResp, false));
14436 spdy::SpdySerializedFrame wrapped_body(
14437 spdy_util_.ConstructSpdyDataFrame(3, "hello", false));
14438 MockRead spdy_reads[] = {
14439 CreateMockRead(conn_auth_resp, 1, ASYNC),
14440 CreateMockRead(conn_resp, 4, ASYNC),
14441 CreateMockRead(wrapped_get_resp, 6, ASYNC),
14442 CreateMockRead(wrapped_body, 7, ASYNC),
14443 MockRead(ASYNC, OK, 8), // EOF. May or may not be read.
14444 };
14445
14446 SequencedSocketData spdy_data(spdy_reads, spdy_writes);
14447 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
14448 // Negotiate SPDY to the proxy
14449 SSLSocketDataProvider proxy(ASYNC, OK);
14450 proxy.next_proto = kProtoHTTP2;
14451 session_deps_.socket_factory->AddSSLSocketDataProvider(&proxy);
14452 // Vanilla SSL to the server
14453 SSLSocketDataProvider server(ASYNC, OK);
14454 session_deps_.socket_factory->AddSSLSocketDataProvider(&server);
14455
14456 TestCompletionCallback callback1;
14457
14458 auto trans =
14459 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
14460
14461 int rv = trans->Start(&request, callback1.callback(),
14462 NetLogWithSource::Make(NetLogSourceType::NONE));
14463 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
14464
14465 rv = callback1.WaitForResult();
14466 EXPECT_THAT(rv, IsOk());
14467 auto entries = net_log_observer.GetEntries();
14468 size_t pos = ExpectLogContainsSomewhere(
14469 entries, 0, NetLogEventType::HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
14470 NetLogEventPhase::NONE);
14471 ExpectLogContainsSomewhere(
14472 entries, pos,
14473 NetLogEventType::HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
14474 NetLogEventPhase::NONE);
14475
14476 const HttpResponseInfo* response = trans->GetResponseInfo();
14477 ASSERT_TRUE(response);
14478 ASSERT_TRUE(response->headers);
14479 EXPECT_EQ(407, response->headers->response_code());
14480 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
14481 EXPECT_TRUE(response->auth_challenge.has_value());
14482 EXPECT_TRUE(CheckBasicSecureProxyAuth(response->auth_challenge));
14483
14484 TestCompletionCallback callback2;
14485
14486 rv =
14487 trans->RestartWithAuth(AuthCredentials(kFoo, kBar), callback2.callback());
14488 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
14489
14490 rv = callback2.WaitForResult();
14491 EXPECT_THAT(rv, IsOk());
14492
14493 response = trans->GetResponseInfo();
14494 ASSERT_TRUE(response);
14495
14496 EXPECT_TRUE(response->headers->IsKeepAlive());
14497 EXPECT_EQ(200, response->headers->response_code());
14498 EXPECT_EQ(5, response->headers->GetContentLength());
14499 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
14500
14501 // The password prompt info should not be set.
14502 EXPECT_FALSE(response->auth_challenge.has_value());
14503
14504 LoadTimingInfo load_timing_info;
14505 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
14506 TestLoadTimingNotReusedWithPac(load_timing_info,
14507 CONNECT_TIMING_HAS_SSL_TIMES);
14508
14509 trans.reset();
14510 session->CloseAllConnections(ERR_FAILED, "Very good reason");
14511 }
14512
14513 // Test HTTPS connections to a site with a bad certificate, going through an
14514 // HTTPS proxy
TEST_P(HttpNetworkTransactionTest,HTTPSBadCertificateViaHttpsProxy)14515 TEST_P(HttpNetworkTransactionTest, HTTPSBadCertificateViaHttpsProxy) {
14516 session_deps_.proxy_resolution_service =
14517 ConfiguredProxyResolutionService::CreateFixedForTest(
14518 "https://proxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
14519
14520 HttpRequestInfo request;
14521 request.method = "GET";
14522 request.url = GURL("https://www.example.org/");
14523 request.traffic_annotation =
14524 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
14525
14526 // Attempt to fetch the URL from a server with a bad cert
14527 MockWrite bad_cert_writes[] = {
14528 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
14529 "Host: www.example.org:443\r\n"
14530 "Proxy-Connection: keep-alive\r\n\r\n"),
14531 };
14532
14533 MockRead bad_cert_reads[] = {MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
14534 MockRead(SYNCHRONOUS, OK)};
14535
14536 // Attempt to fetch the URL with a good cert
14537 MockWrite good_data_writes[] = {
14538 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
14539 "Host: www.example.org:443\r\n"
14540 "Proxy-Connection: keep-alive\r\n\r\n"),
14541 MockWrite("GET / HTTP/1.1\r\n"
14542 "Host: www.example.org\r\n"
14543 "Connection: keep-alive\r\n\r\n"),
14544 };
14545
14546 MockRead good_cert_reads[] = {
14547 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
14548 MockRead("HTTP/1.0 200 OK\r\n"),
14549 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
14550 MockRead("Content-Length: 100\r\n\r\n"),
14551 MockRead(SYNCHRONOUS, OK),
14552 };
14553
14554 StaticSocketDataProvider ssl_bad_certificate(bad_cert_reads, bad_cert_writes);
14555 StaticSocketDataProvider data(good_cert_reads, good_data_writes);
14556 SSLSocketDataProvider ssl_bad(ASYNC, ERR_CERT_AUTHORITY_INVALID);
14557 SSLSocketDataProvider ssl(ASYNC, OK);
14558
14559 // SSL to the proxy, then CONNECT request, then SSL with bad certificate
14560 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
14561 session_deps_.socket_factory->AddSocketDataProvider(&ssl_bad_certificate);
14562 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_bad);
14563
14564 // SSL to the proxy, then CONNECT request, then valid SSL certificate
14565 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
14566 session_deps_.socket_factory->AddSocketDataProvider(&data);
14567 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
14568
14569 TestCompletionCallback callback;
14570
14571 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
14572 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
14573
14574 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
14575 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
14576
14577 rv = callback.WaitForResult();
14578 EXPECT_THAT(rv, IsError(ERR_CERT_AUTHORITY_INVALID));
14579
14580 rv = trans.RestartIgnoringLastError(callback.callback());
14581 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
14582
14583 rv = callback.WaitForResult();
14584 EXPECT_THAT(rv, IsOk());
14585
14586 const HttpResponseInfo* response = trans.GetResponseInfo();
14587
14588 ASSERT_TRUE(response);
14589 EXPECT_EQ(100, response->headers->GetContentLength());
14590 }
14591
TEST_P(HttpNetworkTransactionTest,BuildRequest_UserAgent)14592 TEST_P(HttpNetworkTransactionTest, BuildRequest_UserAgent) {
14593 HttpRequestInfo request;
14594 request.method = "GET";
14595 request.url = GURL("http://www.example.org/");
14596 request.extra_headers.SetHeader(HttpRequestHeaders::kUserAgent,
14597 "Chromium Ultra Awesome X Edition");
14598 request.traffic_annotation =
14599 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
14600
14601 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
14602 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
14603
14604 MockWrite data_writes[] = {
14605 MockWrite("GET / HTTP/1.1\r\n"
14606 "Host: www.example.org\r\n"
14607 "Connection: keep-alive\r\n"
14608 "User-Agent: Chromium Ultra Awesome X Edition\r\n\r\n"),
14609 };
14610
14611 // Lastly, the server responds with the actual content.
14612 MockRead data_reads[] = {
14613 MockRead("HTTP/1.0 200 OK\r\n"),
14614 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
14615 MockRead("Content-Length: 100\r\n\r\n"),
14616 MockRead(SYNCHRONOUS, OK),
14617 };
14618
14619 StaticSocketDataProvider data(data_reads, data_writes);
14620 session_deps_.socket_factory->AddSocketDataProvider(&data);
14621
14622 TestCompletionCallback callback;
14623
14624 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
14625 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
14626
14627 rv = callback.WaitForResult();
14628 EXPECT_THAT(rv, IsOk());
14629 }
14630
TEST_P(HttpNetworkTransactionTest,BuildRequest_UserAgentOverTunnel)14631 TEST_P(HttpNetworkTransactionTest, BuildRequest_UserAgentOverTunnel) {
14632 // Test user agent values, used both for the request header of the original
14633 // request, and the value returned by the HttpUserAgentSettings. nullptr means
14634 // no request header / no HttpUserAgentSettings object.
14635 const char* kTestUserAgents[] = {nullptr, "", "Foopy"};
14636
14637 for (const char* setting_user_agent : kTestUserAgents) {
14638 if (!setting_user_agent) {
14639 session_deps_.http_user_agent_settings.reset();
14640 } else {
14641 session_deps_.http_user_agent_settings =
14642 std::make_unique<StaticHttpUserAgentSettings>(
14643 std::string() /* accept-language */, setting_user_agent);
14644 }
14645 session_deps_.proxy_resolution_service =
14646 ConfiguredProxyResolutionService::CreateFixedForTest(
14647 "myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
14648 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
14649 for (const char* request_user_agent : kTestUserAgents) {
14650 HttpRequestInfo request;
14651 request.method = "GET";
14652 request.url = GURL("https://www.example.org/");
14653 if (request_user_agent) {
14654 request.extra_headers.SetHeader(HttpRequestHeaders::kUserAgent,
14655 request_user_agent);
14656 }
14657 request.traffic_annotation =
14658 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
14659
14660 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
14661
14662 std::string expected_request;
14663 if (!setting_user_agent || strlen(setting_user_agent) == 0) {
14664 expected_request =
14665 "CONNECT www.example.org:443 HTTP/1.1\r\n"
14666 "Host: www.example.org:443\r\n"
14667 "Proxy-Connection: keep-alive\r\n\r\n";
14668 } else {
14669 expected_request = base::StringPrintf(
14670 "CONNECT www.example.org:443 HTTP/1.1\r\n"
14671 "Host: www.example.org:443\r\n"
14672 "Proxy-Connection: keep-alive\r\n"
14673 "User-Agent: %s\r\n\r\n",
14674 setting_user_agent);
14675 }
14676 MockWrite data_writes[] = {
14677 MockWrite(expected_request.c_str()),
14678 };
14679 MockRead data_reads[] = {
14680 // Return an error, so the transaction stops here (this test isn't
14681 // interested in the rest).
14682 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
14683 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
14684 MockRead("Proxy-Connection: close\r\n\r\n"),
14685 };
14686
14687 StaticSocketDataProvider data(data_reads, data_writes);
14688 session_deps_.socket_factory->AddSocketDataProvider(&data);
14689
14690 TestCompletionCallback callback;
14691
14692 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
14693 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
14694
14695 rv = callback.WaitForResult();
14696 EXPECT_THAT(rv, IsOk());
14697 }
14698 }
14699 }
14700
TEST_P(HttpNetworkTransactionTest,BuildRequest_Referer)14701 TEST_P(HttpNetworkTransactionTest, BuildRequest_Referer) {
14702 HttpRequestInfo request;
14703 request.method = "GET";
14704 request.url = GURL("http://www.example.org/");
14705 request.extra_headers.SetHeader(HttpRequestHeaders::kReferer,
14706 "http://the.previous.site.com/");
14707 request.traffic_annotation =
14708 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
14709
14710 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
14711 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
14712
14713 MockWrite data_writes[] = {
14714 MockWrite("GET / HTTP/1.1\r\n"
14715 "Host: www.example.org\r\n"
14716 "Connection: keep-alive\r\n"
14717 "Referer: http://the.previous.site.com/\r\n\r\n"),
14718 };
14719
14720 // Lastly, the server responds with the actual content.
14721 MockRead data_reads[] = {
14722 MockRead("HTTP/1.0 200 OK\r\n"),
14723 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
14724 MockRead("Content-Length: 100\r\n\r\n"),
14725 MockRead(SYNCHRONOUS, OK),
14726 };
14727
14728 StaticSocketDataProvider data(data_reads, data_writes);
14729 session_deps_.socket_factory->AddSocketDataProvider(&data);
14730
14731 TestCompletionCallback callback;
14732
14733 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
14734 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
14735
14736 rv = callback.WaitForResult();
14737 EXPECT_THAT(rv, IsOk());
14738 }
14739
TEST_P(HttpNetworkTransactionTest,BuildRequest_PostContentLengthZero)14740 TEST_P(HttpNetworkTransactionTest, BuildRequest_PostContentLengthZero) {
14741 HttpRequestInfo request;
14742 request.method = "POST";
14743 request.url = GURL("http://www.example.org/");
14744 request.traffic_annotation =
14745 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
14746
14747 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
14748 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
14749
14750 MockWrite data_writes[] = {
14751 MockWrite("POST / HTTP/1.1\r\n"
14752 "Host: www.example.org\r\n"
14753 "Connection: keep-alive\r\n"
14754 "Content-Length: 0\r\n\r\n"),
14755 };
14756
14757 // Lastly, the server responds with the actual content.
14758 MockRead data_reads[] = {
14759 MockRead("HTTP/1.0 200 OK\r\n"),
14760 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
14761 MockRead("Content-Length: 100\r\n\r\n"),
14762 MockRead(SYNCHRONOUS, OK),
14763 };
14764
14765 StaticSocketDataProvider data(data_reads, data_writes);
14766 session_deps_.socket_factory->AddSocketDataProvider(&data);
14767
14768 TestCompletionCallback callback;
14769
14770 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
14771 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
14772
14773 rv = callback.WaitForResult();
14774 EXPECT_THAT(rv, IsOk());
14775 }
14776
TEST_P(HttpNetworkTransactionTest,BuildRequest_PutContentLengthZero)14777 TEST_P(HttpNetworkTransactionTest, BuildRequest_PutContentLengthZero) {
14778 HttpRequestInfo request;
14779 request.method = "PUT";
14780 request.url = GURL("http://www.example.org/");
14781 request.traffic_annotation =
14782 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
14783
14784 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
14785 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
14786
14787 MockWrite data_writes[] = {
14788 MockWrite("PUT / HTTP/1.1\r\n"
14789 "Host: www.example.org\r\n"
14790 "Connection: keep-alive\r\n"
14791 "Content-Length: 0\r\n\r\n"),
14792 };
14793
14794 // Lastly, the server responds with the actual content.
14795 MockRead data_reads[] = {
14796 MockRead("HTTP/1.0 200 OK\r\n"),
14797 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
14798 MockRead("Content-Length: 100\r\n\r\n"),
14799 MockRead(SYNCHRONOUS, OK),
14800 };
14801
14802 StaticSocketDataProvider data(data_reads, data_writes);
14803 session_deps_.socket_factory->AddSocketDataProvider(&data);
14804
14805 TestCompletionCallback callback;
14806
14807 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
14808 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
14809
14810 rv = callback.WaitForResult();
14811 EXPECT_THAT(rv, IsOk());
14812 }
14813
TEST_P(HttpNetworkTransactionTest,BuildRequest_HeadContentLengthZero)14814 TEST_P(HttpNetworkTransactionTest, BuildRequest_HeadContentLengthZero) {
14815 HttpRequestInfo request;
14816 request.method = "HEAD";
14817 request.url = GURL("http://www.example.org/");
14818 request.traffic_annotation =
14819 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
14820
14821 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
14822 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
14823
14824 MockWrite data_writes[] = {
14825 MockWrite("HEAD / HTTP/1.1\r\n"
14826 "Host: www.example.org\r\n"
14827 "Connection: keep-alive\r\n\r\n"),
14828 };
14829
14830 // Lastly, the server responds with the actual content.
14831 MockRead data_reads[] = {
14832 MockRead("HTTP/1.0 200 OK\r\n"),
14833 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
14834 MockRead("Content-Length: 100\r\n\r\n"),
14835 MockRead(SYNCHRONOUS, OK),
14836 };
14837
14838 StaticSocketDataProvider data(data_reads, data_writes);
14839 session_deps_.socket_factory->AddSocketDataProvider(&data);
14840
14841 TestCompletionCallback callback;
14842
14843 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
14844 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
14845
14846 rv = callback.WaitForResult();
14847 EXPECT_THAT(rv, IsOk());
14848 }
14849
TEST_P(HttpNetworkTransactionTest,BuildRequest_CacheControlNoCache)14850 TEST_P(HttpNetworkTransactionTest, BuildRequest_CacheControlNoCache) {
14851 HttpRequestInfo request;
14852 request.method = "GET";
14853 request.url = GURL("http://www.example.org/");
14854 request.load_flags = LOAD_BYPASS_CACHE;
14855 request.traffic_annotation =
14856 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
14857
14858 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
14859 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
14860
14861 MockWrite data_writes[] = {
14862 MockWrite("GET / HTTP/1.1\r\n"
14863 "Host: www.example.org\r\n"
14864 "Connection: keep-alive\r\n"
14865 "Pragma: no-cache\r\n"
14866 "Cache-Control: no-cache\r\n\r\n"),
14867 };
14868
14869 // Lastly, the server responds with the actual content.
14870 MockRead data_reads[] = {
14871 MockRead("HTTP/1.0 200 OK\r\n"),
14872 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
14873 MockRead("Content-Length: 100\r\n\r\n"),
14874 MockRead(SYNCHRONOUS, OK),
14875 };
14876
14877 StaticSocketDataProvider data(data_reads, data_writes);
14878 session_deps_.socket_factory->AddSocketDataProvider(&data);
14879
14880 TestCompletionCallback callback;
14881
14882 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
14883 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
14884
14885 rv = callback.WaitForResult();
14886 EXPECT_THAT(rv, IsOk());
14887 }
14888
TEST_P(HttpNetworkTransactionTest,BuildRequest_CacheControlValidateCache)14889 TEST_P(HttpNetworkTransactionTest, BuildRequest_CacheControlValidateCache) {
14890 HttpRequestInfo request;
14891 request.method = "GET";
14892 request.url = GURL("http://www.example.org/");
14893 request.load_flags = LOAD_VALIDATE_CACHE;
14894 request.traffic_annotation =
14895 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
14896
14897 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
14898 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
14899
14900 MockWrite data_writes[] = {
14901 MockWrite("GET / HTTP/1.1\r\n"
14902 "Host: www.example.org\r\n"
14903 "Connection: keep-alive\r\n"
14904 "Cache-Control: max-age=0\r\n\r\n"),
14905 };
14906
14907 // Lastly, the server responds with the actual content.
14908 MockRead data_reads[] = {
14909 MockRead("HTTP/1.0 200 OK\r\n"),
14910 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
14911 MockRead("Content-Length: 100\r\n\r\n"),
14912 MockRead(SYNCHRONOUS, OK),
14913 };
14914
14915 StaticSocketDataProvider data(data_reads, data_writes);
14916 session_deps_.socket_factory->AddSocketDataProvider(&data);
14917
14918 TestCompletionCallback callback;
14919
14920 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
14921 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
14922
14923 rv = callback.WaitForResult();
14924 EXPECT_THAT(rv, IsOk());
14925 }
14926
TEST_P(HttpNetworkTransactionTest,BuildRequest_ExtraHeaders)14927 TEST_P(HttpNetworkTransactionTest, BuildRequest_ExtraHeaders) {
14928 HttpRequestInfo request;
14929 request.method = "GET";
14930 request.url = GURL("http://www.example.org/");
14931 request.extra_headers.SetHeader("FooHeader", "Bar");
14932 request.traffic_annotation =
14933 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
14934
14935 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
14936 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
14937
14938 MockWrite data_writes[] = {
14939 MockWrite("GET / HTTP/1.1\r\n"
14940 "Host: www.example.org\r\n"
14941 "Connection: keep-alive\r\n"
14942 "FooHeader: Bar\r\n\r\n"),
14943 };
14944
14945 // Lastly, the server responds with the actual content.
14946 MockRead data_reads[] = {
14947 MockRead("HTTP/1.0 200 OK\r\n"),
14948 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
14949 MockRead("Content-Length: 100\r\n\r\n"),
14950 MockRead(SYNCHRONOUS, OK),
14951 };
14952
14953 StaticSocketDataProvider data(data_reads, data_writes);
14954 session_deps_.socket_factory->AddSocketDataProvider(&data);
14955
14956 TestCompletionCallback callback;
14957
14958 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
14959 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
14960
14961 rv = callback.WaitForResult();
14962 EXPECT_THAT(rv, IsOk());
14963 }
14964
TEST_P(HttpNetworkTransactionTest,BuildRequest_ExtraHeadersStripped)14965 TEST_P(HttpNetworkTransactionTest, BuildRequest_ExtraHeadersStripped) {
14966 HttpRequestInfo request;
14967 request.method = "GET";
14968 request.url = GURL("http://www.example.org/");
14969 request.extra_headers.SetHeader("referer", "www.foo.com");
14970 request.extra_headers.SetHeader("hEllo", "Kitty");
14971 request.extra_headers.SetHeader("FoO", "bar");
14972 request.traffic_annotation =
14973 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
14974
14975 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
14976 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
14977
14978 MockWrite data_writes[] = {
14979 MockWrite("GET / HTTP/1.1\r\n"
14980 "Host: www.example.org\r\n"
14981 "Connection: keep-alive\r\n"
14982 "referer: www.foo.com\r\n"
14983 "hEllo: Kitty\r\n"
14984 "FoO: bar\r\n\r\n"),
14985 };
14986
14987 // Lastly, the server responds with the actual content.
14988 MockRead data_reads[] = {
14989 MockRead("HTTP/1.0 200 OK\r\n"),
14990 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
14991 MockRead("Content-Length: 100\r\n\r\n"),
14992 MockRead(SYNCHRONOUS, OK),
14993 };
14994
14995 StaticSocketDataProvider data(data_reads, data_writes);
14996 session_deps_.socket_factory->AddSocketDataProvider(&data);
14997
14998 TestCompletionCallback callback;
14999
15000 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
15001 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
15002
15003 rv = callback.WaitForResult();
15004 EXPECT_THAT(rv, IsOk());
15005 }
15006
TEST_P(HttpNetworkTransactionTest,SOCKS4_HTTP_GET)15007 TEST_P(HttpNetworkTransactionTest, SOCKS4_HTTP_GET) {
15008 HttpRequestInfo request;
15009 request.method = "GET";
15010 request.url = GURL("http://www.example.org/");
15011 request.traffic_annotation =
15012 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
15013
15014 session_deps_.proxy_resolution_service =
15015 ConfiguredProxyResolutionService::CreateFixedFromPacResultForTest(
15016 "SOCKS myproxy:1080", TRAFFIC_ANNOTATION_FOR_TESTS);
15017 session_deps_.net_log = net::NetLog::Get();
15018
15019 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
15020 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
15021
15022 char write_buffer[] = {0x04, 0x01, 0x00, 0x50, 127, 0, 0, 1, 0};
15023 char read_buffer[] = {0x00, 0x5A, 0x00, 0x00, 0, 0, 0, 0};
15024
15025 MockWrite data_writes[] = {
15026 MockWrite(ASYNC, write_buffer, std::size(write_buffer)),
15027 MockWrite("GET / HTTP/1.1\r\n"
15028 "Host: www.example.org\r\n"
15029 "Connection: keep-alive\r\n\r\n")};
15030
15031 MockRead data_reads[] = {
15032 MockRead(ASYNC, read_buffer, std::size(read_buffer)),
15033 MockRead("HTTP/1.0 200 OK\r\n"),
15034 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
15035 MockRead("Payload"), MockRead(SYNCHRONOUS, OK)};
15036
15037 StaticSocketDataProvider data(data_reads, data_writes);
15038 session_deps_.socket_factory->AddSocketDataProvider(&data);
15039
15040 TestCompletionCallback callback;
15041
15042 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
15043 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
15044
15045 rv = callback.WaitForResult();
15046 EXPECT_THAT(rv, IsOk());
15047
15048 const HttpResponseInfo* response = trans.GetResponseInfo();
15049 ASSERT_TRUE(response);
15050
15051 ASSERT_EQ(1u, response->proxy_chain.length());
15052 EXPECT_EQ(ProxyServer::SCHEME_SOCKS4,
15053 response->proxy_chain.GetProxyServer(0).scheme());
15054 LoadTimingInfo load_timing_info;
15055 EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info));
15056 TestLoadTimingNotReusedWithPac(load_timing_info,
15057 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY);
15058
15059 std::string response_text;
15060 rv = ReadTransaction(&trans, &response_text);
15061 EXPECT_THAT(rv, IsOk());
15062 EXPECT_EQ("Payload", response_text);
15063 }
15064
TEST_P(HttpNetworkTransactionTest,SOCKS4_SSL_GET)15065 TEST_P(HttpNetworkTransactionTest, SOCKS4_SSL_GET) {
15066 HttpRequestInfo request;
15067 request.method = "GET";
15068 request.url = GURL("https://www.example.org/");
15069 request.traffic_annotation =
15070 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
15071
15072 session_deps_.proxy_resolution_service =
15073 ConfiguredProxyResolutionService::CreateFixedFromPacResultForTest(
15074 "SOCKS myproxy:1080", TRAFFIC_ANNOTATION_FOR_TESTS);
15075 session_deps_.net_log = net::NetLog::Get();
15076
15077 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
15078 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
15079
15080 unsigned char write_buffer[] = {0x04, 0x01, 0x01, 0xBB, 127, 0, 0, 1, 0};
15081 unsigned char read_buffer[] = {0x00, 0x5A, 0x00, 0x00, 0, 0, 0, 0};
15082
15083 MockWrite data_writes[] = {
15084 MockWrite(ASYNC, reinterpret_cast<char*>(write_buffer),
15085 std::size(write_buffer)),
15086 MockWrite("GET / HTTP/1.1\r\n"
15087 "Host: www.example.org\r\n"
15088 "Connection: keep-alive\r\n\r\n")};
15089
15090 MockRead data_reads[] = {
15091 MockRead(ASYNC, reinterpret_cast<char*>(read_buffer),
15092 std::size(read_buffer)),
15093 MockRead("HTTP/1.0 200 OK\r\n"),
15094 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
15095 MockRead("Payload"), MockRead(SYNCHRONOUS, OK)};
15096
15097 StaticSocketDataProvider data(data_reads, data_writes);
15098 session_deps_.socket_factory->AddSocketDataProvider(&data);
15099
15100 SSLSocketDataProvider ssl(ASYNC, OK);
15101 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
15102
15103 TestCompletionCallback callback;
15104
15105 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
15106 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
15107
15108 rv = callback.WaitForResult();
15109 EXPECT_THAT(rv, IsOk());
15110
15111 LoadTimingInfo load_timing_info;
15112 EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info));
15113 TestLoadTimingNotReusedWithPac(load_timing_info,
15114 CONNECT_TIMING_HAS_SSL_TIMES);
15115
15116 const HttpResponseInfo* response = trans.GetResponseInfo();
15117 ASSERT_TRUE(response);
15118 ASSERT_EQ(1u, response->proxy_chain.length());
15119 EXPECT_EQ(ProxyServer::SCHEME_SOCKS4,
15120 response->proxy_chain.GetProxyServer(0).scheme());
15121
15122 std::string response_text;
15123 rv = ReadTransaction(&trans, &response_text);
15124 EXPECT_THAT(rv, IsOk());
15125 EXPECT_EQ("Payload", response_text);
15126 }
15127
TEST_P(HttpNetworkTransactionTest,SOCKS4_HTTP_GET_no_PAC)15128 TEST_P(HttpNetworkTransactionTest, SOCKS4_HTTP_GET_no_PAC) {
15129 HttpRequestInfo request;
15130 request.method = "GET";
15131 request.url = GURL("http://www.example.org/");
15132 request.traffic_annotation =
15133 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
15134
15135 session_deps_.proxy_resolution_service =
15136 ConfiguredProxyResolutionService::CreateFixedForTest(
15137 "socks4://myproxy:1080", TRAFFIC_ANNOTATION_FOR_TESTS);
15138 session_deps_.net_log = net::NetLog::Get();
15139
15140 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
15141 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
15142
15143 char write_buffer[] = {0x04, 0x01, 0x00, 0x50, 127, 0, 0, 1, 0};
15144 char read_buffer[] = {0x00, 0x5A, 0x00, 0x00, 0, 0, 0, 0};
15145
15146 MockWrite data_writes[] = {
15147 MockWrite(ASYNC, write_buffer, std::size(write_buffer)),
15148 MockWrite("GET / HTTP/1.1\r\n"
15149 "Host: www.example.org\r\n"
15150 "Connection: keep-alive\r\n\r\n")};
15151
15152 MockRead data_reads[] = {
15153 MockRead(ASYNC, read_buffer, std::size(read_buffer)),
15154 MockRead("HTTP/1.0 200 OK\r\n"),
15155 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
15156 MockRead("Payload"), MockRead(SYNCHRONOUS, OK)};
15157
15158 StaticSocketDataProvider data(data_reads, data_writes);
15159 session_deps_.socket_factory->AddSocketDataProvider(&data);
15160
15161 TestCompletionCallback callback;
15162
15163 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
15164 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
15165
15166 rv = callback.WaitForResult();
15167 EXPECT_THAT(rv, IsOk());
15168
15169 const HttpResponseInfo* response = trans.GetResponseInfo();
15170 ASSERT_TRUE(response);
15171
15172 LoadTimingInfo load_timing_info;
15173 EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info));
15174 TestLoadTimingNotReused(load_timing_info,
15175 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY);
15176
15177 std::string response_text;
15178 rv = ReadTransaction(&trans, &response_text);
15179 EXPECT_THAT(rv, IsOk());
15180 EXPECT_EQ("Payload", response_text);
15181 }
15182
TEST_P(HttpNetworkTransactionTest,SOCKS5_HTTP_GET)15183 TEST_P(HttpNetworkTransactionTest, SOCKS5_HTTP_GET) {
15184 HttpRequestInfo request;
15185 request.method = "GET";
15186 request.url = GURL("http://www.example.org/");
15187 request.traffic_annotation =
15188 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
15189
15190 session_deps_.proxy_resolution_service =
15191 ConfiguredProxyResolutionService::CreateFixedFromPacResultForTest(
15192 "SOCKS5 myproxy:1080", TRAFFIC_ANNOTATION_FOR_TESTS);
15193 session_deps_.net_log = net::NetLog::Get();
15194
15195 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
15196 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
15197
15198 const char kSOCKS5ExampleOkRequest[] = {
15199 0x05, // Version
15200 0x01, // Command (CONNECT)
15201 0x00, // Reserved.
15202 0x03, // Address type (DOMAINNAME).
15203 0x0F, // Length of domain (15)
15204 'w', 'w', 'w', '.', 'e', 'x',
15205 'a', 'm', 'p', 'l', 'e', // Domain string
15206 '.', 'o', 'r', 'g', 0x00, 0x50, // 16-bit port (80)
15207 };
15208
15209 MockWrite data_writes[] = {
15210 MockWrite(ASYNC, kSOCKS5GreetRequest, kSOCKS5GreetRequestLength),
15211 MockWrite(ASYNC, kSOCKS5ExampleOkRequest,
15212 std::size(kSOCKS5ExampleOkRequest)),
15213 MockWrite("GET / HTTP/1.1\r\n"
15214 "Host: www.example.org\r\n"
15215 "Connection: keep-alive\r\n\r\n")};
15216
15217 MockRead data_reads[] = {
15218 MockRead(ASYNC, kSOCKS5GreetResponse, kSOCKS5GreetResponseLength),
15219 MockRead(ASYNC, kSOCKS5OkResponse, kSOCKS5OkResponseLength),
15220 MockRead("HTTP/1.0 200 OK\r\n"),
15221 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
15222 MockRead("Payload"),
15223 MockRead(SYNCHRONOUS, OK)};
15224
15225 StaticSocketDataProvider data(data_reads, data_writes);
15226 session_deps_.socket_factory->AddSocketDataProvider(&data);
15227
15228 TestCompletionCallback callback;
15229
15230 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
15231 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
15232
15233 rv = callback.WaitForResult();
15234 EXPECT_THAT(rv, IsOk());
15235
15236 const HttpResponseInfo* response = trans.GetResponseInfo();
15237 ASSERT_TRUE(response);
15238 ASSERT_EQ(1u, response->proxy_chain.length());
15239 EXPECT_EQ(ProxyServer::SCHEME_SOCKS5,
15240 response->proxy_chain.GetProxyServer(0).scheme());
15241
15242 LoadTimingInfo load_timing_info;
15243 EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info));
15244 TestLoadTimingNotReusedWithPac(load_timing_info,
15245 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY);
15246
15247 std::string response_text;
15248 rv = ReadTransaction(&trans, &response_text);
15249 EXPECT_THAT(rv, IsOk());
15250 EXPECT_EQ("Payload", response_text);
15251 }
15252
TEST_P(HttpNetworkTransactionTest,SOCKS5_SSL_GET)15253 TEST_P(HttpNetworkTransactionTest, SOCKS5_SSL_GET) {
15254 HttpRequestInfo request;
15255 request.method = "GET";
15256 request.url = GURL("https://www.example.org/");
15257 request.traffic_annotation =
15258 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
15259
15260 session_deps_.proxy_resolution_service =
15261 ConfiguredProxyResolutionService::CreateFixedFromPacResultForTest(
15262 "SOCKS5 myproxy:1080", TRAFFIC_ANNOTATION_FOR_TESTS);
15263 session_deps_.net_log = net::NetLog::Get();
15264
15265 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
15266 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
15267
15268 const unsigned char kSOCKS5ExampleOkRequest[] = {
15269 0x05, // Version
15270 0x01, // Command (CONNECT)
15271 0x00, // Reserved.
15272 0x03, // Address type (DOMAINNAME).
15273 0x0F, // Length of domain (15)
15274 'w', 'w', 'w', '.', 'e', 'x',
15275 'a', 'm', 'p', 'l', 'e', // Domain string
15276 '.', 'o', 'r', 'g', 0x01, 0xBB, // 16-bit port (443)
15277 };
15278
15279 const char kSOCKS5SslOkResponse[] = {0x05, 0x00, 0x00, 0x01, 0,
15280 0, 0, 0, 0x00, 0x00};
15281
15282 MockWrite data_writes[] = {
15283 MockWrite(ASYNC, kSOCKS5GreetRequest, kSOCKS5GreetRequestLength),
15284 MockWrite(ASYNC, reinterpret_cast<const char*>(kSOCKS5ExampleOkRequest),
15285 std::size(kSOCKS5ExampleOkRequest)),
15286 MockWrite("GET / HTTP/1.1\r\n"
15287 "Host: www.example.org\r\n"
15288 "Connection: keep-alive\r\n\r\n")};
15289
15290 MockRead data_reads[] = {
15291 MockRead(ASYNC, kSOCKS5GreetResponse, kSOCKS5GreetResponseLength),
15292 MockRead(ASYNC, kSOCKS5SslOkResponse, std::size(kSOCKS5SslOkResponse)),
15293 MockRead("HTTP/1.0 200 OK\r\n"),
15294 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
15295 MockRead("Payload"),
15296 MockRead(SYNCHRONOUS, OK)};
15297
15298 StaticSocketDataProvider data(data_reads, data_writes);
15299 session_deps_.socket_factory->AddSocketDataProvider(&data);
15300
15301 SSLSocketDataProvider ssl(ASYNC, OK);
15302 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
15303
15304 TestCompletionCallback callback;
15305
15306 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
15307 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
15308
15309 rv = callback.WaitForResult();
15310 EXPECT_THAT(rv, IsOk());
15311
15312 const HttpResponseInfo* response = trans.GetResponseInfo();
15313 ASSERT_TRUE(response);
15314 ASSERT_EQ(1u, response->proxy_chain.length());
15315 EXPECT_EQ(ProxyServer::SCHEME_SOCKS5,
15316 response->proxy_chain.GetProxyServer(0).scheme());
15317
15318 LoadTimingInfo load_timing_info;
15319 EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info));
15320 TestLoadTimingNotReusedWithPac(load_timing_info,
15321 CONNECT_TIMING_HAS_SSL_TIMES);
15322
15323 std::string response_text;
15324 rv = ReadTransaction(&trans, &response_text);
15325 EXPECT_THAT(rv, IsOk());
15326 EXPECT_EQ("Payload", response_text);
15327 }
15328
15329 namespace {
15330
15331 // Tests that for connection endpoints the group ids are correctly set.
15332
15333 struct GroupIdTest {
15334 std::string proxy_chain;
15335 std::string url;
15336 ClientSocketPool::GroupId expected_group_id;
15337 bool ssl;
15338 };
15339
SetupSessionForGroupIdTests(SpdySessionDependencies * session_deps_)15340 std::unique_ptr<HttpNetworkSession> SetupSessionForGroupIdTests(
15341 SpdySessionDependencies* session_deps_) {
15342 std::unique_ptr<HttpNetworkSession> session(CreateSession(session_deps_));
15343
15344 HttpServerProperties* http_server_properties =
15345 session->http_server_properties();
15346 AlternativeService alternative_service(kProtoHTTP2, "", 444);
15347 base::Time expiration = base::Time::Now() + base::Days(1);
15348 http_server_properties->SetHttp2AlternativeService(
15349 url::SchemeHostPort("https", "host.with.alternate", 443),
15350 NetworkAnonymizationKey(), alternative_service, expiration);
15351
15352 return session;
15353 }
15354
GroupIdTransactionHelper(const std::string & url,HttpNetworkSession * session)15355 int GroupIdTransactionHelper(const std::string& url,
15356 HttpNetworkSession* session) {
15357 HttpRequestInfo request;
15358 request.method = "GET";
15359 request.url = GURL(url);
15360 request.traffic_annotation =
15361 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
15362
15363 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session);
15364
15365 TestCompletionCallback callback;
15366
15367 // We do not complete this request, the dtor will clean the transaction up.
15368 return trans.Start(&request, callback.callback(), NetLogWithSource());
15369 }
15370
15371 } // namespace
15372
TEST_P(HttpNetworkTransactionTest,GroupIdForDirectConnections)15373 TEST_P(HttpNetworkTransactionTest, GroupIdForDirectConnections) {
15374 const GroupIdTest tests[] = {
15375 {
15376 "", // unused
15377 "http://www.example.org/direct",
15378 ClientSocketPool::GroupId(
15379 url::SchemeHostPort(url::kHttpScheme, "www.example.org", 80),
15380 PrivacyMode::PRIVACY_MODE_DISABLED, NetworkAnonymizationKey(),
15381 SecureDnsPolicy::kAllow, /*disable_cert_network_fetches=*/false),
15382 false,
15383 },
15384 {
15385 "", // unused
15386 "http://[2001:1418:13:1::25]/direct",
15387 ClientSocketPool::GroupId(
15388 url::SchemeHostPort(url::kHttpScheme, "[2001:1418:13:1::25]", 80),
15389 PrivacyMode::PRIVACY_MODE_DISABLED, NetworkAnonymizationKey(),
15390 SecureDnsPolicy::kAllow, /*disable_cert_network_fetches=*/false),
15391 false,
15392 },
15393
15394 // SSL Tests
15395 {
15396 "", // unused
15397 "https://www.example.org/direct_ssl",
15398 ClientSocketPool::GroupId(
15399 url::SchemeHostPort(url::kHttpsScheme, "www.example.org", 443),
15400 PrivacyMode::PRIVACY_MODE_DISABLED, NetworkAnonymizationKey(),
15401 SecureDnsPolicy::kAllow, /*disable_cert_network_fetches=*/false),
15402 true,
15403 },
15404 {
15405 "", // unused
15406 "https://[2001:1418:13:1::25]/direct",
15407 ClientSocketPool::GroupId(
15408 url::SchemeHostPort(url::kHttpsScheme, "[2001:1418:13:1::25]",
15409 443),
15410 PrivacyMode::PRIVACY_MODE_DISABLED, NetworkAnonymizationKey(),
15411 SecureDnsPolicy::kAllow, /*disable_cert_network_fetches=*/false),
15412 true,
15413 },
15414 {
15415 "", // unused
15416 "https://host.with.alternate/direct",
15417 ClientSocketPool::GroupId(
15418 url::SchemeHostPort(url::kHttpsScheme, "host.with.alternate",
15419 443),
15420 PrivacyMode::PRIVACY_MODE_DISABLED, NetworkAnonymizationKey(),
15421 SecureDnsPolicy::kAllow, /*disable_cert_network_fetches=*/false),
15422 true,
15423 },
15424 };
15425
15426 for (const auto& test : tests) {
15427 session_deps_.proxy_resolution_service =
15428 ConfiguredProxyResolutionService::CreateFixedForTest(
15429 test.proxy_chain, TRAFFIC_ANNOTATION_FOR_TESTS);
15430 std::unique_ptr<HttpNetworkSession> session(
15431 SetupSessionForGroupIdTests(&session_deps_));
15432
15433 HttpNetworkSessionPeer peer(session.get());
15434 auto transport_conn_pool =
15435 std::make_unique<CaptureGroupIdTransportSocketPool>(
15436 &dummy_connect_job_params_);
15437 auto* transport_conn_pool_ptr = transport_conn_pool.get();
15438 auto mock_pool_manager = std::make_unique<MockClientSocketPoolManager>();
15439 mock_pool_manager->SetSocketPool(ProxyChain::Direct(),
15440 std::move(transport_conn_pool));
15441 peer.SetClientSocketPoolManager(std::move(mock_pool_manager));
15442
15443 EXPECT_EQ(ERR_IO_PENDING,
15444 GroupIdTransactionHelper(test.url, session.get()));
15445 EXPECT_EQ(test.expected_group_id,
15446 transport_conn_pool_ptr->last_group_id_received());
15447 EXPECT_TRUE(transport_conn_pool_ptr->socket_requested());
15448 }
15449 }
15450
TEST_P(HttpNetworkTransactionTest,GroupIdForHTTPProxyConnections)15451 TEST_P(HttpNetworkTransactionTest, GroupIdForHTTPProxyConnections) {
15452 const GroupIdTest tests[] = {
15453 {
15454 "http_proxy",
15455 "http://www.example.org/http_proxy_normal",
15456 ClientSocketPool::GroupId(
15457 url::SchemeHostPort(url::kHttpScheme, "www.example.org", 80),
15458 PrivacyMode::PRIVACY_MODE_DISABLED, NetworkAnonymizationKey(),
15459 SecureDnsPolicy::kAllow, /*disable_cert_network_fetches=*/false),
15460 false,
15461 },
15462
15463 // SSL Tests
15464 {
15465 "http_proxy",
15466 "https://www.example.org/http_connect_ssl",
15467 ClientSocketPool::GroupId(
15468 url::SchemeHostPort(url::kHttpsScheme, "www.example.org", 443),
15469 PrivacyMode::PRIVACY_MODE_DISABLED, NetworkAnonymizationKey(),
15470 SecureDnsPolicy::kAllow, /*disable_cert_network_fetches=*/false),
15471 true,
15472 },
15473
15474 {
15475 "http_proxy",
15476 "https://host.with.alternate/direct",
15477 ClientSocketPool::GroupId(
15478 url::SchemeHostPort(url::kHttpsScheme, "host.with.alternate",
15479 443),
15480 PrivacyMode::PRIVACY_MODE_DISABLED, NetworkAnonymizationKey(),
15481 SecureDnsPolicy::kAllow, /*disable_cert_network_fetches=*/false),
15482 true,
15483 },
15484 };
15485
15486 for (const auto& test : tests) {
15487 session_deps_.proxy_resolution_service =
15488 ConfiguredProxyResolutionService::CreateFixedForTest(
15489 test.proxy_chain, TRAFFIC_ANNOTATION_FOR_TESTS);
15490 std::unique_ptr<HttpNetworkSession> session(
15491 SetupSessionForGroupIdTests(&session_deps_));
15492
15493 HttpNetworkSessionPeer peer(session.get());
15494
15495 ProxyChain proxy_chain(ProxyServer::SCHEME_HTTP,
15496 HostPortPair("http_proxy", 80));
15497 auto http_proxy_pool = std::make_unique<CaptureGroupIdTransportSocketPool>(
15498 &dummy_connect_job_params_);
15499 auto* http_proxy_pool_ptr = http_proxy_pool.get();
15500 auto mock_pool_manager = std::make_unique<MockClientSocketPoolManager>();
15501 mock_pool_manager->SetSocketPool(proxy_chain, std::move(http_proxy_pool));
15502 peer.SetClientSocketPoolManager(std::move(mock_pool_manager));
15503
15504 EXPECT_EQ(ERR_IO_PENDING,
15505 GroupIdTransactionHelper(test.url, session.get()));
15506 EXPECT_EQ(test.expected_group_id,
15507 http_proxy_pool_ptr->last_group_id_received());
15508 }
15509 }
15510
TEST_P(HttpNetworkTransactionTest,GroupIdForSOCKSConnections)15511 TEST_P(HttpNetworkTransactionTest, GroupIdForSOCKSConnections) {
15512 const GroupIdTest tests[] = {
15513 {
15514 "socks4://socks_proxy:1080",
15515 "http://www.example.org/socks4_direct",
15516 ClientSocketPool::GroupId(
15517 url::SchemeHostPort(url::kHttpScheme, "www.example.org", 80),
15518 PrivacyMode::PRIVACY_MODE_DISABLED, NetworkAnonymizationKey(),
15519 SecureDnsPolicy::kAllow, /*disable_cert_network_fetches=*/false),
15520 false,
15521 },
15522 {
15523 "socks5://socks_proxy:1080",
15524 "http://www.example.org/socks5_direct",
15525 ClientSocketPool::GroupId(
15526 url::SchemeHostPort(url::kHttpScheme, "www.example.org", 80),
15527 PrivacyMode::PRIVACY_MODE_DISABLED, NetworkAnonymizationKey(),
15528 SecureDnsPolicy::kAllow, /*disable_cert_network_fetches=*/false),
15529 false,
15530 },
15531
15532 // SSL Tests
15533 {
15534 "socks4://socks_proxy:1080",
15535 "https://www.example.org/socks4_ssl",
15536 ClientSocketPool::GroupId(
15537 url::SchemeHostPort(url::kHttpsScheme, "www.example.org", 443),
15538 PrivacyMode::PRIVACY_MODE_DISABLED, NetworkAnonymizationKey(),
15539 SecureDnsPolicy::kAllow, /*disable_cert_network_fetches=*/false),
15540 true,
15541 },
15542 {
15543 "socks5://socks_proxy:1080",
15544 "https://www.example.org/socks5_ssl",
15545 ClientSocketPool::GroupId(
15546 url::SchemeHostPort(url::kHttpsScheme, "www.example.org", 443),
15547 PrivacyMode::PRIVACY_MODE_DISABLED, NetworkAnonymizationKey(),
15548 SecureDnsPolicy::kAllow, /*disable_cert_network_fetches=*/false),
15549 true,
15550 },
15551
15552 {
15553 "socks4://socks_proxy:1080",
15554 "https://host.with.alternate/direct",
15555 ClientSocketPool::GroupId(
15556 url::SchemeHostPort(url::kHttpsScheme, "host.with.alternate",
15557 443),
15558 PrivacyMode::PRIVACY_MODE_DISABLED, NetworkAnonymizationKey(),
15559 SecureDnsPolicy::kAllow, /*disable_cert_network_fetches=*/false),
15560 true,
15561 },
15562 };
15563
15564 for (const auto& test : tests) {
15565 session_deps_.proxy_resolution_service =
15566 ConfiguredProxyResolutionService::CreateFixedForTest(
15567 test.proxy_chain, TRAFFIC_ANNOTATION_FOR_TESTS);
15568 std::unique_ptr<HttpNetworkSession> session(
15569 SetupSessionForGroupIdTests(&session_deps_));
15570
15571 HttpNetworkSessionPeer peer(session.get());
15572
15573 ProxyChain proxy_chain =
15574 ProxyUriToProxyChain(test.proxy_chain, ProxyServer::SCHEME_HTTP);
15575 ASSERT_TRUE(proxy_chain.IsValid());
15576 auto socks_conn_pool = std::make_unique<CaptureGroupIdTransportSocketPool>(
15577 &dummy_connect_job_params_);
15578 auto* socks_conn_pool_ptr = socks_conn_pool.get();
15579 auto mock_pool_manager = std::make_unique<MockClientSocketPoolManager>();
15580 mock_pool_manager->SetSocketPool(proxy_chain, std::move(socks_conn_pool));
15581 peer.SetClientSocketPoolManager(std::move(mock_pool_manager));
15582
15583 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
15584
15585 EXPECT_EQ(ERR_IO_PENDING,
15586 GroupIdTransactionHelper(test.url, session.get()));
15587 EXPECT_EQ(test.expected_group_id,
15588 socks_conn_pool_ptr->last_group_id_received());
15589 }
15590 }
15591
TEST_P(HttpNetworkTransactionTest,ReconsiderProxyAfterFailedConnection)15592 TEST_P(HttpNetworkTransactionTest, ReconsiderProxyAfterFailedConnection) {
15593 HttpRequestInfo request;
15594 request.method = "GET";
15595 request.url = GURL("http://www.example.org/");
15596 request.traffic_annotation =
15597 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
15598
15599 session_deps_.proxy_resolution_service =
15600 ConfiguredProxyResolutionService::CreateFixedForTest(
15601 "myproxy:70;foobar:80", TRAFFIC_ANNOTATION_FOR_TESTS);
15602
15603 // This simulates failure resolving all hostnames; that means we will fail
15604 // connecting to both proxies (myproxy:70 and foobar:80).
15605 session_deps_.host_resolver->rules()->AddSimulatedFailure("*");
15606
15607 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
15608 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
15609
15610 TestCompletionCallback callback;
15611
15612 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
15613 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
15614
15615 rv = callback.WaitForResult();
15616 EXPECT_THAT(rv, IsError(ERR_PROXY_CONNECTION_FAILED));
15617 }
15618
15619 // Make sure we can handle an error when writing the request.
TEST_P(HttpNetworkTransactionTest,RequestWriteError)15620 TEST_P(HttpNetworkTransactionTest, RequestWriteError) {
15621 HttpRequestInfo request;
15622 request.method = "GET";
15623 request.url = GURL("http://www.foo.com/");
15624 request.traffic_annotation =
15625 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
15626
15627 MockWrite write_failure[] = {
15628 MockWrite(ASYNC, ERR_CONNECTION_RESET),
15629 };
15630 StaticSocketDataProvider data(base::span<MockRead>(), write_failure);
15631 session_deps_.socket_factory->AddSocketDataProvider(&data);
15632 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
15633
15634 TestCompletionCallback callback;
15635
15636 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
15637
15638 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
15639 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
15640
15641 rv = callback.WaitForResult();
15642 EXPECT_THAT(rv, IsError(ERR_CONNECTION_RESET));
15643
15644 IPEndPoint endpoint;
15645 EXPECT_TRUE(trans.GetRemoteEndpoint(&endpoint));
15646 EXPECT_LT(0u, endpoint.address().size());
15647 }
15648
15649 // Check that a connection closed after the start of the headers finishes ok.
TEST_P(HttpNetworkTransactionTest,ConnectionClosedAfterStartOfHeaders)15650 TEST_P(HttpNetworkTransactionTest, ConnectionClosedAfterStartOfHeaders) {
15651 HttpRequestInfo request;
15652 request.method = "GET";
15653 request.url = GURL("http://www.foo.com/");
15654 request.traffic_annotation =
15655 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
15656
15657 MockRead data_reads[] = {
15658 MockRead("HTTP/1."),
15659 MockRead(SYNCHRONOUS, OK),
15660 };
15661
15662 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
15663 session_deps_.socket_factory->AddSocketDataProvider(&data);
15664 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
15665
15666 TestCompletionCallback callback;
15667
15668 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
15669
15670 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
15671 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
15672
15673 rv = callback.WaitForResult();
15674 EXPECT_THAT(rv, IsOk());
15675
15676 const HttpResponseInfo* response = trans.GetResponseInfo();
15677 ASSERT_TRUE(response);
15678
15679 EXPECT_TRUE(response->headers);
15680 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
15681
15682 std::string response_data;
15683 rv = ReadTransaction(&trans, &response_data);
15684 EXPECT_THAT(rv, IsOk());
15685 EXPECT_EQ("", response_data);
15686
15687 IPEndPoint endpoint;
15688 EXPECT_TRUE(trans.GetRemoteEndpoint(&endpoint));
15689 EXPECT_LT(0u, endpoint.address().size());
15690 }
15691
15692 // Make sure that a dropped connection while draining the body for auth
15693 // restart does the right thing.
TEST_P(HttpNetworkTransactionTest,DrainResetOK)15694 TEST_P(HttpNetworkTransactionTest, DrainResetOK) {
15695 HttpRequestInfo request;
15696 request.method = "GET";
15697 request.url = GURL("http://www.example.org/");
15698 request.traffic_annotation =
15699 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
15700
15701 MockWrite data_writes1[] = {
15702 MockWrite("GET / HTTP/1.1\r\n"
15703 "Host: www.example.org\r\n"
15704 "Connection: keep-alive\r\n\r\n"),
15705 };
15706
15707 MockRead data_reads1[] = {
15708 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
15709 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
15710 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
15711 MockRead("Content-Length: 14\r\n\r\n"),
15712 MockRead("Unauth"),
15713 MockRead(ASYNC, ERR_CONNECTION_RESET),
15714 };
15715
15716 StaticSocketDataProvider data1(data_reads1, data_writes1);
15717 session_deps_.socket_factory->AddSocketDataProvider(&data1);
15718
15719 // After calling trans.RestartWithAuth(), this is the request we should
15720 // be issuing -- the final header line contains the credentials.
15721 MockWrite data_writes2[] = {
15722 MockWrite("GET / HTTP/1.1\r\n"
15723 "Host: www.example.org\r\n"
15724 "Connection: keep-alive\r\n"
15725 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
15726 };
15727
15728 // Lastly, the server responds with the actual content.
15729 MockRead data_reads2[] = {
15730 MockRead("HTTP/1.1 200 OK\r\n"),
15731 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
15732 MockRead("Content-Length: 100\r\n\r\n"),
15733 MockRead(SYNCHRONOUS, OK),
15734 };
15735
15736 StaticSocketDataProvider data2(data_reads2, data_writes2);
15737 session_deps_.socket_factory->AddSocketDataProvider(&data2);
15738 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
15739
15740 TestCompletionCallback callback1;
15741
15742 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
15743
15744 int rv = trans.Start(&request, callback1.callback(), NetLogWithSource());
15745 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
15746
15747 rv = callback1.WaitForResult();
15748 EXPECT_THAT(rv, IsOk());
15749
15750 const HttpResponseInfo* response = trans.GetResponseInfo();
15751 ASSERT_TRUE(response);
15752 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge));
15753
15754 TestCompletionCallback callback2;
15755
15756 rv = trans.RestartWithAuth(AuthCredentials(kFoo, kBar), callback2.callback());
15757 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
15758
15759 rv = callback2.WaitForResult();
15760 EXPECT_THAT(rv, IsOk());
15761
15762 response = trans.GetResponseInfo();
15763 ASSERT_TRUE(response);
15764 EXPECT_FALSE(response->auth_challenge.has_value());
15765 EXPECT_EQ(100, response->headers->GetContentLength());
15766 }
15767
15768 // Test HTTPS connections going through a proxy that sends extra data.
TEST_P(HttpNetworkTransactionTest,HTTPSViaProxyWithExtraData)15769 TEST_P(HttpNetworkTransactionTest, HTTPSViaProxyWithExtraData) {
15770 session_deps_.proxy_resolution_service =
15771 ConfiguredProxyResolutionService::CreateFixedForTest(
15772 "myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
15773
15774 HttpRequestInfo request;
15775 request.method = "GET";
15776 request.url = GURL("https://www.example.org/");
15777 request.traffic_annotation =
15778 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
15779
15780 MockRead proxy_reads[] = {
15781 MockRead("HTTP/1.0 200 Connected\r\n\r\nExtra data"),
15782 MockRead(SYNCHRONOUS, OK)};
15783
15784 StaticSocketDataProvider data(proxy_reads, base::span<MockWrite>());
15785 SSLSocketDataProvider ssl(ASYNC, OK);
15786
15787 session_deps_.socket_factory->AddSocketDataProvider(&data);
15788 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
15789
15790 TestCompletionCallback callback;
15791
15792 session_deps_.socket_factory->ResetNextMockIndexes();
15793
15794 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
15795 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
15796
15797 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
15798 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
15799
15800 rv = callback.WaitForResult();
15801 EXPECT_THAT(rv, IsError(ERR_TUNNEL_CONNECTION_FAILED));
15802 }
15803
TEST_P(HttpNetworkTransactionTest,LargeContentLengthThenClose)15804 TEST_P(HttpNetworkTransactionTest, LargeContentLengthThenClose) {
15805 HttpRequestInfo request;
15806 request.method = "GET";
15807 request.url = GURL("http://www.example.org/");
15808 request.traffic_annotation =
15809 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
15810
15811 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
15812 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
15813
15814 MockRead data_reads[] = {
15815 MockRead("HTTP/1.0 200 OK\r\nContent-Length:6719476739\r\n\r\n"),
15816 MockRead(SYNCHRONOUS, OK),
15817 };
15818
15819 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
15820 session_deps_.socket_factory->AddSocketDataProvider(&data);
15821
15822 TestCompletionCallback callback;
15823
15824 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
15825 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
15826
15827 EXPECT_THAT(callback.WaitForResult(), IsOk());
15828
15829 const HttpResponseInfo* response = trans.GetResponseInfo();
15830 ASSERT_TRUE(response);
15831
15832 EXPECT_TRUE(response->headers);
15833 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
15834
15835 std::string response_data;
15836 rv = ReadTransaction(&trans, &response_data);
15837 EXPECT_THAT(rv, IsError(ERR_CONTENT_LENGTH_MISMATCH));
15838 }
15839
TEST_P(HttpNetworkTransactionTest,UploadFileSmallerThanLength)15840 TEST_P(HttpNetworkTransactionTest, UploadFileSmallerThanLength) {
15841 base::FilePath temp_file_path;
15842 ASSERT_TRUE(base::CreateTemporaryFile(&temp_file_path));
15843 const uint64_t kFakeSize = 100000; // file is actually blank
15844 UploadFileElementReader::ScopedOverridingContentLengthForTests
15845 overriding_content_length(kFakeSize);
15846
15847 std::vector<std::unique_ptr<UploadElementReader>> element_readers;
15848 element_readers.push_back(std::make_unique<UploadFileElementReader>(
15849 base::SingleThreadTaskRunner::GetCurrentDefault().get(), temp_file_path,
15850 0, std::numeric_limits<uint64_t>::max(), base::Time()));
15851 ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0);
15852
15853 HttpRequestInfo request;
15854 request.method = "POST";
15855 request.url = GURL("http://www.example.org/upload");
15856 request.upload_data_stream = &upload_data_stream;
15857 request.traffic_annotation =
15858 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
15859
15860 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
15861 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
15862
15863 MockRead data_reads[] = {
15864 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
15865 MockRead("hello world"),
15866 MockRead(SYNCHRONOUS, OK),
15867 };
15868 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
15869 session_deps_.socket_factory->AddSocketDataProvider(&data);
15870
15871 TestCompletionCallback callback;
15872
15873 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
15874 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
15875
15876 rv = callback.WaitForResult();
15877 EXPECT_THAT(rv, IsError(ERR_UPLOAD_FILE_CHANGED));
15878
15879 const HttpResponseInfo* response = trans.GetResponseInfo();
15880 ASSERT_TRUE(response);
15881
15882 EXPECT_FALSE(response->headers);
15883
15884 base::DeleteFile(temp_file_path);
15885 }
15886
TEST_P(HttpNetworkTransactionTest,UploadUnreadableFile)15887 TEST_P(HttpNetworkTransactionTest, UploadUnreadableFile) {
15888 base::FilePath temp_file;
15889 ASSERT_TRUE(base::CreateTemporaryFile(&temp_file));
15890 std::string temp_file_content("Unreadable file.");
15891 ASSERT_TRUE(base::WriteFile(temp_file, temp_file_content));
15892 ASSERT_TRUE(base::MakeFileUnreadable(temp_file));
15893
15894 std::vector<std::unique_ptr<UploadElementReader>> element_readers;
15895 element_readers.push_back(std::make_unique<UploadFileElementReader>(
15896 base::SingleThreadTaskRunner::GetCurrentDefault().get(), temp_file, 0,
15897 std::numeric_limits<uint64_t>::max(), base::Time()));
15898 ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0);
15899
15900 HttpRequestInfo request;
15901 request.method = "POST";
15902 request.url = GURL("http://www.example.org/upload");
15903 request.upload_data_stream = &upload_data_stream;
15904 request.traffic_annotation =
15905 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
15906
15907 // If we try to upload an unreadable file, the transaction should fail.
15908 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
15909 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
15910
15911 StaticSocketDataProvider data;
15912 session_deps_.socket_factory->AddSocketDataProvider(&data);
15913
15914 TestCompletionCallback callback;
15915
15916 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
15917 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
15918
15919 rv = callback.WaitForResult();
15920 EXPECT_THAT(rv, IsError(ERR_ACCESS_DENIED));
15921
15922 base::DeleteFile(temp_file);
15923 }
15924
TEST_P(HttpNetworkTransactionTest,CancelDuringInitRequestBody)15925 TEST_P(HttpNetworkTransactionTest, CancelDuringInitRequestBody) {
15926 class FakeUploadElementReader : public UploadElementReader {
15927 public:
15928 FakeUploadElementReader() = default;
15929 ~FakeUploadElementReader() override = default;
15930
15931 CompletionOnceCallback TakeCallback() { return std::move(callback_); }
15932
15933 // UploadElementReader overrides:
15934 int Init(CompletionOnceCallback callback) override {
15935 callback_ = std::move(callback);
15936 return ERR_IO_PENDING;
15937 }
15938 uint64_t GetContentLength() const override { return 0; }
15939 uint64_t BytesRemaining() const override { return 0; }
15940 int Read(IOBuffer* buf,
15941 int buf_length,
15942 CompletionOnceCallback callback) override {
15943 return ERR_FAILED;
15944 }
15945
15946 private:
15947 CompletionOnceCallback callback_;
15948 };
15949
15950 auto fake_reader = std::make_unique<FakeUploadElementReader>();
15951 auto* fake_reader_ptr = fake_reader.get();
15952 std::vector<std::unique_ptr<UploadElementReader>> element_readers;
15953 element_readers.push_back(std::move(fake_reader));
15954 ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0);
15955
15956 HttpRequestInfo request;
15957 request.method = "POST";
15958 request.url = GURL("http://www.example.org/upload");
15959 request.upload_data_stream = &upload_data_stream;
15960 request.traffic_annotation =
15961 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
15962
15963 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
15964 auto trans =
15965 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
15966
15967 StaticSocketDataProvider data;
15968 session_deps_.socket_factory->AddSocketDataProvider(&data);
15969
15970 TestCompletionCallback callback;
15971 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
15972 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
15973 base::RunLoop().RunUntilIdle();
15974
15975 // Transaction is pending on request body initialization.
15976 CompletionOnceCallback init_callback = fake_reader_ptr->TakeCallback();
15977 ASSERT_FALSE(init_callback.is_null());
15978
15979 // Return Init()'s result after the transaction gets destroyed.
15980 trans.reset();
15981 std::move(init_callback).Run(OK); // Should not crash.
15982 }
15983
15984 // Tests that changes to Auth realms are treated like auth rejections.
TEST_P(HttpNetworkTransactionTest,ChangeAuthRealms)15985 TEST_P(HttpNetworkTransactionTest, ChangeAuthRealms) {
15986 HttpRequestInfo request;
15987 request.method = "GET";
15988 request.url = GURL("http://www.example.org/");
15989 request.traffic_annotation =
15990 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
15991
15992 // First transaction will request a resource and receive a Basic challenge
15993 // with realm="first_realm".
15994 MockWrite data_writes1[] = {
15995 MockWrite("GET / HTTP/1.1\r\n"
15996 "Host: www.example.org\r\n"
15997 "Connection: keep-alive\r\n"
15998 "\r\n"),
15999 };
16000 MockRead data_reads1[] = {
16001 MockRead("HTTP/1.1 401 Unauthorized\r\n"
16002 "WWW-Authenticate: Basic realm=\"first_realm\"\r\n"
16003 "\r\n"),
16004 };
16005
16006 // After calling trans.RestartWithAuth(), provide an Authentication header
16007 // for first_realm. The server will reject and provide a challenge with
16008 // second_realm.
16009 MockWrite data_writes2[] = {
16010 MockWrite("GET / HTTP/1.1\r\n"
16011 "Host: www.example.org\r\n"
16012 "Connection: keep-alive\r\n"
16013 "Authorization: Basic Zmlyc3Q6YmF6\r\n"
16014 "\r\n"),
16015 };
16016 MockRead data_reads2[] = {
16017 MockRead("HTTP/1.1 401 Unauthorized\r\n"
16018 "WWW-Authenticate: Basic realm=\"second_realm\"\r\n"
16019 "\r\n"),
16020 };
16021
16022 // This again fails, and goes back to first_realm. Make sure that the
16023 // entry is removed from cache.
16024 MockWrite data_writes3[] = {
16025 MockWrite("GET / HTTP/1.1\r\n"
16026 "Host: www.example.org\r\n"
16027 "Connection: keep-alive\r\n"
16028 "Authorization: Basic c2Vjb25kOmZvdQ==\r\n"
16029 "\r\n"),
16030 };
16031 MockRead data_reads3[] = {
16032 MockRead("HTTP/1.1 401 Unauthorized\r\n"
16033 "WWW-Authenticate: Basic realm=\"first_realm\"\r\n"
16034 "\r\n"),
16035 };
16036
16037 // Try one last time (with the correct password) and get the resource.
16038 MockWrite data_writes4[] = {
16039 MockWrite("GET / HTTP/1.1\r\n"
16040 "Host: www.example.org\r\n"
16041 "Connection: keep-alive\r\n"
16042 "Authorization: Basic Zmlyc3Q6YmFy\r\n"
16043 "\r\n"),
16044 };
16045 MockRead data_reads4[] = {
16046 MockRead("HTTP/1.1 200 OK\r\n"
16047 "Content-Type: text/html; charset=iso-8859-1\r\n"
16048 "Content-Length: 5\r\n"
16049 "\r\n"
16050 "hello"),
16051 };
16052
16053 StaticSocketDataProvider data1(data_reads1, data_writes1);
16054 StaticSocketDataProvider data2(data_reads2, data_writes2);
16055 StaticSocketDataProvider data3(data_reads3, data_writes3);
16056 StaticSocketDataProvider data4(data_reads4, data_writes4);
16057 session_deps_.socket_factory->AddSocketDataProvider(&data1);
16058 session_deps_.socket_factory->AddSocketDataProvider(&data2);
16059 session_deps_.socket_factory->AddSocketDataProvider(&data3);
16060 session_deps_.socket_factory->AddSocketDataProvider(&data4);
16061
16062 TestCompletionCallback callback1;
16063
16064 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
16065 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
16066
16067 // Issue the first request with Authorize headers. There should be a
16068 // password prompt for first_realm waiting to be filled in after the
16069 // transaction completes.
16070 int rv = trans.Start(&request, callback1.callback(), NetLogWithSource());
16071 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
16072 rv = callback1.WaitForResult();
16073 EXPECT_THAT(rv, IsOk());
16074 const HttpResponseInfo* response = trans.GetResponseInfo();
16075 ASSERT_TRUE(response);
16076 std::optional<AuthChallengeInfo> challenge = response->auth_challenge;
16077 ASSERT_TRUE(challenge);
16078 EXPECT_FALSE(challenge->is_proxy);
16079 EXPECT_EQ("http://www.example.org", challenge->challenger.Serialize());
16080 EXPECT_EQ("first_realm", challenge->realm);
16081 EXPECT_EQ(kBasicAuthScheme, challenge->scheme);
16082
16083 // Issue the second request with an incorrect password. There should be a
16084 // password prompt for second_realm waiting to be filled in after the
16085 // transaction completes.
16086 TestCompletionCallback callback2;
16087 rv = trans.RestartWithAuth(AuthCredentials(kFirst, kBaz),
16088 callback2.callback());
16089 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
16090 rv = callback2.WaitForResult();
16091 EXPECT_THAT(rv, IsOk());
16092 response = trans.GetResponseInfo();
16093 ASSERT_TRUE(response);
16094 challenge = response->auth_challenge;
16095 ASSERT_TRUE(challenge);
16096 EXPECT_FALSE(challenge->is_proxy);
16097 EXPECT_EQ("http://www.example.org", challenge->challenger.Serialize());
16098 EXPECT_EQ("second_realm", challenge->realm);
16099 EXPECT_EQ(kBasicAuthScheme, challenge->scheme);
16100
16101 // Issue the third request with another incorrect password. There should be
16102 // a password prompt for first_realm waiting to be filled in. If the password
16103 // prompt is not present, it indicates that the HttpAuthCacheEntry for
16104 // first_realm was not correctly removed.
16105 TestCompletionCallback callback3;
16106 rv = trans.RestartWithAuth(AuthCredentials(kSecond, kFou),
16107 callback3.callback());
16108 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
16109 rv = callback3.WaitForResult();
16110 EXPECT_THAT(rv, IsOk());
16111 response = trans.GetResponseInfo();
16112 ASSERT_TRUE(response);
16113 challenge = response->auth_challenge;
16114 ASSERT_TRUE(challenge);
16115 EXPECT_FALSE(challenge->is_proxy);
16116 EXPECT_EQ("http://www.example.org", challenge->challenger.Serialize());
16117 EXPECT_EQ("first_realm", challenge->realm);
16118 EXPECT_EQ(kBasicAuthScheme, challenge->scheme);
16119
16120 // Issue the fourth request with the correct password and username.
16121 TestCompletionCallback callback4;
16122 rv = trans.RestartWithAuth(AuthCredentials(kFirst, kBar),
16123 callback4.callback());
16124 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
16125 rv = callback4.WaitForResult();
16126 EXPECT_THAT(rv, IsOk());
16127 response = trans.GetResponseInfo();
16128 ASSERT_TRUE(response);
16129 EXPECT_FALSE(response->auth_challenge.has_value());
16130 }
16131
16132 // Regression test for https://crbug.com/754395.
TEST_P(HttpNetworkTransactionTest,IgnoreAltSvcWithInvalidCert)16133 TEST_P(HttpNetworkTransactionTest, IgnoreAltSvcWithInvalidCert) {
16134 MockRead data_reads[] = {
16135 MockRead("HTTP/1.1 200 OK\r\n"),
16136 MockRead(kAlternativeServiceHttpHeader),
16137 MockRead("\r\n"),
16138 MockRead("hello world"),
16139 MockRead(SYNCHRONOUS, OK),
16140 };
16141
16142 HttpRequestInfo request;
16143 request.method = "GET";
16144 request.url = GURL("https://www.example.org/");
16145 request.traffic_annotation =
16146 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
16147
16148 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
16149 session_deps_.socket_factory->AddSocketDataProvider(&data);
16150
16151 SSLSocketDataProvider ssl(ASYNC, OK);
16152 ssl.ssl_info.cert =
16153 ImportCertFromFile(GetTestCertsDirectory(), "wildcard.pem");
16154 ASSERT_TRUE(ssl.ssl_info.cert);
16155 ssl.ssl_info.cert_status = CERT_STATUS_COMMON_NAME_INVALID;
16156 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
16157
16158 TestCompletionCallback callback;
16159
16160 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
16161 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
16162
16163 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
16164 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
16165
16166 url::SchemeHostPort test_server(request.url);
16167 HttpServerProperties* http_server_properties =
16168 session->http_server_properties();
16169 EXPECT_TRUE(
16170 http_server_properties
16171 ->GetAlternativeServiceInfos(test_server, NetworkAnonymizationKey())
16172 .empty());
16173
16174 EXPECT_THAT(callback.WaitForResult(), IsOk());
16175
16176 const HttpResponseInfo* response = trans.GetResponseInfo();
16177 ASSERT_TRUE(response);
16178 ASSERT_TRUE(response->headers);
16179 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
16180 EXPECT_FALSE(response->was_fetched_via_spdy);
16181 EXPECT_FALSE(response->was_alpn_negotiated);
16182
16183 std::string response_data;
16184 ASSERT_THAT(ReadTransaction(&trans, &response_data), IsOk());
16185 EXPECT_EQ("hello world", response_data);
16186
16187 EXPECT_TRUE(
16188 http_server_properties
16189 ->GetAlternativeServiceInfos(test_server, NetworkAnonymizationKey())
16190 .empty());
16191 }
16192
TEST_P(HttpNetworkTransactionTest,HonorAlternativeServiceHeader)16193 TEST_P(HttpNetworkTransactionTest, HonorAlternativeServiceHeader) {
16194 MockRead data_reads[] = {
16195 MockRead("HTTP/1.1 200 OK\r\n"),
16196 MockRead(kAlternativeServiceHttpHeader),
16197 MockRead("\r\n"),
16198 MockRead("hello world"),
16199 MockRead(SYNCHRONOUS, OK),
16200 };
16201
16202 HttpRequestInfo request;
16203 request.method = "GET";
16204 request.url = GURL("https://www.example.org/");
16205 request.traffic_annotation =
16206 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
16207
16208 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
16209 session_deps_.socket_factory->AddSocketDataProvider(&data);
16210
16211 SSLSocketDataProvider ssl(ASYNC, OK);
16212 ssl.ssl_info.cert =
16213 ImportCertFromFile(GetTestCertsDirectory(), "wildcard.pem");
16214 ASSERT_TRUE(ssl.ssl_info.cert);
16215 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
16216
16217 TestCompletionCallback callback;
16218
16219 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
16220 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
16221
16222 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
16223 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
16224
16225 url::SchemeHostPort test_server(request.url);
16226 HttpServerProperties* http_server_properties =
16227 session->http_server_properties();
16228 EXPECT_TRUE(
16229 http_server_properties
16230 ->GetAlternativeServiceInfos(test_server, NetworkAnonymizationKey())
16231 .empty());
16232
16233 EXPECT_THAT(callback.WaitForResult(), IsOk());
16234
16235 const HttpResponseInfo* response = trans.GetResponseInfo();
16236 ASSERT_TRUE(response);
16237 ASSERT_TRUE(response->headers);
16238 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
16239 EXPECT_FALSE(response->was_fetched_via_spdy);
16240 EXPECT_FALSE(response->was_alpn_negotiated);
16241
16242 std::string response_data;
16243 ASSERT_THAT(ReadTransaction(&trans, &response_data), IsOk());
16244 EXPECT_EQ("hello world", response_data);
16245
16246 AlternativeServiceInfoVector alternative_service_info_vector =
16247 http_server_properties->GetAlternativeServiceInfos(
16248 test_server, NetworkAnonymizationKey());
16249 ASSERT_EQ(1u, alternative_service_info_vector.size());
16250 AlternativeService alternative_service(kProtoHTTP2, "mail.example.org", 443);
16251 EXPECT_EQ(alternative_service,
16252 alternative_service_info_vector[0].alternative_service());
16253 }
16254
TEST_P(HttpNetworkTransactionTest,HonorAlternativeServiceHeaderWithNetworkAnonymizationKey)16255 TEST_P(HttpNetworkTransactionTest,
16256 HonorAlternativeServiceHeaderWithNetworkAnonymizationKey) {
16257 base::test::ScopedFeatureList feature_list;
16258 feature_list.InitWithFeatures(
16259 // enabled_features
16260 {features::kPartitionHttpServerPropertiesByNetworkIsolationKey,
16261 // Need to partition connections by NetworkAnonymizationKey for
16262 // SpdySessionKeys to include NetworkAnonymizationKeys.
16263 features::kPartitionConnectionsByNetworkIsolationKey},
16264 // disabled_features
16265 {});
16266 // Since HttpServerProperties caches the feature value, have to create a new
16267 // one.
16268 session_deps_.http_server_properties =
16269 std::make_unique<HttpServerProperties>();
16270
16271 const SchemefulSite kSite1(GURL("https://foo.test/"));
16272 const auto kNetworkAnonymizationKey1 =
16273 net::NetworkAnonymizationKey::CreateSameSite(kSite1);
16274 const net::NetworkIsolationKey kNetworkIsolationKey1(kSite1, kSite1);
16275 const SchemefulSite kSite2(GURL("https://bar.test/"));
16276 const auto kNetworkAnonymizationKey2 =
16277 net::NetworkAnonymizationKey::CreateSameSite(kSite2);
16278 const net::NetworkIsolationKey kNetworkIsolationKey2(kSite2, kSite2);
16279
16280 MockRead data_reads[] = {
16281 MockRead("HTTP/1.1 200 OK\r\n"),
16282 MockRead(kAlternativeServiceHttpHeader),
16283 MockRead("\r\n"),
16284 MockRead("hello world"),
16285 MockRead(SYNCHRONOUS, OK),
16286 };
16287
16288 HttpRequestInfo request;
16289 request.method = "GET";
16290 request.url = GURL("https://www.example.org/");
16291 request.traffic_annotation =
16292 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
16293 request.network_isolation_key = kNetworkIsolationKey1;
16294 request.network_anonymization_key = kNetworkAnonymizationKey1;
16295
16296 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
16297 session_deps_.socket_factory->AddSocketDataProvider(&data);
16298
16299 SSLSocketDataProvider ssl(ASYNC, OK);
16300 ssl.ssl_info.cert =
16301 ImportCertFromFile(GetTestCertsDirectory(), "wildcard.pem");
16302 ASSERT_TRUE(ssl.ssl_info.cert);
16303 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
16304
16305 TestCompletionCallback callback;
16306
16307 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
16308 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
16309
16310 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
16311 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
16312
16313 url::SchemeHostPort test_server(request.url);
16314 HttpServerProperties* http_server_properties =
16315 session->http_server_properties();
16316 EXPECT_TRUE(
16317 http_server_properties
16318 ->GetAlternativeServiceInfos(test_server, kNetworkAnonymizationKey1)
16319 .empty());
16320
16321 EXPECT_THAT(callback.WaitForResult(), IsOk());
16322
16323 const HttpResponseInfo* response = trans.GetResponseInfo();
16324 ASSERT_TRUE(response);
16325 ASSERT_TRUE(response->headers);
16326 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
16327 EXPECT_FALSE(response->was_fetched_via_spdy);
16328 EXPECT_FALSE(response->was_alpn_negotiated);
16329
16330 std::string response_data;
16331 ASSERT_THAT(ReadTransaction(&trans, &response_data), IsOk());
16332 EXPECT_EQ("hello world", response_data);
16333
16334 AlternativeServiceInfoVector alternative_service_info_vector =
16335 http_server_properties->GetAlternativeServiceInfos(
16336 test_server, kNetworkAnonymizationKey1);
16337 ASSERT_EQ(1u, alternative_service_info_vector.size());
16338 AlternativeService alternative_service(kProtoHTTP2, "mail.example.org", 443);
16339 EXPECT_EQ(alternative_service,
16340 alternative_service_info_vector[0].alternative_service());
16341
16342 // Make sure the alternative service information is only associated with
16343 // kNetworkAnonymizationKey1.
16344 EXPECT_TRUE(
16345 http_server_properties
16346 ->GetAlternativeServiceInfos(test_server, NetworkAnonymizationKey())
16347 .empty());
16348 EXPECT_TRUE(
16349 http_server_properties
16350 ->GetAlternativeServiceInfos(test_server, kNetworkAnonymizationKey2)
16351 .empty());
16352 }
16353
16354 // Regression test for https://crbug.com/615497.
TEST_P(HttpNetworkTransactionTest,DoNotParseAlternativeServiceHeaderOnInsecureRequest)16355 TEST_P(HttpNetworkTransactionTest,
16356 DoNotParseAlternativeServiceHeaderOnInsecureRequest) {
16357 MockRead data_reads[] = {
16358 MockRead("HTTP/1.1 200 OK\r\n"),
16359 MockRead(kAlternativeServiceHttpHeader),
16360 MockRead("\r\n"),
16361 MockRead("hello world"),
16362 MockRead(SYNCHRONOUS, OK),
16363 };
16364
16365 HttpRequestInfo request;
16366 request.method = "GET";
16367 request.url = GURL("http://www.example.org/");
16368 request.load_flags = 0;
16369 request.traffic_annotation =
16370 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
16371
16372 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
16373 session_deps_.socket_factory->AddSocketDataProvider(&data);
16374
16375 TestCompletionCallback callback;
16376
16377 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
16378 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
16379
16380 url::SchemeHostPort test_server(request.url);
16381 HttpServerProperties* http_server_properties =
16382 session->http_server_properties();
16383 EXPECT_TRUE(
16384 http_server_properties
16385 ->GetAlternativeServiceInfos(test_server, NetworkAnonymizationKey())
16386 .empty());
16387
16388 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
16389 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
16390 EXPECT_THAT(callback.WaitForResult(), IsOk());
16391
16392 const HttpResponseInfo* response = trans.GetResponseInfo();
16393 ASSERT_TRUE(response);
16394 ASSERT_TRUE(response->headers);
16395 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
16396 EXPECT_FALSE(response->was_fetched_via_spdy);
16397 EXPECT_FALSE(response->was_alpn_negotiated);
16398
16399 std::string response_data;
16400 ASSERT_THAT(ReadTransaction(&trans, &response_data), IsOk());
16401 EXPECT_EQ("hello world", response_data);
16402
16403 EXPECT_TRUE(
16404 http_server_properties
16405 ->GetAlternativeServiceInfos(test_server, NetworkAnonymizationKey())
16406 .empty());
16407 }
16408
16409 // HTTP/2 Alternative Services should be disabled by default.
16410 // TODO(bnc): Remove when https://crbug.com/615413 is fixed.
TEST_P(HttpNetworkTransactionTest,DisableHTTP2AlternativeServicesWithDifferentHost)16411 TEST_P(HttpNetworkTransactionTest,
16412 DisableHTTP2AlternativeServicesWithDifferentHost) {
16413 session_deps_.enable_http2_alternative_service = false;
16414
16415 HttpRequestInfo request;
16416 request.method = "GET";
16417 request.url = GURL("https://www.example.org/");
16418 request.load_flags = 0;
16419 request.traffic_annotation =
16420 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
16421
16422 MockConnect mock_connect(ASYNC, ERR_CONNECTION_REFUSED);
16423 StaticSocketDataProvider first_data;
16424 first_data.set_connect_data(mock_connect);
16425 session_deps_.socket_factory->AddSocketDataProvider(&first_data);
16426 SSLSocketDataProvider ssl_http11(ASYNC, OK);
16427 ssl_http11.next_proto = kProtoHTTP11;
16428 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_http11);
16429
16430 MockRead data_reads[] = {
16431 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
16432 MockRead("hello world"),
16433 MockRead(ASYNC, OK),
16434 };
16435 StaticSocketDataProvider second_data(data_reads, base::span<MockWrite>());
16436 session_deps_.socket_factory->AddSocketDataProvider(&second_data);
16437
16438 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
16439
16440 HttpServerProperties* http_server_properties =
16441 session->http_server_properties();
16442 AlternativeService alternative_service(kProtoHTTP2, "different.example.org",
16443 444);
16444 base::Time expiration = base::Time::Now() + base::Days(1);
16445 http_server_properties->SetHttp2AlternativeService(
16446 url::SchemeHostPort(request.url), NetworkAnonymizationKey(),
16447 alternative_service, expiration);
16448
16449 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
16450 TestCompletionCallback callback;
16451
16452 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
16453 // Alternative service is not used, request fails.
16454 EXPECT_THAT(callback.GetResult(rv), IsError(ERR_CONNECTION_REFUSED));
16455 }
16456
16457 // Regression test for https://crbug.com/615497:
16458 // Alternative Services should be disabled for http origin.
TEST_P(HttpNetworkTransactionTest,DisableAlternativeServicesForInsecureOrigin)16459 TEST_P(HttpNetworkTransactionTest,
16460 DisableAlternativeServicesForInsecureOrigin) {
16461 HttpRequestInfo request;
16462 request.method = "GET";
16463 request.url = GURL("http://www.example.org/");
16464 request.load_flags = 0;
16465 request.traffic_annotation =
16466 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
16467
16468 MockConnect mock_connect(ASYNC, ERR_CONNECTION_REFUSED);
16469 StaticSocketDataProvider first_data;
16470 first_data.set_connect_data(mock_connect);
16471 session_deps_.socket_factory->AddSocketDataProvider(&first_data);
16472
16473 MockRead data_reads[] = {
16474 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
16475 MockRead("hello world"),
16476 MockRead(ASYNC, OK),
16477 };
16478 StaticSocketDataProvider second_data(data_reads, base::span<MockWrite>());
16479 session_deps_.socket_factory->AddSocketDataProvider(&second_data);
16480
16481 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
16482
16483 HttpServerProperties* http_server_properties =
16484 session->http_server_properties();
16485 AlternativeService alternative_service(kProtoHTTP2, "", 444);
16486 base::Time expiration = base::Time::Now() + base::Days(1);
16487 http_server_properties->SetHttp2AlternativeService(
16488 url::SchemeHostPort(request.url), NetworkAnonymizationKey(),
16489 alternative_service, expiration);
16490
16491 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
16492 TestCompletionCallback callback;
16493
16494 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
16495 // Alternative service is not used, request fails.
16496 EXPECT_THAT(callback.GetResult(rv), IsError(ERR_CONNECTION_REFUSED));
16497 }
16498
TEST_P(HttpNetworkTransactionTest,ClearAlternativeServices)16499 TEST_P(HttpNetworkTransactionTest, ClearAlternativeServices) {
16500 // Set an alternative service for origin.
16501 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
16502 HttpServerProperties* http_server_properties =
16503 session->http_server_properties();
16504 url::SchemeHostPort test_server("https", "www.example.org", 443);
16505 AlternativeService alternative_service(kProtoQUIC, "", 80);
16506 base::Time expiration = base::Time::Now() + base::Days(1);
16507 http_server_properties->SetQuicAlternativeService(
16508 test_server, NetworkAnonymizationKey(), alternative_service, expiration,
16509 session->context().quic_context->params()->supported_versions);
16510 EXPECT_EQ(1u, http_server_properties
16511 ->GetAlternativeServiceInfos(test_server,
16512 NetworkAnonymizationKey())
16513 .size());
16514
16515 // Send a clear header.
16516 MockRead data_reads[] = {
16517 MockRead("HTTP/1.1 200 OK\r\n"),
16518 MockRead("Alt-Svc: clear\r\n"),
16519 MockRead("\r\n"),
16520 MockRead("hello world"),
16521 MockRead(SYNCHRONOUS, OK),
16522 };
16523 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
16524 session_deps_.socket_factory->AddSocketDataProvider(&data);
16525
16526 SSLSocketDataProvider ssl(ASYNC, OK);
16527 ssl.ssl_info.cert =
16528 ImportCertFromFile(GetTestCertsDirectory(), "wildcard.pem");
16529 ASSERT_TRUE(ssl.ssl_info.cert);
16530 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
16531
16532 HttpRequestInfo request;
16533 request.method = "GET";
16534 request.url = GURL("https://www.example.org/");
16535 request.traffic_annotation =
16536 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
16537
16538 TestCompletionCallback callback;
16539
16540 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
16541
16542 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
16543 EXPECT_THAT(callback.GetResult(rv), IsOk());
16544
16545 const HttpResponseInfo* response = trans.GetResponseInfo();
16546 ASSERT_TRUE(response);
16547 ASSERT_TRUE(response->headers);
16548 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
16549 EXPECT_FALSE(response->was_fetched_via_spdy);
16550 EXPECT_FALSE(response->was_alpn_negotiated);
16551
16552 std::string response_data;
16553 ASSERT_THAT(ReadTransaction(&trans, &response_data), IsOk());
16554 EXPECT_EQ("hello world", response_data);
16555
16556 EXPECT_TRUE(
16557 http_server_properties
16558 ->GetAlternativeServiceInfos(test_server, NetworkAnonymizationKey())
16559 .empty());
16560 }
16561
TEST_P(HttpNetworkTransactionTest,HonorMultipleAlternativeServiceHeaders)16562 TEST_P(HttpNetworkTransactionTest, HonorMultipleAlternativeServiceHeaders) {
16563 MockRead data_reads[] = {
16564 MockRead("HTTP/1.1 200 OK\r\n"),
16565 MockRead("Alt-Svc: h2=\"www.example.com:443\","),
16566 MockRead("h2=\":1234\"\r\n\r\n"),
16567 MockRead("hello world"),
16568 MockRead(SYNCHRONOUS, OK),
16569 };
16570
16571 HttpRequestInfo request;
16572 request.method = "GET";
16573 request.url = GURL("https://www.example.org/");
16574 request.traffic_annotation =
16575 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
16576
16577 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
16578 session_deps_.socket_factory->AddSocketDataProvider(&data);
16579
16580 SSLSocketDataProvider ssl(ASYNC, OK);
16581 ssl.ssl_info.cert =
16582 ImportCertFromFile(GetTestCertsDirectory(), "wildcard.pem");
16583 ASSERT_TRUE(ssl.ssl_info.cert);
16584 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
16585
16586 TestCompletionCallback callback;
16587
16588 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
16589 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
16590
16591 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
16592 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
16593
16594 url::SchemeHostPort test_server("https", "www.example.org", 443);
16595 HttpServerProperties* http_server_properties =
16596 session->http_server_properties();
16597 EXPECT_TRUE(
16598 http_server_properties
16599 ->GetAlternativeServiceInfos(test_server, NetworkAnonymizationKey())
16600 .empty());
16601
16602 EXPECT_THAT(callback.WaitForResult(), IsOk());
16603
16604 const HttpResponseInfo* response = trans.GetResponseInfo();
16605 ASSERT_TRUE(response);
16606 ASSERT_TRUE(response->headers);
16607 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
16608 EXPECT_FALSE(response->was_fetched_via_spdy);
16609 EXPECT_FALSE(response->was_alpn_negotiated);
16610
16611 std::string response_data;
16612 ASSERT_THAT(ReadTransaction(&trans, &response_data), IsOk());
16613 EXPECT_EQ("hello world", response_data);
16614
16615 AlternativeServiceInfoVector alternative_service_info_vector =
16616 http_server_properties->GetAlternativeServiceInfos(
16617 test_server, NetworkAnonymizationKey());
16618 ASSERT_EQ(2u, alternative_service_info_vector.size());
16619
16620 AlternativeService alternative_service(kProtoHTTP2, "www.example.com", 443);
16621 EXPECT_EQ(alternative_service,
16622 alternative_service_info_vector[0].alternative_service());
16623 AlternativeService alternative_service_2(kProtoHTTP2, "www.example.org",
16624 1234);
16625 EXPECT_EQ(alternative_service_2,
16626 alternative_service_info_vector[1].alternative_service());
16627 }
16628
TEST_P(HttpNetworkTransactionTest,IdentifyQuicBroken)16629 TEST_P(HttpNetworkTransactionTest, IdentifyQuicBroken) {
16630 url::SchemeHostPort server("https", "origin.example.org", 443);
16631 HostPortPair alternative("alternative.example.org", 443);
16632 std::string origin_url = "https://origin.example.org:443";
16633 std::string alternative_url = "https://alternative.example.org:443";
16634
16635 // Negotiate HTTP/1.1 with alternative.example.org.
16636 SSLSocketDataProvider ssl(ASYNC, OK);
16637 ssl.next_proto = kProtoHTTP11;
16638 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
16639
16640 // HTTP/1.1 data for request.
16641 MockWrite http_writes[] = {
16642 MockWrite("GET / HTTP/1.1\r\n"
16643 "Host: alternative.example.org\r\n"
16644 "Connection: keep-alive\r\n\r\n"),
16645 };
16646
16647 MockRead http_reads[] = {
16648 MockRead("HTTP/1.1 200 OK\r\n"
16649 "Content-Type: text/html; charset=iso-8859-1\r\n"
16650 "Content-Length: 40\r\n\r\n"
16651 "first HTTP/1.1 response from alternative"),
16652 };
16653 StaticSocketDataProvider http_data(http_reads, http_writes);
16654 session_deps_.socket_factory->AddSocketDataProvider(&http_data);
16655
16656 StaticSocketDataProvider data_refused;
16657 data_refused.set_connect_data(MockConnect(ASYNC, ERR_CONNECTION_REFUSED));
16658 session_deps_.socket_factory->AddSocketDataProvider(&data_refused);
16659
16660 // Set up a QUIC alternative service for server.
16661 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
16662 HttpServerProperties* http_server_properties =
16663 session->http_server_properties();
16664 AlternativeService alternative_service(kProtoQUIC, alternative);
16665 base::Time expiration = base::Time::Now() + base::Days(1);
16666 http_server_properties->SetQuicAlternativeService(
16667 server, NetworkAnonymizationKey(), alternative_service, expiration,
16668 DefaultSupportedQuicVersions());
16669 // Mark the QUIC alternative service as broken.
16670 http_server_properties->MarkAlternativeServiceBroken(
16671 alternative_service, NetworkAnonymizationKey());
16672
16673 HttpRequestInfo request;
16674 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
16675 request.method = "GET";
16676 request.url = GURL(origin_url);
16677 request.traffic_annotation =
16678 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
16679
16680 TestCompletionCallback callback;
16681 NetErrorDetails details;
16682 EXPECT_FALSE(details.quic_broken);
16683
16684 trans.Start(&request, callback.callback(), NetLogWithSource());
16685 trans.PopulateNetErrorDetails(&details);
16686 EXPECT_TRUE(details.quic_broken);
16687 }
16688
TEST_P(HttpNetworkTransactionTest,IdentifyQuicNotBroken)16689 TEST_P(HttpNetworkTransactionTest, IdentifyQuicNotBroken) {
16690 url::SchemeHostPort server("https", "origin.example.org", 443);
16691 HostPortPair alternative1("alternative1.example.org", 443);
16692 HostPortPair alternative2("alternative2.example.org", 443);
16693 std::string origin_url = "https://origin.example.org:443";
16694 std::string alternative_url1 = "https://alternative1.example.org:443";
16695 std::string alternative_url2 = "https://alternative2.example.org:443";
16696
16697 // Negotiate HTTP/1.1 with alternative1.example.org.
16698 SSLSocketDataProvider ssl(ASYNC, OK);
16699 ssl.next_proto = kProtoHTTP11;
16700 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
16701
16702 // HTTP/1.1 data for request.
16703 MockWrite http_writes[] = {
16704 MockWrite("GET / HTTP/1.1\r\n"
16705 "Host: alternative1.example.org\r\n"
16706 "Connection: keep-alive\r\n\r\n"),
16707 };
16708
16709 MockRead http_reads[] = {
16710 MockRead("HTTP/1.1 200 OK\r\n"
16711 "Content-Type: text/html; charset=iso-8859-1\r\n"
16712 "Content-Length: 40\r\n\r\n"
16713 "first HTTP/1.1 response from alternative1"),
16714 };
16715 StaticSocketDataProvider http_data(http_reads, http_writes);
16716 session_deps_.socket_factory->AddSocketDataProvider(&http_data);
16717
16718 StaticSocketDataProvider data_refused;
16719 data_refused.set_connect_data(MockConnect(ASYNC, ERR_CONNECTION_REFUSED));
16720 session_deps_.socket_factory->AddSocketDataProvider(&data_refused);
16721
16722 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
16723 HttpServerProperties* http_server_properties =
16724 session->http_server_properties();
16725
16726 // Set up two QUIC alternative services for server.
16727 AlternativeServiceInfoVector alternative_service_info_vector;
16728 base::Time expiration = base::Time::Now() + base::Days(1);
16729
16730 AlternativeService alternative_service1(kProtoQUIC, alternative1);
16731 alternative_service_info_vector.push_back(
16732 AlternativeServiceInfo::CreateQuicAlternativeServiceInfo(
16733 alternative_service1, expiration,
16734 session->context().quic_context->params()->supported_versions));
16735 AlternativeService alternative_service2(kProtoQUIC, alternative2);
16736 alternative_service_info_vector.push_back(
16737 AlternativeServiceInfo::CreateQuicAlternativeServiceInfo(
16738 alternative_service2, expiration,
16739 session->context().quic_context->params()->supported_versions));
16740
16741 http_server_properties->SetAlternativeServices(
16742 server, NetworkAnonymizationKey(), alternative_service_info_vector);
16743
16744 // Mark one of the QUIC alternative service as broken.
16745 http_server_properties->MarkAlternativeServiceBroken(
16746 alternative_service1, NetworkAnonymizationKey());
16747 EXPECT_EQ(2u,
16748 http_server_properties
16749 ->GetAlternativeServiceInfos(server, NetworkAnonymizationKey())
16750 .size());
16751
16752 HttpRequestInfo request;
16753 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
16754 request.method = "GET";
16755 request.url = GURL(origin_url);
16756 request.traffic_annotation =
16757 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
16758
16759 TestCompletionCallback callback;
16760 NetErrorDetails details;
16761 EXPECT_FALSE(details.quic_broken);
16762
16763 trans.Start(&request, callback.callback(), NetLogWithSource());
16764 trans.PopulateNetErrorDetails(&details);
16765 EXPECT_FALSE(details.quic_broken);
16766 }
16767
TEST_P(HttpNetworkTransactionTest,MarkBrokenAlternateProtocolAndFallback)16768 TEST_P(HttpNetworkTransactionTest, MarkBrokenAlternateProtocolAndFallback) {
16769 HttpRequestInfo request;
16770 request.method = "GET";
16771 request.url = GURL("https://www.example.org/");
16772 request.traffic_annotation =
16773 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
16774
16775 MockConnect mock_connect(ASYNC, ERR_CONNECTION_REFUSED);
16776 StaticSocketDataProvider first_data;
16777 first_data.set_connect_data(mock_connect);
16778 session_deps_.socket_factory->AddSocketDataProvider(&first_data);
16779 SSLSocketDataProvider ssl_http11(ASYNC, OK);
16780 ssl_http11.next_proto = kProtoHTTP11;
16781 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_http11);
16782
16783 MockRead data_reads[] = {
16784 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
16785 MockRead("hello world"),
16786 MockRead(ASYNC, OK),
16787 };
16788 StaticSocketDataProvider second_data(data_reads, base::span<MockWrite>());
16789 session_deps_.socket_factory->AddSocketDataProvider(&second_data);
16790
16791 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
16792
16793 HttpServerProperties* http_server_properties =
16794 session->http_server_properties();
16795 const url::SchemeHostPort server(request.url);
16796 // Port must be < 1024, or the header will be ignored (since initial port was
16797 // port 80 (another restricted port).
16798 // Port is ignored by MockConnect anyway.
16799 const AlternativeService alternative_service(kProtoHTTP2, "www.example.org",
16800 666);
16801 base::Time expiration = base::Time::Now() + base::Days(1);
16802 http_server_properties->SetHttp2AlternativeService(
16803 server, NetworkAnonymizationKey(), alternative_service, expiration);
16804
16805 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
16806 TestCompletionCallback callback;
16807
16808 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
16809 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
16810 EXPECT_THAT(callback.WaitForResult(), IsOk());
16811
16812 const HttpResponseInfo* response = trans.GetResponseInfo();
16813 ASSERT_TRUE(response);
16814 ASSERT_TRUE(response->headers);
16815 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
16816
16817 std::string response_data;
16818 ASSERT_THAT(ReadTransaction(&trans, &response_data), IsOk());
16819 EXPECT_EQ("hello world", response_data);
16820
16821 const AlternativeServiceInfoVector alternative_service_info_vector =
16822 http_server_properties->GetAlternativeServiceInfos(
16823 server, NetworkAnonymizationKey());
16824 ASSERT_EQ(1u, alternative_service_info_vector.size());
16825 EXPECT_EQ(alternative_service,
16826 alternative_service_info_vector[0].alternative_service());
16827 EXPECT_TRUE(http_server_properties->IsAlternativeServiceBroken(
16828 alternative_service, NetworkAnonymizationKey()));
16829 }
16830
16831 // Ensure that we are not allowed to redirect traffic via an alternate protocol
16832 // to an unrestricted (port >= 1024) when the original traffic was on a
16833 // restricted port (port < 1024). Ensure that we can redirect in all other
16834 // cases.
TEST_P(HttpNetworkTransactionTest,AlternateProtocolPortRestrictedBlocked)16835 TEST_P(HttpNetworkTransactionTest, AlternateProtocolPortRestrictedBlocked) {
16836 HttpRequestInfo restricted_port_request;
16837 restricted_port_request.method = "GET";
16838 restricted_port_request.url = GURL("https://www.example.org:1023/");
16839 restricted_port_request.load_flags = 0;
16840 restricted_port_request.traffic_annotation =
16841 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
16842
16843 MockConnect mock_connect(ASYNC, ERR_CONNECTION_REFUSED);
16844 StaticSocketDataProvider first_data;
16845 first_data.set_connect_data(mock_connect);
16846 session_deps_.socket_factory->AddSocketDataProvider(&first_data);
16847
16848 MockRead data_reads[] = {
16849 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
16850 MockRead("hello world"),
16851 MockRead(ASYNC, OK),
16852 };
16853 StaticSocketDataProvider second_data(data_reads, base::span<MockWrite>());
16854 session_deps_.socket_factory->AddSocketDataProvider(&second_data);
16855 SSLSocketDataProvider ssl_http11(ASYNC, OK);
16856 ssl_http11.next_proto = kProtoHTTP11;
16857 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_http11);
16858
16859 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
16860
16861 HttpServerProperties* http_server_properties =
16862 session->http_server_properties();
16863 const int kUnrestrictedAlternatePort = 1024;
16864 AlternativeService alternative_service(kProtoHTTP2, "www.example.org",
16865 kUnrestrictedAlternatePort);
16866 base::Time expiration = base::Time::Now() + base::Days(1);
16867 http_server_properties->SetHttp2AlternativeService(
16868 url::SchemeHostPort(restricted_port_request.url),
16869 NetworkAnonymizationKey(), alternative_service, expiration);
16870
16871 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
16872 TestCompletionCallback callback;
16873
16874 int rv = trans.Start(&restricted_port_request, callback.callback(),
16875 NetLogWithSource());
16876 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
16877 // Invalid change to unrestricted port should fail.
16878 EXPECT_THAT(callback.WaitForResult(), IsError(ERR_CONNECTION_REFUSED));
16879 }
16880
16881 // Ensure that we are allowed to redirect traffic via an alternate protocol to
16882 // an unrestricted (port >= 1024) when the original traffic was on a restricted
16883 // port (port < 1024) if we set |enable_user_alternate_protocol_ports|.
TEST_P(HttpNetworkTransactionTest,AlternateProtocolPortRestrictedPermitted)16884 TEST_P(HttpNetworkTransactionTest, AlternateProtocolPortRestrictedPermitted) {
16885 session_deps_.enable_user_alternate_protocol_ports = true;
16886
16887 HttpRequestInfo restricted_port_request;
16888 restricted_port_request.method = "GET";
16889 restricted_port_request.url = GURL("https://www.example.org:1023/");
16890 restricted_port_request.load_flags = 0;
16891 restricted_port_request.traffic_annotation =
16892 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
16893
16894 MockConnect mock_connect(ASYNC, ERR_CONNECTION_REFUSED);
16895 StaticSocketDataProvider first_data;
16896 first_data.set_connect_data(mock_connect);
16897 session_deps_.socket_factory->AddSocketDataProvider(&first_data);
16898
16899 MockRead data_reads[] = {
16900 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
16901 MockRead("hello world"),
16902 MockRead(ASYNC, OK),
16903 };
16904 StaticSocketDataProvider second_data(data_reads, base::span<MockWrite>());
16905 session_deps_.socket_factory->AddSocketDataProvider(&second_data);
16906 SSLSocketDataProvider ssl_http11(ASYNC, OK);
16907 ssl_http11.next_proto = kProtoHTTP11;
16908 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_http11);
16909
16910 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
16911
16912 HttpServerProperties* http_server_properties =
16913 session->http_server_properties();
16914 const int kUnrestrictedAlternatePort = 1024;
16915 AlternativeService alternative_service(kProtoHTTP2, "www.example.org",
16916 kUnrestrictedAlternatePort);
16917 base::Time expiration = base::Time::Now() + base::Days(1);
16918 http_server_properties->SetHttp2AlternativeService(
16919 url::SchemeHostPort(restricted_port_request.url),
16920 NetworkAnonymizationKey(), alternative_service, expiration);
16921
16922 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
16923 TestCompletionCallback callback;
16924
16925 EXPECT_EQ(ERR_IO_PENDING,
16926 trans.Start(&restricted_port_request, callback.callback(),
16927 NetLogWithSource()));
16928 // Change to unrestricted port should succeed.
16929 EXPECT_THAT(callback.WaitForResult(), IsOk());
16930 }
16931
16932 // Ensure that we are not allowed to redirect traffic via an alternate protocol
16933 // to an unrestricted (port >= 1024) when the original traffic was on a
16934 // restricted port (port < 1024). Ensure that we can redirect in all other
16935 // cases.
TEST_P(HttpNetworkTransactionTest,AlternateProtocolPortRestrictedAllowed)16936 TEST_P(HttpNetworkTransactionTest, AlternateProtocolPortRestrictedAllowed) {
16937 HttpRequestInfo restricted_port_request;
16938 restricted_port_request.method = "GET";
16939 restricted_port_request.url = GURL("https://www.example.org:1023/");
16940 restricted_port_request.load_flags = 0;
16941 restricted_port_request.traffic_annotation =
16942 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
16943
16944 MockConnect mock_connect(ASYNC, ERR_CONNECTION_REFUSED);
16945 StaticSocketDataProvider first_data;
16946 first_data.set_connect_data(mock_connect);
16947 session_deps_.socket_factory->AddSocketDataProvider(&first_data);
16948
16949 MockRead data_reads[] = {
16950 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
16951 MockRead("hello world"),
16952 MockRead(ASYNC, OK),
16953 };
16954 StaticSocketDataProvider second_data(data_reads, base::span<MockWrite>());
16955 session_deps_.socket_factory->AddSocketDataProvider(&second_data);
16956
16957 SSLSocketDataProvider ssl(ASYNC, OK);
16958 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
16959
16960 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
16961
16962 HttpServerProperties* http_server_properties =
16963 session->http_server_properties();
16964 const int kRestrictedAlternatePort = 80;
16965 AlternativeService alternative_service(kProtoHTTP2, "www.example.org",
16966 kRestrictedAlternatePort);
16967 base::Time expiration = base::Time::Now() + base::Days(1);
16968 http_server_properties->SetHttp2AlternativeService(
16969 url::SchemeHostPort(restricted_port_request.url),
16970 NetworkAnonymizationKey(), alternative_service, expiration);
16971
16972 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
16973 TestCompletionCallback callback;
16974
16975 int rv = trans.Start(&restricted_port_request, callback.callback(),
16976 NetLogWithSource());
16977 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
16978 // Valid change to restricted port should pass.
16979 EXPECT_THAT(callback.WaitForResult(), IsOk());
16980 }
16981
16982 // Ensure that we are not allowed to redirect traffic via an alternate protocol
16983 // to an unrestricted (port >= 1024) when the original traffic was on a
16984 // restricted port (port < 1024). Ensure that we can redirect in all other
16985 // cases.
TEST_P(HttpNetworkTransactionTest,AlternateProtocolPortUnrestrictedAllowed1)16986 TEST_P(HttpNetworkTransactionTest, AlternateProtocolPortUnrestrictedAllowed1) {
16987 HttpRequestInfo unrestricted_port_request;
16988 unrestricted_port_request.method = "GET";
16989 unrestricted_port_request.url = GURL("https://www.example.org:1024/");
16990 unrestricted_port_request.load_flags = 0;
16991 unrestricted_port_request.traffic_annotation =
16992 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
16993
16994 MockConnect mock_connect(ASYNC, ERR_CONNECTION_REFUSED);
16995 StaticSocketDataProvider first_data;
16996 first_data.set_connect_data(mock_connect);
16997 session_deps_.socket_factory->AddSocketDataProvider(&first_data);
16998
16999 MockRead data_reads[] = {
17000 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
17001 MockRead("hello world"),
17002 MockRead(ASYNC, OK),
17003 };
17004 StaticSocketDataProvider second_data(data_reads, base::span<MockWrite>());
17005 session_deps_.socket_factory->AddSocketDataProvider(&second_data);
17006 SSLSocketDataProvider ssl_http11(ASYNC, OK);
17007 ssl_http11.next_proto = kProtoHTTP11;
17008 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_http11);
17009
17010 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
17011
17012 HttpServerProperties* http_server_properties =
17013 session->http_server_properties();
17014 const int kRestrictedAlternatePort = 80;
17015 AlternativeService alternative_service(kProtoHTTP2, "www.example.org",
17016 kRestrictedAlternatePort);
17017 base::Time expiration = base::Time::Now() + base::Days(1);
17018 http_server_properties->SetHttp2AlternativeService(
17019 url::SchemeHostPort(unrestricted_port_request.url),
17020 NetworkAnonymizationKey(), alternative_service, expiration);
17021
17022 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
17023 TestCompletionCallback callback;
17024
17025 int rv = trans.Start(&unrestricted_port_request, callback.callback(),
17026 NetLogWithSource());
17027 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
17028 // Valid change to restricted port should pass.
17029 EXPECT_THAT(callback.WaitForResult(), IsOk());
17030 }
17031
17032 // Ensure that we are not allowed to redirect traffic via an alternate protocol
17033 // to an unrestricted (port >= 1024) when the original traffic was on a
17034 // restricted port (port < 1024). Ensure that we can redirect in all other
17035 // cases.
TEST_P(HttpNetworkTransactionTest,AlternateProtocolPortUnrestrictedAllowed2)17036 TEST_P(HttpNetworkTransactionTest, AlternateProtocolPortUnrestrictedAllowed2) {
17037 HttpRequestInfo unrestricted_port_request;
17038 unrestricted_port_request.method = "GET";
17039 unrestricted_port_request.url = GURL("https://www.example.org:1024/");
17040 unrestricted_port_request.load_flags = 0;
17041 unrestricted_port_request.traffic_annotation =
17042 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
17043
17044 MockConnect mock_connect(ASYNC, ERR_CONNECTION_REFUSED);
17045 StaticSocketDataProvider first_data;
17046 first_data.set_connect_data(mock_connect);
17047 session_deps_.socket_factory->AddSocketDataProvider(&first_data);
17048
17049 MockRead data_reads[] = {
17050 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
17051 MockRead("hello world"),
17052 MockRead(ASYNC, OK),
17053 };
17054 StaticSocketDataProvider second_data(data_reads, base::span<MockWrite>());
17055 session_deps_.socket_factory->AddSocketDataProvider(&second_data);
17056
17057 SSLSocketDataProvider ssl(ASYNC, OK);
17058 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
17059
17060 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
17061
17062 HttpServerProperties* http_server_properties =
17063 session->http_server_properties();
17064 const int kUnrestrictedAlternatePort = 1025;
17065 AlternativeService alternative_service(kProtoHTTP2, "www.example.org",
17066 kUnrestrictedAlternatePort);
17067 base::Time expiration = base::Time::Now() + base::Days(1);
17068 http_server_properties->SetHttp2AlternativeService(
17069 url::SchemeHostPort(unrestricted_port_request.url),
17070 NetworkAnonymizationKey(), alternative_service, expiration);
17071
17072 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
17073 TestCompletionCallback callback;
17074
17075 int rv = trans.Start(&unrestricted_port_request, callback.callback(),
17076 NetLogWithSource());
17077 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
17078 // Valid change to an unrestricted port should pass.
17079 EXPECT_THAT(callback.WaitForResult(), IsOk());
17080 }
17081
17082 // Ensure that we are not allowed to redirect traffic via an alternate protocol
17083 // to an unsafe port, and that we resume the second HttpStreamFactory::Job once
17084 // the alternate protocol request fails.
TEST_P(HttpNetworkTransactionTest,AlternateProtocolUnsafeBlocked)17085 TEST_P(HttpNetworkTransactionTest, AlternateProtocolUnsafeBlocked) {
17086 HttpRequestInfo request;
17087 request.method = "GET";
17088 request.url = GURL("http://www.example.org/");
17089 request.traffic_annotation =
17090 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
17091
17092 // The alternate protocol request will error out before we attempt to connect,
17093 // so only the standard HTTP request will try to connect.
17094 MockRead data_reads[] = {
17095 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
17096 MockRead("hello world"),
17097 MockRead(ASYNC, OK),
17098 };
17099 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
17100 session_deps_.socket_factory->AddSocketDataProvider(&data);
17101
17102 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
17103
17104 HttpServerProperties* http_server_properties =
17105 session->http_server_properties();
17106 const int kUnsafePort = 7;
17107 AlternativeService alternative_service(kProtoHTTP2, "www.example.org",
17108 kUnsafePort);
17109 base::Time expiration = base::Time::Now() + base::Days(1);
17110 http_server_properties->SetHttp2AlternativeService(
17111 url::SchemeHostPort(request.url), NetworkAnonymizationKey(),
17112 alternative_service, expiration);
17113
17114 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
17115 TestCompletionCallback callback;
17116
17117 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
17118 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
17119 // The HTTP request should succeed.
17120 EXPECT_THAT(callback.WaitForResult(), IsOk());
17121
17122 const HttpResponseInfo* response = trans.GetResponseInfo();
17123 ASSERT_TRUE(response);
17124 ASSERT_TRUE(response->headers);
17125 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
17126
17127 std::string response_data;
17128 ASSERT_THAT(ReadTransaction(&trans, &response_data), IsOk());
17129 EXPECT_EQ("hello world", response_data);
17130 }
17131
TEST_P(HttpNetworkTransactionTest,UseAlternateProtocolForNpnSpdy)17132 TEST_P(HttpNetworkTransactionTest, UseAlternateProtocolForNpnSpdy) {
17133 HttpRequestInfo request;
17134 request.method = "GET";
17135 request.url = GURL("https://www.example.org/");
17136 request.traffic_annotation =
17137 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
17138
17139 MockRead data_reads[] = {
17140 MockRead("HTTP/1.1 200 OK\r\n"),
17141 MockRead(kAlternativeServiceHttpHeader),
17142 MockRead("\r\n"),
17143 MockRead("hello world"),
17144 MockRead(SYNCHRONOUS, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
17145 MockRead(ASYNC, OK)};
17146
17147 StaticSocketDataProvider first_transaction(data_reads,
17148 base::span<MockWrite>());
17149 session_deps_.socket_factory->AddSocketDataProvider(&first_transaction);
17150 SSLSocketDataProvider ssl_http11(ASYNC, OK);
17151 ssl_http11.next_proto = kProtoHTTP11;
17152 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_http11);
17153
17154 AddSSLSocketData();
17155
17156 spdy::SpdySerializedFrame req(
17157 spdy_util_.ConstructSpdyGet("https://www.example.org/", 1, LOWEST));
17158 MockWrite spdy_writes[] = {CreateMockWrite(req, 0)};
17159
17160 spdy::SpdySerializedFrame resp(
17161 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
17162 spdy::SpdySerializedFrame data(spdy_util_.ConstructSpdyDataFrame(1, true));
17163 MockRead spdy_reads[] = {
17164 CreateMockRead(resp, 1),
17165 CreateMockRead(data, 2),
17166 MockRead(ASYNC, 0, 3),
17167 };
17168
17169 SequencedSocketData spdy_data(spdy_reads, spdy_writes);
17170 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
17171
17172 MockConnect never_finishing_connect(SYNCHRONOUS, ERR_IO_PENDING);
17173 StaticSocketDataProvider hanging_non_alternate_protocol_socket;
17174 hanging_non_alternate_protocol_socket.set_connect_data(
17175 never_finishing_connect);
17176 session_deps_.socket_factory->AddSocketDataProvider(
17177 &hanging_non_alternate_protocol_socket);
17178
17179 TestCompletionCallback callback;
17180
17181 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
17182 auto trans =
17183 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
17184
17185 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
17186 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
17187 EXPECT_THAT(callback.WaitForResult(), IsOk());
17188
17189 const HttpResponseInfo* response = trans->GetResponseInfo();
17190 ASSERT_TRUE(response);
17191 ASSERT_TRUE(response->headers);
17192 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
17193
17194 std::string response_data;
17195 ASSERT_THAT(ReadTransaction(trans.get(), &response_data), IsOk());
17196 EXPECT_EQ("hello world", response_data);
17197
17198 trans =
17199 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
17200
17201 rv = trans->Start(&request, callback.callback(), NetLogWithSource());
17202 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
17203 EXPECT_THAT(callback.WaitForResult(), IsOk());
17204
17205 response = trans->GetResponseInfo();
17206 ASSERT_TRUE(response);
17207 ASSERT_TRUE(response->headers);
17208 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
17209 EXPECT_TRUE(response->was_fetched_via_spdy);
17210 EXPECT_TRUE(response->was_alpn_negotiated);
17211
17212 ASSERT_THAT(ReadTransaction(trans.get(), &response_data), IsOk());
17213 EXPECT_EQ("hello!", response_data);
17214 }
17215
TEST_P(HttpNetworkTransactionTest,AlternateProtocolWithSpdyLateBinding)17216 TEST_P(HttpNetworkTransactionTest, AlternateProtocolWithSpdyLateBinding) {
17217 HttpRequestInfo request;
17218 request.method = "GET";
17219 request.url = GURL("https://www.example.org/");
17220 request.traffic_annotation =
17221 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
17222
17223 // First transaction receives Alt-Svc header over HTTP/1.1.
17224 MockRead data_reads[] = {
17225 MockRead("HTTP/1.1 200 OK\r\n"),
17226 MockRead(kAlternativeServiceHttpHeader),
17227 MockRead("\r\n"),
17228 MockRead("hello world"),
17229 MockRead(SYNCHRONOUS, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
17230 MockRead(ASYNC, OK),
17231 };
17232
17233 StaticSocketDataProvider http11_data(data_reads, base::span<MockWrite>());
17234 session_deps_.socket_factory->AddSocketDataProvider(&http11_data);
17235
17236 SSLSocketDataProvider ssl_http11(ASYNC, OK);
17237 ssl_http11.ssl_info.cert =
17238 ImportCertFromFile(GetTestCertsDirectory(), "wildcard.pem");
17239 ASSERT_TRUE(ssl_http11.ssl_info.cert);
17240 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_http11);
17241
17242 // Second transaction starts an alternative and a non-alternative Job.
17243 // Both sockets hang.
17244 MockConnect never_finishing_connect(SYNCHRONOUS, ERR_IO_PENDING);
17245 StaticSocketDataProvider hanging_socket1;
17246 hanging_socket1.set_connect_data(never_finishing_connect);
17247 session_deps_.socket_factory->AddSocketDataProvider(&hanging_socket1);
17248
17249 StaticSocketDataProvider hanging_socket2;
17250 hanging_socket2.set_connect_data(never_finishing_connect);
17251 session_deps_.socket_factory->AddSocketDataProvider(&hanging_socket2);
17252
17253 // Third transaction starts an alternative and a non-alternative job.
17254 // The non-alternative job hangs, but the alternative one succeeds.
17255 // The second transaction, still pending, binds to this socket.
17256 spdy::SpdySerializedFrame req1(
17257 spdy_util_.ConstructSpdyGet("https://www.example.org/", 1, LOWEST));
17258 spdy::SpdySerializedFrame req2(
17259 spdy_util_.ConstructSpdyGet("https://www.example.org/", 3, LOWEST));
17260 MockWrite spdy_writes[] = {
17261 CreateMockWrite(req1, 0),
17262 CreateMockWrite(req2, 1),
17263 };
17264 spdy::SpdySerializedFrame resp1(
17265 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
17266 spdy::SpdySerializedFrame data1(spdy_util_.ConstructSpdyDataFrame(1, true));
17267 spdy::SpdySerializedFrame resp2(
17268 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 3));
17269 spdy::SpdySerializedFrame data2(spdy_util_.ConstructSpdyDataFrame(3, true));
17270 MockRead spdy_reads[] = {
17271 CreateMockRead(resp1, 2), CreateMockRead(data1, 3),
17272 CreateMockRead(resp2, 4), CreateMockRead(data2, 5),
17273 MockRead(ASYNC, 0, 6),
17274 };
17275
17276 SequencedSocketData spdy_data(spdy_reads, spdy_writes);
17277 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
17278
17279 AddSSLSocketData();
17280
17281 StaticSocketDataProvider hanging_socket3;
17282 hanging_socket3.set_connect_data(never_finishing_connect);
17283 session_deps_.socket_factory->AddSocketDataProvider(&hanging_socket3);
17284
17285 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
17286 TestCompletionCallback callback1;
17287 HttpNetworkTransaction trans1(DEFAULT_PRIORITY, session.get());
17288
17289 int rv = trans1.Start(&request, callback1.callback(), NetLogWithSource());
17290 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
17291 EXPECT_THAT(callback1.WaitForResult(), IsOk());
17292
17293 const HttpResponseInfo* response = trans1.GetResponseInfo();
17294 ASSERT_TRUE(response);
17295 ASSERT_TRUE(response->headers);
17296 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
17297
17298 std::string response_data;
17299 ASSERT_THAT(ReadTransaction(&trans1, &response_data), IsOk());
17300 EXPECT_EQ("hello world", response_data);
17301
17302 TestCompletionCallback callback2;
17303 HttpNetworkTransaction trans2(DEFAULT_PRIORITY, session.get());
17304 rv = trans2.Start(&request, callback2.callback(), NetLogWithSource());
17305 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
17306
17307 TestCompletionCallback callback3;
17308 HttpNetworkTransaction trans3(DEFAULT_PRIORITY, session.get());
17309 rv = trans3.Start(&request, callback3.callback(), NetLogWithSource());
17310 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
17311
17312 EXPECT_THAT(callback2.WaitForResult(), IsOk());
17313 EXPECT_THAT(callback3.WaitForResult(), IsOk());
17314
17315 response = trans2.GetResponseInfo();
17316 ASSERT_TRUE(response);
17317 ASSERT_TRUE(response->headers);
17318 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
17319 EXPECT_TRUE(response->was_fetched_via_spdy);
17320 EXPECT_TRUE(response->was_alpn_negotiated);
17321 ASSERT_THAT(ReadTransaction(&trans2, &response_data), IsOk());
17322 EXPECT_EQ("hello!", response_data);
17323
17324 response = trans3.GetResponseInfo();
17325 ASSERT_TRUE(response);
17326 ASSERT_TRUE(response->headers);
17327 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
17328 EXPECT_TRUE(response->was_fetched_via_spdy);
17329 EXPECT_TRUE(response->was_alpn_negotiated);
17330 ASSERT_THAT(ReadTransaction(&trans3, &response_data), IsOk());
17331 EXPECT_EQ("hello!", response_data);
17332 }
17333
TEST_P(HttpNetworkTransactionTest,StallAlternativeServiceForNpnSpdy)17334 TEST_P(HttpNetworkTransactionTest, StallAlternativeServiceForNpnSpdy) {
17335 session_deps_.host_resolver->set_synchronous_mode(true);
17336
17337 HttpRequestInfo request;
17338 request.method = "GET";
17339 request.url = GURL("https://www.example.org/");
17340 request.traffic_annotation =
17341 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
17342
17343 MockRead data_reads[] = {
17344 MockRead("HTTP/1.1 200 OK\r\n"),
17345 MockRead(kAlternativeServiceHttpHeader),
17346 MockRead("\r\n"),
17347 MockRead("hello world"),
17348 MockRead(SYNCHRONOUS, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
17349 MockRead(ASYNC, OK),
17350 };
17351
17352 StaticSocketDataProvider first_transaction(data_reads,
17353 base::span<MockWrite>());
17354 session_deps_.socket_factory->AddSocketDataProvider(&first_transaction);
17355
17356 SSLSocketDataProvider ssl(ASYNC, OK);
17357 ssl.ssl_info.cert =
17358 ImportCertFromFile(GetTestCertsDirectory(), "wildcard.pem");
17359 ASSERT_TRUE(ssl.ssl_info.cert);
17360 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
17361
17362 MockConnect never_finishing_connect(SYNCHRONOUS, ERR_IO_PENDING);
17363 StaticSocketDataProvider hanging_alternate_protocol_socket;
17364 hanging_alternate_protocol_socket.set_connect_data(never_finishing_connect);
17365 session_deps_.socket_factory->AddSocketDataProvider(
17366 &hanging_alternate_protocol_socket);
17367
17368 // 2nd request is just a copy of the first one, over HTTP/1.1 again.
17369 StaticSocketDataProvider second_transaction(data_reads,
17370 base::span<MockWrite>());
17371 session_deps_.socket_factory->AddSocketDataProvider(&second_transaction);
17372 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
17373
17374 TestCompletionCallback callback;
17375
17376 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
17377 auto trans =
17378 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
17379
17380 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
17381 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
17382 EXPECT_THAT(callback.WaitForResult(), IsOk());
17383
17384 const HttpResponseInfo* response = trans->GetResponseInfo();
17385 ASSERT_TRUE(response);
17386 ASSERT_TRUE(response->headers);
17387 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
17388
17389 std::string response_data;
17390 ASSERT_THAT(ReadTransaction(trans.get(), &response_data), IsOk());
17391 EXPECT_EQ("hello world", response_data);
17392
17393 trans =
17394 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
17395
17396 rv = trans->Start(&request, callback.callback(), NetLogWithSource());
17397 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
17398 EXPECT_THAT(callback.WaitForResult(), IsOk());
17399
17400 response = trans->GetResponseInfo();
17401 ASSERT_TRUE(response);
17402 ASSERT_TRUE(response->headers);
17403 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
17404 EXPECT_FALSE(response->was_fetched_via_spdy);
17405 EXPECT_FALSE(response->was_alpn_negotiated);
17406
17407 ASSERT_THAT(ReadTransaction(trans.get(), &response_data), IsOk());
17408 EXPECT_EQ("hello world", response_data);
17409 }
17410
17411 // Test that proxy is resolved using the origin url,
17412 // regardless of the alternative server.
TEST_P(HttpNetworkTransactionTest,UseOriginNotAlternativeForProxy)17413 TEST_P(HttpNetworkTransactionTest, UseOriginNotAlternativeForProxy) {
17414 // Configure proxy to bypass www.example.org, which is the origin URL.
17415 ProxyConfig proxy_config;
17416 proxy_config.proxy_rules().ParseFromString("myproxy:70");
17417 proxy_config.proxy_rules().bypass_rules.AddRuleFromString("www.example.org");
17418 auto proxy_config_service = std::make_unique<ProxyConfigServiceFixed>(
17419 ProxyConfigWithAnnotation(proxy_config, TRAFFIC_ANNOTATION_FOR_TESTS));
17420
17421 CapturingProxyResolver capturing_proxy_resolver;
17422 auto proxy_resolver_factory = std::make_unique<CapturingProxyResolverFactory>(
17423 &capturing_proxy_resolver);
17424
17425 session_deps_.proxy_resolution_service =
17426 std::make_unique<ConfiguredProxyResolutionService>(
17427 std::move(proxy_config_service), std::move(proxy_resolver_factory),
17428 net::NetLog::Get(), /*quick_check_enabled=*/true);
17429
17430 session_deps_.net_log = net::NetLog::Get();
17431
17432 // Configure alternative service with a hostname that is not bypassed by the
17433 // proxy.
17434 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
17435 HttpServerProperties* http_server_properties =
17436 session->http_server_properties();
17437 url::SchemeHostPort server("https", "www.example.org", 443);
17438 HostPortPair alternative("www.example.com", 443);
17439 AlternativeService alternative_service(kProtoHTTP2, alternative);
17440 base::Time expiration = base::Time::Now() + base::Days(1);
17441 http_server_properties->SetHttp2AlternativeService(
17442 server, NetworkAnonymizationKey(), alternative_service, expiration);
17443
17444 // Non-alternative job should hang.
17445 MockConnect never_finishing_connect(SYNCHRONOUS, ERR_IO_PENDING);
17446 StaticSocketDataProvider hanging_alternate_protocol_socket;
17447 hanging_alternate_protocol_socket.set_connect_data(never_finishing_connect);
17448 session_deps_.socket_factory->AddSocketDataProvider(
17449 &hanging_alternate_protocol_socket);
17450
17451 AddSSLSocketData();
17452
17453 HttpRequestInfo request;
17454 request.method = "GET";
17455 request.url = GURL("https://www.example.org/");
17456 request.load_flags = 0;
17457 request.traffic_annotation =
17458 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
17459
17460 spdy::SpdySerializedFrame req(
17461 spdy_util_.ConstructSpdyGet("https://www.example.org/", 1, LOWEST));
17462
17463 MockWrite spdy_writes[] = {CreateMockWrite(req, 0)};
17464
17465 spdy::SpdySerializedFrame resp(
17466 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
17467 spdy::SpdySerializedFrame data(spdy_util_.ConstructSpdyDataFrame(1, true));
17468 MockRead spdy_reads[] = {
17469 CreateMockRead(resp, 1),
17470 CreateMockRead(data, 2),
17471 MockRead(ASYNC, 0, 3),
17472 };
17473
17474 SequencedSocketData spdy_data(spdy_reads, spdy_writes);
17475 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
17476
17477 TestCompletionCallback callback;
17478
17479 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
17480
17481 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
17482 EXPECT_THAT(callback.GetResult(rv), IsOk());
17483
17484 const HttpResponseInfo* response = trans.GetResponseInfo();
17485 ASSERT_TRUE(response);
17486 ASSERT_TRUE(response->headers);
17487 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
17488 EXPECT_TRUE(response->was_fetched_via_spdy);
17489 EXPECT_TRUE(response->was_alpn_negotiated);
17490
17491 std::string response_data;
17492 ASSERT_THAT(ReadTransaction(&trans, &response_data), IsOk());
17493 EXPECT_EQ("hello!", response_data);
17494
17495 // Origin host bypasses proxy, no resolution should have happened.
17496 ASSERT_TRUE(capturing_proxy_resolver.lookup_info().empty());
17497 }
17498
TEST_P(HttpNetworkTransactionTest,UseAlternativeServiceForTunneledNpnSpdy)17499 TEST_P(HttpNetworkTransactionTest, UseAlternativeServiceForTunneledNpnSpdy) {
17500 ProxyConfig proxy_config;
17501 proxy_config.set_auto_detect(true);
17502 proxy_config.set_pac_url(GURL("http://fooproxyurl"));
17503
17504 CapturingProxyResolver capturing_proxy_resolver;
17505 session_deps_.proxy_resolution_service =
17506 std::make_unique<ConfiguredProxyResolutionService>(
17507 std::make_unique<ProxyConfigServiceFixed>(ProxyConfigWithAnnotation(
17508 proxy_config, TRAFFIC_ANNOTATION_FOR_TESTS)),
17509 std::make_unique<CapturingProxyResolverFactory>(
17510 &capturing_proxy_resolver),
17511 nullptr, /*quick_check_enabled=*/true);
17512 session_deps_.net_log = net::NetLog::Get();
17513
17514 HttpRequestInfo request;
17515 request.method = "GET";
17516 request.url = GURL("https://www.example.org/");
17517 request.traffic_annotation =
17518 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
17519
17520 MockRead data_reads[] = {
17521 MockRead("HTTP/1.1 200 OK\r\n"),
17522 MockRead(kAlternativeServiceHttpHeader),
17523 MockRead("\r\n"),
17524 MockRead("hello world"),
17525 MockRead(SYNCHRONOUS, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
17526 MockRead(ASYNC, OK),
17527 };
17528
17529 StaticSocketDataProvider first_transaction(data_reads,
17530 base::span<MockWrite>());
17531 session_deps_.socket_factory->AddSocketDataProvider(&first_transaction);
17532 SSLSocketDataProvider ssl_http11(ASYNC, OK);
17533 ssl_http11.next_proto = kProtoHTTP11;
17534 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_http11);
17535
17536 AddSSLSocketData();
17537
17538 spdy::SpdySerializedFrame req(
17539 spdy_util_.ConstructSpdyGet("https://www.example.org/", 1, LOWEST));
17540 MockWrite spdy_writes[] = {
17541 MockWrite(ASYNC, 0,
17542 "CONNECT www.example.org:443 HTTP/1.1\r\n"
17543 "Host: www.example.org:443\r\n"
17544 "Proxy-Connection: keep-alive\r\n\r\n"),
17545 CreateMockWrite(req, 2),
17546 };
17547
17548 const char kCONNECTResponse[] = "HTTP/1.1 200 Connected\r\n\r\n";
17549
17550 spdy::SpdySerializedFrame resp(
17551 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
17552 spdy::SpdySerializedFrame data(spdy_util_.ConstructSpdyDataFrame(1, true));
17553 MockRead spdy_reads[] = {
17554 MockRead(ASYNC, 1, kCONNECTResponse),
17555 CreateMockRead(resp, 3),
17556 CreateMockRead(data, 4),
17557 MockRead(SYNCHRONOUS, ERR_IO_PENDING, 5),
17558 };
17559
17560 SequencedSocketData spdy_data(spdy_reads, spdy_writes);
17561 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
17562
17563 MockConnect never_finishing_connect(SYNCHRONOUS, ERR_IO_PENDING);
17564 StaticSocketDataProvider hanging_non_alternate_protocol_socket;
17565 hanging_non_alternate_protocol_socket.set_connect_data(
17566 never_finishing_connect);
17567 session_deps_.socket_factory->AddSocketDataProvider(
17568 &hanging_non_alternate_protocol_socket);
17569
17570 TestCompletionCallback callback;
17571
17572 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
17573 auto trans =
17574 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
17575
17576 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
17577 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
17578 EXPECT_THAT(callback.WaitForResult(), IsOk());
17579
17580 const HttpResponseInfo* response = trans->GetResponseInfo();
17581 ASSERT_TRUE(response);
17582 ASSERT_TRUE(response->headers);
17583 EXPECT_EQ("HTTP/0.9 200 OK", response->headers->GetStatusLine());
17584 EXPECT_FALSE(response->was_fetched_via_spdy);
17585 EXPECT_TRUE(response->was_alpn_negotiated);
17586
17587 std::string response_data;
17588 ASSERT_THAT(ReadTransaction(trans.get(), &response_data), IsOk());
17589 EXPECT_EQ("hello world", response_data);
17590
17591 trans =
17592 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
17593
17594 rv = trans->Start(&request, callback.callback(), NetLogWithSource());
17595 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
17596 EXPECT_THAT(callback.WaitForResult(), IsOk());
17597
17598 response = trans->GetResponseInfo();
17599 ASSERT_TRUE(response);
17600 ASSERT_TRUE(response->headers);
17601 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
17602 EXPECT_TRUE(response->was_fetched_via_spdy);
17603 EXPECT_TRUE(response->was_alpn_negotiated);
17604
17605 ASSERT_THAT(ReadTransaction(trans.get(), &response_data), IsOk());
17606 EXPECT_EQ("hello!", response_data);
17607 ASSERT_EQ(2u, capturing_proxy_resolver.lookup_info().size());
17608 EXPECT_EQ("https://www.example.org/",
17609 capturing_proxy_resolver.lookup_info()[0].url.spec());
17610 EXPECT_EQ("https://www.example.org/",
17611 capturing_proxy_resolver.lookup_info()[1].url.spec());
17612
17613 LoadTimingInfo load_timing_info;
17614 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
17615 TestLoadTimingNotReusedWithPac(load_timing_info,
17616 CONNECT_TIMING_HAS_SSL_TIMES);
17617 }
17618
TEST_P(HttpNetworkTransactionTest,UseAlternativeServiceForNpnSpdyWithExistingSpdySession)17619 TEST_P(HttpNetworkTransactionTest,
17620 UseAlternativeServiceForNpnSpdyWithExistingSpdySession) {
17621 HttpRequestInfo request;
17622 request.method = "GET";
17623 request.url = GURL("https://www.example.org/");
17624 request.traffic_annotation =
17625 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
17626
17627 MockRead data_reads[] = {
17628 MockRead("HTTP/1.1 200 OK\r\n"),
17629 MockRead(kAlternativeServiceHttpHeader),
17630 MockRead("\r\n"),
17631 MockRead("hello world"),
17632 MockRead(ASYNC, OK),
17633 };
17634
17635 StaticSocketDataProvider first_transaction(data_reads,
17636 base::span<MockWrite>());
17637 session_deps_.socket_factory->AddSocketDataProvider(&first_transaction);
17638 SSLSocketDataProvider ssl_http11(ASYNC, OK);
17639 ssl_http11.next_proto = kProtoHTTP11;
17640 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_http11);
17641
17642 AddSSLSocketData();
17643
17644 spdy::SpdySerializedFrame req(
17645 spdy_util_.ConstructSpdyGet("https://www.example.org/", 1, LOWEST));
17646 MockWrite spdy_writes[] = {CreateMockWrite(req, 0)};
17647
17648 spdy::SpdySerializedFrame resp(
17649 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
17650 spdy::SpdySerializedFrame data(spdy_util_.ConstructSpdyDataFrame(1, true));
17651 MockRead spdy_reads[] = {
17652 CreateMockRead(resp, 1),
17653 CreateMockRead(data, 2),
17654 MockRead(ASYNC, 0, 3),
17655 };
17656
17657 SequencedSocketData spdy_data(spdy_reads, spdy_writes);
17658 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
17659
17660 TestCompletionCallback callback;
17661
17662 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
17663
17664 auto trans =
17665 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
17666
17667 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
17668 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
17669 EXPECT_THAT(callback.WaitForResult(), IsOk());
17670
17671 const HttpResponseInfo* response = trans->GetResponseInfo();
17672 ASSERT_TRUE(response);
17673 ASSERT_TRUE(response->headers);
17674 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
17675
17676 std::string response_data;
17677 ASSERT_THAT(ReadTransaction(trans.get(), &response_data), IsOk());
17678 EXPECT_EQ("hello world", response_data);
17679
17680 // Set up an initial SpdySession in the pool to reuse.
17681 HostPortPair host_port_pair("www.example.org", 443);
17682 SpdySessionKey key(host_port_pair, PRIVACY_MODE_DISABLED,
17683 ProxyChain::Direct(), SessionUsage::kDestination,
17684 SocketTag(), NetworkAnonymizationKey(),
17685 SecureDnsPolicy::kAllow,
17686 /*disable_cert_verification_network_fetches=*/false);
17687 base::WeakPtr<SpdySession> spdy_session =
17688 CreateSpdySession(session.get(), key, NetLogWithSource());
17689
17690 trans =
17691 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
17692
17693 ConnectedHandler connected_handler;
17694 trans->SetConnectedCallback(connected_handler.Callback());
17695
17696 rv = trans->Start(&request, callback.callback(), NetLogWithSource());
17697 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
17698 EXPECT_THAT(callback.WaitForResult(), IsOk());
17699
17700 TransportInfo expected_transport;
17701 expected_transport.type = TransportType::kDirect;
17702 expected_transport.endpoint = IPEndPoint(IPAddress::IPv4Localhost(), 443);
17703 expected_transport.negotiated_protocol = kProtoHTTP2;
17704 EXPECT_THAT(connected_handler.transports(), ElementsAre(expected_transport));
17705
17706 response = trans->GetResponseInfo();
17707 ASSERT_TRUE(response);
17708 ASSERT_TRUE(response->headers);
17709 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
17710 EXPECT_TRUE(response->was_fetched_via_spdy);
17711 EXPECT_TRUE(response->was_alpn_negotiated);
17712
17713 ASSERT_THAT(ReadTransaction(trans.get(), &response_data), IsOk());
17714 EXPECT_EQ("hello!", response_data);
17715 }
17716
17717 // GenerateAuthToken is a mighty big test.
17718 // It tests all permutation of GenerateAuthToken behavior:
17719 // - Synchronous and Asynchronous completion.
17720 // - OK or error on completion.
17721 // - Direct connection, non-authenticating proxy, and authenticating proxy.
17722 // - HTTP or HTTPS backend (to include proxy tunneling).
17723 // - Non-authenticating and authenticating backend.
17724 //
17725 // In all, there are 44 reasonable permuations (for example, if there are
17726 // problems generating an auth token for an authenticating proxy, we don't
17727 // need to test all permutations of the backend server).
17728 //
17729 // The test proceeds by going over each of the configuration cases, and
17730 // potentially running up to three rounds in each of the tests. The TestConfig
17731 // specifies both the configuration for the test as well as the expectations
17732 // for the results.
TEST_P(HttpNetworkTransactionTest,GenerateAuthToken)17733 TEST_P(HttpNetworkTransactionTest, GenerateAuthToken) {
17734 static const char kServer[] = "http://www.example.com";
17735 static const char kSecureServer[] = "https://www.example.com";
17736 static const char kProxy[] = "myproxy:70";
17737
17738 enum AuthTiming {
17739 AUTH_NONE,
17740 AUTH_SYNC,
17741 AUTH_ASYNC,
17742 };
17743
17744 const MockWrite kGet(
17745 "GET / HTTP/1.1\r\n"
17746 "Host: www.example.com\r\n"
17747 "Connection: keep-alive\r\n\r\n");
17748 const MockWrite kGetProxy(
17749 "GET http://www.example.com/ HTTP/1.1\r\n"
17750 "Host: www.example.com\r\n"
17751 "Proxy-Connection: keep-alive\r\n\r\n");
17752 const MockWrite kGetAuth(
17753 "GET / HTTP/1.1\r\n"
17754 "Host: www.example.com\r\n"
17755 "Connection: keep-alive\r\n"
17756 "Authorization: auth_token\r\n\r\n");
17757 const MockWrite kGetProxyAuth(
17758 "GET http://www.example.com/ HTTP/1.1\r\n"
17759 "Host: www.example.com\r\n"
17760 "Proxy-Connection: keep-alive\r\n"
17761 "Proxy-Authorization: auth_token\r\n\r\n");
17762 const MockWrite kGetAuthThroughProxy(
17763 "GET http://www.example.com/ HTTP/1.1\r\n"
17764 "Host: www.example.com\r\n"
17765 "Proxy-Connection: keep-alive\r\n"
17766 "Authorization: auth_token\r\n\r\n");
17767 const MockWrite kGetAuthWithProxyAuth(
17768 "GET http://www.example.com/ HTTP/1.1\r\n"
17769 "Host: www.example.com\r\n"
17770 "Proxy-Connection: keep-alive\r\n"
17771 "Proxy-Authorization: auth_token\r\n"
17772 "Authorization: auth_token\r\n\r\n");
17773 const MockWrite kConnect(
17774 "CONNECT www.example.com:443 HTTP/1.1\r\n"
17775 "Host: www.example.com:443\r\n"
17776 "Proxy-Connection: keep-alive\r\n\r\n");
17777 const MockWrite kConnectProxyAuth(
17778 "CONNECT www.example.com:443 HTTP/1.1\r\n"
17779 "Host: www.example.com:443\r\n"
17780 "Proxy-Connection: keep-alive\r\n"
17781 "Proxy-Authorization: auth_token\r\n\r\n");
17782
17783 const MockRead kSuccess(
17784 "HTTP/1.1 200 OK\r\n"
17785 "Content-Type: text/html; charset=iso-8859-1\r\n"
17786 "Content-Length: 3\r\n\r\n"
17787 "Yes");
17788 const MockRead kFailure("Should not be called.");
17789 const MockRead kServerChallenge(
17790 "HTTP/1.1 401 Unauthorized\r\n"
17791 "WWW-Authenticate: Mock realm=server\r\n"
17792 "Content-Type: text/html; charset=iso-8859-1\r\n"
17793 "Content-Length: 14\r\n\r\n"
17794 "Unauthorized\r\n");
17795 const MockRead kProxyChallenge(
17796 "HTTP/1.1 407 Unauthorized\r\n"
17797 "Proxy-Authenticate: Mock realm=proxy\r\n"
17798 "Proxy-Connection: close\r\n"
17799 "Content-Type: text/html; charset=iso-8859-1\r\n"
17800 "Content-Length: 14\r\n\r\n"
17801 "Unauthorized\r\n");
17802 const MockRead kProxyConnected("HTTP/1.1 200 Connection Established\r\n\r\n");
17803
17804 // NOTE(cbentzel): I wanted TestReadWriteRound to be a simple struct with
17805 // no constructors, but the C++ compiler on Windows warns about
17806 // unspecified data in compound literals. So, moved to using constructors,
17807 // and TestRound's created with the default constructor should not be used.
17808 struct TestRound {
17809 TestRound()
17810 : expected_rv(ERR_UNEXPECTED),
17811 extra_write(nullptr),
17812 extra_read(nullptr) {}
17813 TestRound(const MockWrite& write_arg,
17814 const MockRead& read_arg,
17815 int expected_rv_arg)
17816 : write(write_arg),
17817 read(read_arg),
17818 expected_rv(expected_rv_arg),
17819 extra_write(nullptr),
17820 extra_read(nullptr) {}
17821 TestRound(const MockWrite& write_arg,
17822 const MockRead& read_arg,
17823 int expected_rv_arg,
17824 const MockWrite* extra_write_arg,
17825 const MockRead* extra_read_arg)
17826 : write(write_arg),
17827 read(read_arg),
17828 expected_rv(expected_rv_arg),
17829 extra_write(extra_write_arg),
17830 extra_read(extra_read_arg) {}
17831 MockWrite write;
17832 MockRead read;
17833 int expected_rv;
17834 raw_ptr<const MockWrite> extra_write = nullptr;
17835 raw_ptr<const MockRead> extra_read = nullptr;
17836 };
17837
17838 static const int kNoSSL = 500;
17839
17840 struct TestConfig {
17841 int line_number;
17842 const char* const proxy_url;
17843 AuthTiming proxy_auth_timing;
17844 int first_generate_proxy_token_rv;
17845 const char* const server_url;
17846 AuthTiming server_auth_timing;
17847 int first_generate_server_token_rv;
17848 int num_auth_rounds;
17849 int first_ssl_round;
17850 TestRound rounds[4];
17851 } test_configs[] = {
17852 // Non-authenticating HTTP server with a direct connection.
17853 {__LINE__,
17854 nullptr,
17855 AUTH_NONE,
17856 OK,
17857 kServer,
17858 AUTH_NONE,
17859 OK,
17860 1,
17861 kNoSSL,
17862 {TestRound(kGet, kSuccess, OK)}},
17863 // Authenticating HTTP server with a direct connection.
17864 {__LINE__,
17865 nullptr,
17866 AUTH_NONE,
17867 OK,
17868 kServer,
17869 AUTH_SYNC,
17870 OK,
17871 2,
17872 kNoSSL,
17873 {TestRound(kGet, kServerChallenge, OK),
17874 TestRound(kGetAuth, kSuccess, OK)}},
17875 {__LINE__,
17876 nullptr,
17877 AUTH_NONE,
17878 OK,
17879 kServer,
17880 AUTH_SYNC,
17881 ERR_INVALID_AUTH_CREDENTIALS,
17882 3,
17883 kNoSSL,
17884 {TestRound(kGet, kServerChallenge, OK),
17885 TestRound(kGet, kServerChallenge, OK),
17886 TestRound(kGetAuth, kSuccess, OK)}},
17887 {__LINE__,
17888 nullptr,
17889 AUTH_NONE,
17890 OK,
17891 kServer,
17892 AUTH_SYNC,
17893 ERR_UNSUPPORTED_AUTH_SCHEME,
17894 2,
17895 kNoSSL,
17896 {TestRound(kGet, kServerChallenge, OK), TestRound(kGet, kSuccess, OK)}},
17897 {__LINE__,
17898 nullptr,
17899 AUTH_NONE,
17900 OK,
17901 kServer,
17902 AUTH_SYNC,
17903 ERR_UNDOCUMENTED_SECURITY_LIBRARY_STATUS,
17904 2,
17905 kNoSSL,
17906 {TestRound(kGet, kServerChallenge, OK), TestRound(kGet, kSuccess, OK)}},
17907 {__LINE__,
17908 kProxy,
17909 AUTH_SYNC,
17910 ERR_FAILED,
17911 kServer,
17912 AUTH_NONE,
17913 OK,
17914 2,
17915 kNoSSL,
17916 {TestRound(kGetProxy, kProxyChallenge, OK),
17917 TestRound(kGetProxy, kFailure, ERR_FAILED)}},
17918 {__LINE__,
17919 kProxy,
17920 AUTH_ASYNC,
17921 ERR_FAILED,
17922 kServer,
17923 AUTH_NONE,
17924 OK,
17925 2,
17926 kNoSSL,
17927 {TestRound(kGetProxy, kProxyChallenge, OK),
17928 TestRound(kGetProxy, kFailure, ERR_FAILED)}},
17929 {__LINE__,
17930 nullptr,
17931 AUTH_NONE,
17932 OK,
17933 kServer,
17934 AUTH_SYNC,
17935 ERR_FAILED,
17936 2,
17937 kNoSSL,
17938 {TestRound(kGet, kServerChallenge, OK),
17939 TestRound(kGet, kFailure, ERR_FAILED)}},
17940 {__LINE__,
17941 nullptr,
17942 AUTH_NONE,
17943 OK,
17944 kServer,
17945 AUTH_ASYNC,
17946 ERR_FAILED,
17947 2,
17948 kNoSSL,
17949 {TestRound(kGet, kServerChallenge, OK),
17950 TestRound(kGet, kFailure, ERR_FAILED)}},
17951 {__LINE__,
17952 nullptr,
17953 AUTH_NONE,
17954 OK,
17955 kServer,
17956 AUTH_ASYNC,
17957 OK,
17958 2,
17959 kNoSSL,
17960 {TestRound(kGet, kServerChallenge, OK),
17961 TestRound(kGetAuth, kSuccess, OK)}},
17962 {__LINE__,
17963 nullptr,
17964 AUTH_NONE,
17965 OK,
17966 kServer,
17967 AUTH_ASYNC,
17968 ERR_INVALID_AUTH_CREDENTIALS,
17969 3,
17970 kNoSSL,
17971 {TestRound(kGet, kServerChallenge, OK),
17972 // The second round uses a HttpAuthHandlerMock that always succeeds.
17973 TestRound(kGet, kServerChallenge, OK),
17974 TestRound(kGetAuth, kSuccess, OK)}},
17975 // Non-authenticating HTTP server through a non-authenticating proxy.
17976 {__LINE__,
17977 kProxy,
17978 AUTH_NONE,
17979 OK,
17980 kServer,
17981 AUTH_NONE,
17982 OK,
17983 1,
17984 kNoSSL,
17985 {TestRound(kGetProxy, kSuccess, OK)}},
17986 // Authenticating HTTP server through a non-authenticating proxy.
17987 {__LINE__,
17988 kProxy,
17989 AUTH_NONE,
17990 OK,
17991 kServer,
17992 AUTH_SYNC,
17993 OK,
17994 2,
17995 kNoSSL,
17996 {TestRound(kGetProxy, kServerChallenge, OK),
17997 TestRound(kGetAuthThroughProxy, kSuccess, OK)}},
17998 {__LINE__,
17999 kProxy,
18000 AUTH_NONE,
18001 OK,
18002 kServer,
18003 AUTH_SYNC,
18004 ERR_INVALID_AUTH_CREDENTIALS,
18005 3,
18006 kNoSSL,
18007 {TestRound(kGetProxy, kServerChallenge, OK),
18008 TestRound(kGetProxy, kServerChallenge, OK),
18009 TestRound(kGetAuthThroughProxy, kSuccess, OK)}},
18010 {__LINE__,
18011 kProxy,
18012 AUTH_NONE,
18013 OK,
18014 kServer,
18015 AUTH_ASYNC,
18016 OK,
18017 2,
18018 kNoSSL,
18019 {TestRound(kGetProxy, kServerChallenge, OK),
18020 TestRound(kGetAuthThroughProxy, kSuccess, OK)}},
18021 {__LINE__,
18022 kProxy,
18023 AUTH_NONE,
18024 OK,
18025 kServer,
18026 AUTH_ASYNC,
18027 ERR_INVALID_AUTH_CREDENTIALS,
18028 2,
18029 kNoSSL,
18030 {TestRound(kGetProxy, kServerChallenge, OK),
18031 TestRound(kGetProxy, kSuccess, OK)}},
18032 // Non-authenticating HTTP server through an authenticating proxy.
18033 {__LINE__,
18034 kProxy,
18035 AUTH_SYNC,
18036 OK,
18037 kServer,
18038 AUTH_NONE,
18039 OK,
18040 2,
18041 kNoSSL,
18042 {TestRound(kGetProxy, kProxyChallenge, OK),
18043 TestRound(kGetProxyAuth, kSuccess, OK)}},
18044 {__LINE__,
18045 kProxy,
18046 AUTH_SYNC,
18047 ERR_INVALID_AUTH_CREDENTIALS,
18048 kServer,
18049 AUTH_NONE,
18050 OK,
18051 2,
18052 kNoSSL,
18053 {TestRound(kGetProxy, kProxyChallenge, OK),
18054 TestRound(kGetProxy, kSuccess, OK)}},
18055 {__LINE__,
18056 kProxy,
18057 AUTH_ASYNC,
18058 OK,
18059 kServer,
18060 AUTH_NONE,
18061 OK,
18062 2,
18063 kNoSSL,
18064 {TestRound(kGetProxy, kProxyChallenge, OK),
18065 TestRound(kGetProxyAuth, kSuccess, OK)}},
18066 {__LINE__,
18067 kProxy,
18068 AUTH_ASYNC,
18069 ERR_INVALID_AUTH_CREDENTIALS,
18070 kServer,
18071 AUTH_NONE,
18072 OK,
18073 2,
18074 kNoSSL,
18075 {TestRound(kGetProxy, kProxyChallenge, OK),
18076 TestRound(kGetProxy, kSuccess, OK)}},
18077 {__LINE__,
18078 kProxy,
18079 AUTH_ASYNC,
18080 ERR_INVALID_AUTH_CREDENTIALS,
18081 kServer,
18082 AUTH_NONE,
18083 OK,
18084 3,
18085 kNoSSL,
18086 {TestRound(kGetProxy, kProxyChallenge, OK),
18087 TestRound(kGetProxy, kProxyChallenge, OK),
18088 TestRound(kGetProxyAuth, kSuccess, OK)}},
18089 // Authenticating HTTP server through an authenticating proxy.
18090 {__LINE__,
18091 kProxy,
18092 AUTH_SYNC,
18093 OK,
18094 kServer,
18095 AUTH_SYNC,
18096 OK,
18097 3,
18098 kNoSSL,
18099 {TestRound(kGetProxy, kProxyChallenge, OK),
18100 TestRound(kGetProxyAuth, kServerChallenge, OK),
18101 TestRound(kGetAuthWithProxyAuth, kSuccess, OK)}},
18102 {__LINE__,
18103 kProxy,
18104 AUTH_SYNC,
18105 OK,
18106 kServer,
18107 AUTH_SYNC,
18108 ERR_INVALID_AUTH_CREDENTIALS,
18109 3,
18110 kNoSSL,
18111 {TestRound(kGetProxy, kProxyChallenge, OK),
18112 TestRound(kGetProxyAuth, kServerChallenge, OK),
18113 TestRound(kGetProxyAuth, kSuccess, OK)}},
18114 {__LINE__,
18115 kProxy,
18116 AUTH_ASYNC,
18117 OK,
18118 kServer,
18119 AUTH_SYNC,
18120 OK,
18121 3,
18122 kNoSSL,
18123 {TestRound(kGetProxy, kProxyChallenge, OK),
18124 TestRound(kGetProxyAuth, kServerChallenge, OK),
18125 TestRound(kGetAuthWithProxyAuth, kSuccess, OK)}},
18126 {__LINE__,
18127 kProxy,
18128 AUTH_ASYNC,
18129 OK,
18130 kServer,
18131 AUTH_SYNC,
18132 ERR_INVALID_AUTH_CREDENTIALS,
18133 3,
18134 kNoSSL,
18135 {TestRound(kGetProxy, kProxyChallenge, OK),
18136 TestRound(kGetProxyAuth, kServerChallenge, OK),
18137 TestRound(kGetProxyAuth, kSuccess, OK)}},
18138 {__LINE__,
18139 kProxy,
18140 AUTH_SYNC,
18141 OK,
18142 kServer,
18143 AUTH_ASYNC,
18144 OK,
18145 3,
18146 kNoSSL,
18147 {TestRound(kGetProxy, kProxyChallenge, OK),
18148 TestRound(kGetProxyAuth, kServerChallenge, OK),
18149 TestRound(kGetAuthWithProxyAuth, kSuccess, OK)}},
18150 {__LINE__,
18151 kProxy,
18152 AUTH_SYNC,
18153 ERR_INVALID_AUTH_CREDENTIALS,
18154 kServer,
18155 AUTH_ASYNC,
18156 OK,
18157 4,
18158 kNoSSL,
18159 {TestRound(kGetProxy, kProxyChallenge, OK),
18160 TestRound(kGetProxy, kProxyChallenge, OK),
18161 TestRound(kGetProxyAuth, kServerChallenge, OK),
18162 TestRound(kGetAuthWithProxyAuth, kSuccess, OK)}},
18163 {__LINE__,
18164 kProxy,
18165 AUTH_SYNC,
18166 OK,
18167 kServer,
18168 AUTH_ASYNC,
18169 ERR_INVALID_AUTH_CREDENTIALS,
18170 3,
18171 kNoSSL,
18172 {TestRound(kGetProxy, kProxyChallenge, OK),
18173 TestRound(kGetProxyAuth, kServerChallenge, OK),
18174 TestRound(kGetProxyAuth, kSuccess, OK)}},
18175 {__LINE__,
18176 kProxy,
18177 AUTH_ASYNC,
18178 OK,
18179 kServer,
18180 AUTH_ASYNC,
18181 OK,
18182 3,
18183 kNoSSL,
18184 {TestRound(kGetProxy, kProxyChallenge, OK),
18185 TestRound(kGetProxyAuth, kServerChallenge, OK),
18186 TestRound(kGetAuthWithProxyAuth, kSuccess, OK)}},
18187 {__LINE__,
18188 kProxy,
18189 AUTH_ASYNC,
18190 OK,
18191 kServer,
18192 AUTH_ASYNC,
18193 ERR_INVALID_AUTH_CREDENTIALS,
18194 3,
18195 kNoSSL,
18196 {TestRound(kGetProxy, kProxyChallenge, OK),
18197 TestRound(kGetProxyAuth, kServerChallenge, OK),
18198 TestRound(kGetProxyAuth, kSuccess, OK)}},
18199 {__LINE__,
18200 kProxy,
18201 AUTH_ASYNC,
18202 ERR_INVALID_AUTH_CREDENTIALS,
18203 kServer,
18204 AUTH_ASYNC,
18205 ERR_INVALID_AUTH_CREDENTIALS,
18206 4,
18207 kNoSSL,
18208 {TestRound(kGetProxy, kProxyChallenge, OK),
18209 TestRound(kGetProxy, kProxyChallenge, OK),
18210 TestRound(kGetProxyAuth, kServerChallenge, OK),
18211 TestRound(kGetProxyAuth, kSuccess, OK)}},
18212 // Non-authenticating HTTPS server with a direct connection.
18213 {__LINE__,
18214 nullptr,
18215 AUTH_NONE,
18216 OK,
18217 kSecureServer,
18218 AUTH_NONE,
18219 OK,
18220 1,
18221 0,
18222 {TestRound(kGet, kSuccess, OK)}},
18223 // Authenticating HTTPS server with a direct connection.
18224 {__LINE__,
18225 nullptr,
18226 AUTH_NONE,
18227 OK,
18228 kSecureServer,
18229 AUTH_SYNC,
18230 OK,
18231 2,
18232 0,
18233 {TestRound(kGet, kServerChallenge, OK),
18234 TestRound(kGetAuth, kSuccess, OK)}},
18235 {__LINE__,
18236 nullptr,
18237 AUTH_NONE,
18238 OK,
18239 kSecureServer,
18240 AUTH_SYNC,
18241 ERR_INVALID_AUTH_CREDENTIALS,
18242 2,
18243 0,
18244 {TestRound(kGet, kServerChallenge, OK), TestRound(kGet, kSuccess, OK)}},
18245 {__LINE__,
18246 nullptr,
18247 AUTH_NONE,
18248 OK,
18249 kSecureServer,
18250 AUTH_ASYNC,
18251 OK,
18252 2,
18253 0,
18254 {TestRound(kGet, kServerChallenge, OK),
18255 TestRound(kGetAuth, kSuccess, OK)}},
18256 {__LINE__,
18257 nullptr,
18258 AUTH_NONE,
18259 OK,
18260 kSecureServer,
18261 AUTH_ASYNC,
18262 ERR_INVALID_AUTH_CREDENTIALS,
18263 2,
18264 0,
18265 {TestRound(kGet, kServerChallenge, OK), TestRound(kGet, kSuccess, OK)}},
18266 // Non-authenticating HTTPS server with a non-authenticating proxy.
18267 {__LINE__,
18268 kProxy,
18269 AUTH_NONE,
18270 OK,
18271 kSecureServer,
18272 AUTH_NONE,
18273 OK,
18274 1,
18275 0,
18276 {TestRound(kConnect, kProxyConnected, OK, &kGet, &kSuccess)}},
18277 // Authenticating HTTPS server through a non-authenticating proxy.
18278 {__LINE__,
18279 kProxy,
18280 AUTH_NONE,
18281 OK,
18282 kSecureServer,
18283 AUTH_SYNC,
18284 OK,
18285 2,
18286 0,
18287 {TestRound(kConnect, kProxyConnected, OK, &kGet, &kServerChallenge),
18288 TestRound(kGetAuth, kSuccess, OK)}},
18289 {__LINE__,
18290 kProxy,
18291 AUTH_NONE,
18292 OK,
18293 kSecureServer,
18294 AUTH_SYNC,
18295 ERR_INVALID_AUTH_CREDENTIALS,
18296 2,
18297 0,
18298 {TestRound(kConnect, kProxyConnected, OK, &kGet, &kServerChallenge),
18299 TestRound(kGet, kSuccess, OK)}},
18300 {__LINE__,
18301 kProxy,
18302 AUTH_NONE,
18303 OK,
18304 kSecureServer,
18305 AUTH_ASYNC,
18306 OK,
18307 2,
18308 0,
18309 {TestRound(kConnect, kProxyConnected, OK, &kGet, &kServerChallenge),
18310 TestRound(kGetAuth, kSuccess, OK)}},
18311 {__LINE__,
18312 kProxy,
18313 AUTH_NONE,
18314 OK,
18315 kSecureServer,
18316 AUTH_ASYNC,
18317 ERR_INVALID_AUTH_CREDENTIALS,
18318 2,
18319 0,
18320 {TestRound(kConnect, kProxyConnected, OK, &kGet, &kServerChallenge),
18321 TestRound(kGet, kSuccess, OK)}},
18322 // Non-Authenticating HTTPS server through an authenticating proxy.
18323 {__LINE__,
18324 kProxy,
18325 AUTH_SYNC,
18326 OK,
18327 kSecureServer,
18328 AUTH_NONE,
18329 OK,
18330 2,
18331 1,
18332 {TestRound(kConnect, kProxyChallenge, OK),
18333 TestRound(kConnectProxyAuth, kProxyConnected, OK, &kGet, &kSuccess)}},
18334 {__LINE__,
18335 kProxy,
18336 AUTH_SYNC,
18337 ERR_INVALID_AUTH_CREDENTIALS,
18338 kSecureServer,
18339 AUTH_NONE,
18340 OK,
18341 2,
18342 kNoSSL,
18343 {TestRound(kConnect, kProxyChallenge, OK),
18344 TestRound(kConnect, kProxyConnected, OK, &kGet, &kSuccess)}},
18345 {__LINE__,
18346 kProxy,
18347 AUTH_SYNC,
18348 ERR_UNSUPPORTED_AUTH_SCHEME,
18349 kSecureServer,
18350 AUTH_NONE,
18351 OK,
18352 2,
18353 kNoSSL,
18354 {TestRound(kConnect, kProxyChallenge, OK),
18355 TestRound(kConnect, kProxyConnected, OK, &kGet, &kSuccess)}},
18356 {__LINE__,
18357 kProxy,
18358 AUTH_SYNC,
18359 ERR_UNEXPECTED,
18360 kSecureServer,
18361 AUTH_NONE,
18362 OK,
18363 2,
18364 kNoSSL,
18365 {TestRound(kConnect, kProxyChallenge, OK),
18366 TestRound(kConnect, kProxyConnected, ERR_UNEXPECTED)}},
18367 {__LINE__,
18368 kProxy,
18369 AUTH_ASYNC,
18370 OK,
18371 kSecureServer,
18372 AUTH_NONE,
18373 OK,
18374 2,
18375 1,
18376 {TestRound(kConnect, kProxyChallenge, OK),
18377 TestRound(kConnectProxyAuth, kProxyConnected, OK, &kGet, &kSuccess)}},
18378 {__LINE__,
18379 kProxy,
18380 AUTH_ASYNC,
18381 ERR_INVALID_AUTH_CREDENTIALS,
18382 kSecureServer,
18383 AUTH_NONE,
18384 OK,
18385 2,
18386 kNoSSL,
18387 {TestRound(kConnect, kProxyChallenge, OK),
18388 TestRound(kConnect, kProxyConnected, OK, &kGet, &kSuccess)}},
18389 // Authenticating HTTPS server through an authenticating proxy.
18390 {__LINE__,
18391 kProxy,
18392 AUTH_SYNC,
18393 OK,
18394 kSecureServer,
18395 AUTH_SYNC,
18396 OK,
18397 3,
18398 1,
18399 {TestRound(kConnect, kProxyChallenge, OK),
18400 TestRound(kConnectProxyAuth, kProxyConnected, OK, &kGet,
18401 &kServerChallenge),
18402 TestRound(kGetAuth, kSuccess, OK)}},
18403 {__LINE__,
18404 kProxy,
18405 AUTH_SYNC,
18406 OK,
18407 kSecureServer,
18408 AUTH_SYNC,
18409 ERR_INVALID_AUTH_CREDENTIALS,
18410 3,
18411 1,
18412 {TestRound(kConnect, kProxyChallenge, OK),
18413 TestRound(kConnectProxyAuth, kProxyConnected, OK, &kGet,
18414 &kServerChallenge),
18415 TestRound(kGet, kSuccess, OK)}},
18416 {__LINE__,
18417 kProxy,
18418 AUTH_ASYNC,
18419 OK,
18420 kSecureServer,
18421 AUTH_SYNC,
18422 OK,
18423 3,
18424 1,
18425 {TestRound(kConnect, kProxyChallenge, OK),
18426 TestRound(kConnectProxyAuth, kProxyConnected, OK, &kGet,
18427 &kServerChallenge),
18428 TestRound(kGetAuth, kSuccess, OK)}},
18429 {__LINE__,
18430 kProxy,
18431 AUTH_ASYNC,
18432 OK,
18433 kSecureServer,
18434 AUTH_SYNC,
18435 ERR_INVALID_AUTH_CREDENTIALS,
18436 3,
18437 1,
18438 {TestRound(kConnect, kProxyChallenge, OK),
18439 TestRound(kConnectProxyAuth, kProxyConnected, OK, &kGet,
18440 &kServerChallenge),
18441 TestRound(kGet, kSuccess, OK)}},
18442 {__LINE__,
18443 kProxy,
18444 AUTH_SYNC,
18445 OK,
18446 kSecureServer,
18447 AUTH_ASYNC,
18448 OK,
18449 3,
18450 1,
18451 {TestRound(kConnect, kProxyChallenge, OK),
18452 TestRound(kConnectProxyAuth, kProxyConnected, OK, &kGet,
18453 &kServerChallenge),
18454 TestRound(kGetAuth, kSuccess, OK)}},
18455 {__LINE__,
18456 kProxy,
18457 AUTH_SYNC,
18458 OK,
18459 kSecureServer,
18460 AUTH_ASYNC,
18461 ERR_INVALID_AUTH_CREDENTIALS,
18462 3,
18463 1,
18464 {TestRound(kConnect, kProxyChallenge, OK),
18465 TestRound(kConnectProxyAuth, kProxyConnected, OK, &kGet,
18466 &kServerChallenge),
18467 TestRound(kGet, kSuccess, OK)}},
18468 {__LINE__,
18469 kProxy,
18470 AUTH_ASYNC,
18471 OK,
18472 kSecureServer,
18473 AUTH_ASYNC,
18474 OK,
18475 3,
18476 1,
18477 {TestRound(kConnect, kProxyChallenge, OK),
18478 TestRound(kConnectProxyAuth, kProxyConnected, OK, &kGet,
18479 &kServerChallenge),
18480 TestRound(kGetAuth, kSuccess, OK)}},
18481 {__LINE__,
18482 kProxy,
18483 AUTH_ASYNC,
18484 OK,
18485 kSecureServer,
18486 AUTH_ASYNC,
18487 ERR_INVALID_AUTH_CREDENTIALS,
18488 3,
18489 1,
18490 {TestRound(kConnect, kProxyChallenge, OK),
18491 TestRound(kConnectProxyAuth, kProxyConnected, OK, &kGet,
18492 &kServerChallenge),
18493 TestRound(kGet, kSuccess, OK)}},
18494 {__LINE__,
18495 kProxy,
18496 AUTH_ASYNC,
18497 ERR_INVALID_AUTH_CREDENTIALS,
18498 kSecureServer,
18499 AUTH_ASYNC,
18500 ERR_INVALID_AUTH_CREDENTIALS,
18501 4,
18502 2,
18503 {TestRound(kConnect, kProxyChallenge, OK),
18504 TestRound(kConnect, kProxyChallenge, OK),
18505 TestRound(kConnectProxyAuth, kProxyConnected, OK, &kGet,
18506 &kServerChallenge),
18507 TestRound(kGet, kSuccess, OK)}},
18508 };
18509
18510 for (const auto& test_config : test_configs) {
18511 SCOPED_TRACE(::testing::Message()
18512 << "Test config at " << test_config.line_number);
18513 auto auth_factory = std::make_unique<HttpAuthHandlerMock::Factory>();
18514 auto* auth_factory_ptr = auth_factory.get();
18515 session_deps_.http_auth_handler_factory = std::move(auth_factory);
18516 SSLInfo empty_ssl_info;
18517
18518 // Set up authentication handlers as necessary.
18519 if (test_config.proxy_auth_timing != AUTH_NONE) {
18520 for (int n = 0; n < 3; n++) {
18521 auto auth_handler = std::make_unique<HttpAuthHandlerMock>();
18522 std::string auth_challenge = "Mock realm=proxy";
18523 url::SchemeHostPort scheme_host_port(GURL(test_config.proxy_url));
18524 HttpAuthChallengeTokenizer tokenizer(auth_challenge.begin(),
18525 auth_challenge.end());
18526 auth_handler->InitFromChallenge(
18527 &tokenizer, HttpAuth::AUTH_PROXY, empty_ssl_info,
18528 NetworkAnonymizationKey(), scheme_host_port, NetLogWithSource());
18529 auth_handler->SetGenerateExpectation(
18530 test_config.proxy_auth_timing == AUTH_ASYNC,
18531 n == 0 ? test_config.first_generate_proxy_token_rv : OK);
18532 auth_factory_ptr->AddMockHandler(std::move(auth_handler),
18533 HttpAuth::AUTH_PROXY);
18534 }
18535 }
18536 if (test_config.server_auth_timing != AUTH_NONE) {
18537 auto auth_handler = std::make_unique<HttpAuthHandlerMock>();
18538 std::string auth_challenge = "Mock realm=server";
18539 url::SchemeHostPort scheme_host_port(GURL(test_config.server_url));
18540 HttpAuthChallengeTokenizer tokenizer(auth_challenge.begin(),
18541 auth_challenge.end());
18542 auth_handler->InitFromChallenge(&tokenizer, HttpAuth::AUTH_SERVER,
18543 empty_ssl_info, NetworkAnonymizationKey(),
18544 scheme_host_port, NetLogWithSource());
18545 auth_handler->SetGenerateExpectation(
18546 test_config.server_auth_timing == AUTH_ASYNC,
18547 test_config.first_generate_server_token_rv);
18548 auth_factory_ptr->AddMockHandler(std::move(auth_handler),
18549 HttpAuth::AUTH_SERVER);
18550
18551 // The second handler always succeeds. It should only be used where there
18552 // are multiple auth sessions for server auth in the same network
18553 // transaction using the same auth scheme.
18554 std::unique_ptr<HttpAuthHandlerMock> second_handler =
18555 std::make_unique<HttpAuthHandlerMock>();
18556 second_handler->InitFromChallenge(
18557 &tokenizer, HttpAuth::AUTH_SERVER, empty_ssl_info,
18558 NetworkAnonymizationKey(), scheme_host_port, NetLogWithSource());
18559 second_handler->SetGenerateExpectation(true, OK);
18560 auth_factory_ptr->AddMockHandler(std::move(second_handler),
18561 HttpAuth::AUTH_SERVER);
18562 }
18563 if (test_config.proxy_url) {
18564 session_deps_.proxy_resolution_service =
18565 ConfiguredProxyResolutionService::CreateFixedForTest(
18566 test_config.proxy_url, TRAFFIC_ANNOTATION_FOR_TESTS);
18567 } else {
18568 session_deps_.proxy_resolution_service =
18569 ConfiguredProxyResolutionService::CreateDirect();
18570 }
18571
18572 HttpRequestInfo request;
18573 request.method = "GET";
18574 request.url = GURL(test_config.server_url);
18575 request.traffic_annotation =
18576 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
18577
18578 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
18579
18580 SSLSocketDataProvider ssl_socket_data_provider(SYNCHRONOUS, OK);
18581
18582 std::vector<std::vector<MockRead>> mock_reads(1);
18583 std::vector<std::vector<MockWrite>> mock_writes(1);
18584 for (int round = 0; round < test_config.num_auth_rounds; ++round) {
18585 SCOPED_TRACE(round);
18586 const TestRound& read_write_round = test_config.rounds[round];
18587
18588 // Set up expected reads and writes.
18589 mock_reads.back().push_back(read_write_round.read);
18590 mock_writes.back().push_back(read_write_round.write);
18591
18592 // kProxyChallenge uses Proxy-Connection: close which means that the
18593 // socket is closed and a new one will be created for the next request.
18594 if (read_write_round.read.data == kProxyChallenge.data) {
18595 mock_reads.emplace_back();
18596 mock_writes.emplace_back();
18597 }
18598
18599 if (read_write_round.extra_read) {
18600 mock_reads.back().push_back(*read_write_round.extra_read);
18601 }
18602 if (read_write_round.extra_write) {
18603 mock_writes.back().push_back(*read_write_round.extra_write);
18604 }
18605
18606 // Add an SSL sequence if necessary.
18607 if (round >= test_config.first_ssl_round) {
18608 session_deps_.socket_factory->AddSSLSocketDataProvider(
18609 &ssl_socket_data_provider);
18610 }
18611 }
18612
18613 std::vector<std::unique_ptr<StaticSocketDataProvider>> data_providers;
18614 for (size_t i = 0; i < mock_reads.size(); ++i) {
18615 data_providers.push_back(std::make_unique<StaticSocketDataProvider>(
18616 mock_reads[i], mock_writes[i]));
18617 session_deps_.socket_factory->AddSocketDataProvider(
18618 data_providers.back().get());
18619 }
18620
18621 // Transaction must be created after DataProviders, so it's destroyed before
18622 // they are as well.
18623 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
18624
18625 for (int round = 0; round < test_config.num_auth_rounds; ++round) {
18626 SCOPED_TRACE(round);
18627 const TestRound& read_write_round = test_config.rounds[round];
18628 // Start or restart the transaction.
18629 TestCompletionCallback callback;
18630 int rv;
18631 if (round == 0) {
18632 rv = trans.Start(&request, callback.callback(), NetLogWithSource());
18633 } else {
18634 rv = trans.RestartWithAuth(AuthCredentials(kFoo, kBar),
18635 callback.callback());
18636 }
18637 if (rv == ERR_IO_PENDING) {
18638 rv = callback.WaitForResult();
18639 }
18640
18641 // Compare results with expected data.
18642 EXPECT_THAT(rv, IsError(read_write_round.expected_rv));
18643 const HttpResponseInfo* response = trans.GetResponseInfo();
18644 if (read_write_round.expected_rv != OK) {
18645 EXPECT_EQ(round + 1, test_config.num_auth_rounds);
18646 continue;
18647 }
18648 if (round + 1 < test_config.num_auth_rounds) {
18649 EXPECT_TRUE(response->auth_challenge.has_value());
18650 } else {
18651 EXPECT_FALSE(response->auth_challenge.has_value());
18652 EXPECT_FALSE(trans.IsReadyToRestartForAuth());
18653 }
18654 }
18655 }
18656 }
18657
TEST_P(HttpNetworkTransactionTest,MultiRoundAuth)18658 TEST_P(HttpNetworkTransactionTest, MultiRoundAuth) {
18659 // Do multi-round authentication and make sure it works correctly.
18660 auto auth_factory = std::make_unique<HttpAuthHandlerMock::Factory>();
18661 auto* auth_factory_ptr = auth_factory.get();
18662 session_deps_.http_auth_handler_factory = std::move(auth_factory);
18663 session_deps_.proxy_resolution_service =
18664 ConfiguredProxyResolutionService::CreateDirect();
18665 session_deps_.host_resolver->rules()->AddRule("www.example.com", "10.0.0.1");
18666
18667 auto auth_handler = std::make_unique<HttpAuthHandlerMock>();
18668 auto* auth_handler_ptr = auth_handler.get();
18669 auth_handler->set_connection_based(true);
18670 std::string auth_challenge = "Mock realm=server";
18671 GURL url("http://www.example.com");
18672 HttpAuthChallengeTokenizer tokenizer(auth_challenge.begin(),
18673 auth_challenge.end());
18674 SSLInfo empty_ssl_info;
18675 auth_handler->InitFromChallenge(&tokenizer, HttpAuth::AUTH_SERVER,
18676 empty_ssl_info, NetworkAnonymizationKey(),
18677 url::SchemeHostPort(url), NetLogWithSource());
18678 auth_factory_ptr->AddMockHandler(std::move(auth_handler),
18679 HttpAuth::AUTH_SERVER);
18680
18681 int rv = OK;
18682 const HttpResponseInfo* response = nullptr;
18683 HttpRequestInfo request;
18684 request.method = "GET";
18685 request.url = url;
18686 request.traffic_annotation =
18687 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
18688
18689 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
18690
18691 // Use a TCP Socket Pool with only one connection per group. This is used
18692 // to validate that the TCP socket is not released to the pool between
18693 // each round of multi-round authentication.
18694 HttpNetworkSessionPeer session_peer(session.get());
18695 CommonConnectJobParams common_connect_job_params(
18696 session->CreateCommonConnectJobParams());
18697 auto transport_pool = std::make_unique<TransportClientSocketPool>(
18698 50, // Max sockets for pool
18699 1, // Max sockets per group
18700 /*unused_idle_socket_timeout=*/base::Seconds(10), ProxyChain::Direct(),
18701 /*is_for_websockets=*/false, &common_connect_job_params);
18702 auto* transport_pool_ptr = transport_pool.get();
18703 auto mock_pool_manager = std::make_unique<MockClientSocketPoolManager>();
18704 mock_pool_manager->SetSocketPool(ProxyChain::Direct(),
18705 std::move(transport_pool));
18706 session_peer.SetClientSocketPoolManager(std::move(mock_pool_manager));
18707
18708 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
18709 TestCompletionCallback callback;
18710
18711 const MockWrite kGet(
18712 "GET / HTTP/1.1\r\n"
18713 "Host: www.example.com\r\n"
18714 "Connection: keep-alive\r\n\r\n");
18715 const MockWrite kGetAuth(
18716 "GET / HTTP/1.1\r\n"
18717 "Host: www.example.com\r\n"
18718 "Connection: keep-alive\r\n"
18719 "Authorization: auth_token\r\n\r\n");
18720
18721 const MockRead kServerChallenge(
18722 "HTTP/1.1 401 Unauthorized\r\n"
18723 "WWW-Authenticate: Mock realm=server\r\n"
18724 "Content-Type: text/html; charset=iso-8859-1\r\n"
18725 "Content-Length: 14\r\n\r\n"
18726 "Unauthorized\r\n");
18727 const MockRead kSuccess(
18728 "HTTP/1.1 200 OK\r\n"
18729 "Content-Type: text/html; charset=iso-8859-1\r\n"
18730 "Content-Length: 3\r\n\r\n"
18731 "Yes");
18732
18733 MockWrite writes[] = {
18734 // First round
18735 kGet,
18736 // Second round
18737 kGetAuth,
18738 // Third round
18739 kGetAuth,
18740 // Fourth round
18741 kGetAuth,
18742 // Competing request
18743 kGet,
18744 };
18745 MockRead reads[] = {
18746 // First round
18747 kServerChallenge,
18748 // Second round
18749 kServerChallenge,
18750 // Third round
18751 kServerChallenge,
18752 // Fourth round
18753 kSuccess,
18754 // Competing response
18755 kSuccess,
18756 };
18757 StaticSocketDataProvider data_provider(reads, writes);
18758 session_deps_.socket_factory->AddSocketDataProvider(&data_provider);
18759
18760 const ClientSocketPool::GroupId kSocketGroup(
18761 url::SchemeHostPort(url::kHttpScheme, "www.example.com", 80),
18762 PrivacyMode::PRIVACY_MODE_DISABLED, NetworkAnonymizationKey(),
18763 SecureDnsPolicy::kAllow, /*disable_cert_network_fetches=*/false);
18764
18765 // First round of authentication.
18766 auth_handler_ptr->SetGenerateExpectation(false, OK);
18767 rv = trans.Start(&request, callback.callback(), NetLogWithSource());
18768 if (rv == ERR_IO_PENDING) {
18769 rv = callback.WaitForResult();
18770 }
18771 EXPECT_THAT(rv, IsOk());
18772 response = trans.GetResponseInfo();
18773 ASSERT_TRUE(response);
18774 EXPECT_TRUE(response->auth_challenge.has_value());
18775 EXPECT_EQ(0u, transport_pool_ptr->IdleSocketCountInGroup(kSocketGroup));
18776 EXPECT_EQ(HttpAuthHandlerMock::State::WAIT_FOR_GENERATE_AUTH_TOKEN,
18777 auth_handler_ptr->state());
18778
18779 // In between rounds, another request comes in for the same domain.
18780 // It should not be able to grab the TCP socket that trans has already
18781 // claimed.
18782 HttpNetworkTransaction trans_compete(DEFAULT_PRIORITY, session.get());
18783 TestCompletionCallback callback_compete;
18784 rv = trans_compete.Start(&request, callback_compete.callback(),
18785 NetLogWithSource());
18786 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
18787 // callback_compete.WaitForResult at this point would stall forever,
18788 // since the HttpNetworkTransaction does not release the request back to
18789 // the pool until after authentication completes.
18790
18791 // Second round of authentication.
18792 auth_handler_ptr->SetGenerateExpectation(false, OK);
18793 rv = trans.RestartWithAuth(AuthCredentials(kFoo, kBar), callback.callback());
18794 if (rv == ERR_IO_PENDING) {
18795 rv = callback.WaitForResult();
18796 }
18797 EXPECT_THAT(rv, IsOk());
18798 response = trans.GetResponseInfo();
18799 ASSERT_TRUE(response);
18800 EXPECT_FALSE(response->auth_challenge.has_value());
18801 EXPECT_EQ(0u, transport_pool_ptr->IdleSocketCountInGroup(kSocketGroup));
18802 EXPECT_EQ(HttpAuthHandlerMock::State::WAIT_FOR_GENERATE_AUTH_TOKEN,
18803 auth_handler_ptr->state());
18804
18805 // Third round of authentication.
18806 auth_handler_ptr->SetGenerateExpectation(false, OK);
18807 rv = trans.RestartWithAuth(AuthCredentials(), callback.callback());
18808 if (rv == ERR_IO_PENDING) {
18809 rv = callback.WaitForResult();
18810 }
18811 EXPECT_THAT(rv, IsOk());
18812 response = trans.GetResponseInfo();
18813 ASSERT_TRUE(response);
18814 EXPECT_FALSE(response->auth_challenge.has_value());
18815 EXPECT_EQ(0u, transport_pool_ptr->IdleSocketCountInGroup(kSocketGroup));
18816 EXPECT_EQ(HttpAuthHandlerMock::State::WAIT_FOR_GENERATE_AUTH_TOKEN,
18817 auth_handler_ptr->state());
18818
18819 // Fourth round of authentication, which completes successfully.
18820 auth_handler_ptr->SetGenerateExpectation(false, OK);
18821 rv = trans.RestartWithAuth(AuthCredentials(), callback.callback());
18822 if (rv == ERR_IO_PENDING) {
18823 rv = callback.WaitForResult();
18824 }
18825 EXPECT_THAT(rv, IsOk());
18826 response = trans.GetResponseInfo();
18827 ASSERT_TRUE(response);
18828 EXPECT_FALSE(response->auth_challenge.has_value());
18829 EXPECT_EQ(0u, transport_pool_ptr->IdleSocketCountInGroup(kSocketGroup));
18830
18831 // In WAIT_FOR_CHALLENGE, although in reality the auth handler is done. A real
18832 // auth handler should transition to a DONE state in concert with the remote
18833 // server. But that's not something we can test here with a mock handler.
18834 EXPECT_EQ(HttpAuthHandlerMock::State::WAIT_FOR_CHALLENGE,
18835 auth_handler_ptr->state());
18836
18837 // Read the body since the fourth round was successful. This will also
18838 // release the socket back to the pool.
18839 scoped_refptr<IOBufferWithSize> io_buf =
18840 base::MakeRefCounted<IOBufferWithSize>(50);
18841 rv = trans.Read(io_buf.get(), io_buf->size(), callback.callback());
18842 if (rv == ERR_IO_PENDING) {
18843 rv = callback.WaitForResult();
18844 }
18845 EXPECT_EQ(3, rv);
18846 rv = trans.Read(io_buf.get(), io_buf->size(), callback.callback());
18847 EXPECT_EQ(0, rv);
18848 // There are still 0 idle sockets, since the trans_compete transaction
18849 // will be handed it immediately after trans releases it to the group.
18850 EXPECT_EQ(0u, transport_pool_ptr->IdleSocketCountInGroup(kSocketGroup));
18851
18852 // The competing request can now finish. Wait for the headers and then
18853 // read the body.
18854 rv = callback_compete.WaitForResult();
18855 EXPECT_THAT(rv, IsOk());
18856 rv = trans_compete.Read(io_buf.get(), io_buf->size(), callback.callback());
18857 if (rv == ERR_IO_PENDING) {
18858 rv = callback.WaitForResult();
18859 }
18860 EXPECT_EQ(3, rv);
18861 rv = trans_compete.Read(io_buf.get(), io_buf->size(), callback.callback());
18862 EXPECT_EQ(0, rv);
18863
18864 // Finally, the socket is released to the group.
18865 EXPECT_EQ(1u, transport_pool_ptr->IdleSocketCountInGroup(kSocketGroup));
18866 }
18867
18868 // This tests the case that a request is issued via http instead of spdy after
18869 // npn is negotiated.
TEST_P(HttpNetworkTransactionTest,NpnWithHttpOverSSL)18870 TEST_P(HttpNetworkTransactionTest, NpnWithHttpOverSSL) {
18871 HttpRequestInfo request;
18872 request.method = "GET";
18873 request.url = GURL("https://www.example.org/");
18874 request.traffic_annotation =
18875 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
18876
18877 MockWrite data_writes[] = {
18878 MockWrite("GET / HTTP/1.1\r\n"
18879 "Host: www.example.org\r\n"
18880 "Connection: keep-alive\r\n\r\n"),
18881 };
18882
18883 MockRead data_reads[] = {
18884 MockRead("HTTP/1.1 200 OK\r\n"),
18885 MockRead(kAlternativeServiceHttpHeader),
18886 MockRead("\r\n"),
18887 MockRead("hello world"),
18888 MockRead(SYNCHRONOUS, OK),
18889 };
18890
18891 SSLSocketDataProvider ssl(ASYNC, OK);
18892 ssl.next_proto = kProtoHTTP11;
18893
18894 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
18895
18896 StaticSocketDataProvider data(data_reads, data_writes);
18897 session_deps_.socket_factory->AddSocketDataProvider(&data);
18898
18899 TestCompletionCallback callback;
18900
18901 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
18902 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
18903
18904 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
18905
18906 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
18907 EXPECT_THAT(callback.WaitForResult(), IsOk());
18908
18909 const HttpResponseInfo* response = trans.GetResponseInfo();
18910 ASSERT_TRUE(response);
18911 ASSERT_TRUE(response->headers);
18912 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
18913
18914 std::string response_data;
18915 ASSERT_THAT(ReadTransaction(&trans, &response_data), IsOk());
18916 EXPECT_EQ("hello world", response_data);
18917
18918 EXPECT_FALSE(response->was_fetched_via_spdy);
18919 EXPECT_TRUE(response->was_alpn_negotiated);
18920 }
18921
18922 // Simulate the SSL handshake completing with a ALPN negotiation followed by an
18923 // immediate server closing of the socket.
18924 // Regression test for https://crbug.com/46369.
TEST_P(HttpNetworkTransactionTest,SpdyPostALPNServerHangup)18925 TEST_P(HttpNetworkTransactionTest, SpdyPostALPNServerHangup) {
18926 HttpRequestInfo request;
18927 request.method = "GET";
18928 request.url = GURL("https://www.example.org/");
18929 request.traffic_annotation =
18930 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
18931
18932 SSLSocketDataProvider ssl(ASYNC, OK);
18933 ssl.next_proto = kProtoHTTP2;
18934 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
18935
18936 spdy::SpdySerializedFrame req(
18937 spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST));
18938 MockWrite spdy_writes[] = {CreateMockWrite(req, 1)};
18939
18940 MockRead spdy_reads[] = {
18941 MockRead(SYNCHRONOUS, 0, 0) // Not async - return 0 immediately.
18942 };
18943
18944 SequencedSocketData spdy_data(spdy_reads, spdy_writes);
18945 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
18946
18947 TestCompletionCallback callback;
18948
18949 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
18950 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
18951
18952 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
18953 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
18954 EXPECT_THAT(callback.WaitForResult(), IsError(ERR_CONNECTION_CLOSED));
18955 }
18956
18957 // A subclass of HttpAuthHandlerMock that records the request URL when
18958 // it gets it. This is needed since the auth handler may get destroyed
18959 // before we get a chance to query it.
18960 class UrlRecordingHttpAuthHandlerMock : public HttpAuthHandlerMock {
18961 public:
UrlRecordingHttpAuthHandlerMock(GURL * url)18962 explicit UrlRecordingHttpAuthHandlerMock(GURL* url) : url_(url) {}
18963
18964 ~UrlRecordingHttpAuthHandlerMock() override = default;
18965
18966 protected:
GenerateAuthTokenImpl(const AuthCredentials * credentials,const HttpRequestInfo * request,CompletionOnceCallback callback,std::string * auth_token)18967 int GenerateAuthTokenImpl(const AuthCredentials* credentials,
18968 const HttpRequestInfo* request,
18969 CompletionOnceCallback callback,
18970 std::string* auth_token) override {
18971 *url_ = request->url;
18972 return HttpAuthHandlerMock::GenerateAuthTokenImpl(
18973 credentials, request, std::move(callback), auth_token);
18974 }
18975
18976 private:
18977 raw_ptr<GURL> url_ = nullptr;
18978 };
18979
18980 // Test that if we cancel the transaction as the connection is completing, that
18981 // everything tears down correctly.
TEST_P(HttpNetworkTransactionTest,SimpleCancel)18982 TEST_P(HttpNetworkTransactionTest, SimpleCancel) {
18983 // Setup everything about the connection to complete synchronously, so that
18984 // after calling HttpNetworkTransaction::Start, the only thing we're waiting
18985 // for is the callback from the HttpStreamRequest.
18986 // Then cancel the transaction.
18987 // Verify that we don't crash.
18988 MockConnect mock_connect(SYNCHRONOUS, OK);
18989 MockRead data_reads[] = {
18990 MockRead(SYNCHRONOUS, "HTTP/1.0 200 OK\r\n\r\n"),
18991 MockRead(SYNCHRONOUS, "hello world"),
18992 MockRead(SYNCHRONOUS, OK),
18993 };
18994
18995 HttpRequestInfo request;
18996 request.method = "GET";
18997 request.url = GURL("http://www.example.org/");
18998 request.traffic_annotation =
18999 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
19000
19001 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
19002 auto trans =
19003 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
19004
19005 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
19006 data.set_connect_data(mock_connect);
19007 session_deps_.socket_factory->AddSocketDataProvider(&data);
19008
19009 TestCompletionCallback callback;
19010
19011 int rv = trans->Start(&request, callback.callback(),
19012 NetLogWithSource::Make(NetLogSourceType::NONE));
19013 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
19014 trans.reset(); // Cancel the transaction here.
19015
19016 base::RunLoop().RunUntilIdle();
19017 }
19018
19019 // Test that if a transaction is cancelled after receiving the headers, the
19020 // stream is drained properly and added back to the socket pool. The main
19021 // purpose of this test is to make sure that an HttpStreamParser can be read
19022 // from after the HttpNetworkTransaction and the objects it owns have been
19023 // deleted.
19024 // See http://crbug.com/368418
TEST_P(HttpNetworkTransactionTest,CancelAfterHeaders)19025 TEST_P(HttpNetworkTransactionTest, CancelAfterHeaders) {
19026 MockRead data_reads[] = {
19027 MockRead(ASYNC, "HTTP/1.1 200 OK\r\n"),
19028 MockRead(ASYNC, "Content-Length: 2\r\n"),
19029 MockRead(ASYNC, "Connection: Keep-Alive\r\n\r\n"), MockRead(ASYNC, "1"),
19030 // 2 async reads are necessary to trigger a ReadResponseBody call after
19031 // the HttpNetworkTransaction has been deleted.
19032 MockRead(ASYNC, "2"),
19033 MockRead(SYNCHRONOUS, ERR_IO_PENDING), // Should never read this.
19034 };
19035 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
19036 session_deps_.socket_factory->AddSocketDataProvider(&data);
19037
19038 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
19039
19040 {
19041 HttpRequestInfo request;
19042 request.method = "GET";
19043 request.url = GURL("http://www.example.org/");
19044 request.traffic_annotation =
19045 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
19046
19047 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
19048 TestCompletionCallback callback;
19049
19050 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
19051 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
19052 callback.WaitForResult();
19053
19054 const HttpResponseInfo* response = trans.GetResponseInfo();
19055 ASSERT_TRUE(response);
19056 EXPECT_TRUE(response->headers);
19057 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
19058
19059 // The transaction and HttpRequestInfo are deleted.
19060 }
19061
19062 // Let the HttpResponseBodyDrainer drain the socket.
19063 base::RunLoop().RunUntilIdle();
19064
19065 // Socket should now be idle, waiting to be reused.
19066 EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session.get()));
19067 }
19068
19069 // Test a basic GET request through a proxy.
TEST_P(HttpNetworkTransactionTest,ProxyGet)19070 TEST_P(HttpNetworkTransactionTest, ProxyGet) {
19071 session_deps_.proxy_resolution_service =
19072 ConfiguredProxyResolutionService::CreateFixedFromPacResultForTest(
19073 "PROXY myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
19074 session_deps_.net_log = NetLog::Get();
19075 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
19076
19077 HttpRequestInfo request;
19078 request.method = "GET";
19079 request.url = GURL("http://www.example.org/");
19080 request.traffic_annotation =
19081 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
19082
19083 MockWrite data_writes1[] = {
19084 MockWrite("GET http://www.example.org/ HTTP/1.1\r\n"
19085 "Host: www.example.org\r\n"
19086 "Proxy-Connection: keep-alive\r\n\r\n"),
19087 };
19088
19089 MockRead data_reads1[] = {
19090 MockRead("HTTP/1.1 200 OK\r\n"),
19091 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
19092 MockRead("Content-Length: 100\r\n\r\n"),
19093 MockRead(SYNCHRONOUS, OK),
19094 };
19095
19096 StaticSocketDataProvider data1(data_reads1, data_writes1);
19097 session_deps_.socket_factory->AddSocketDataProvider(&data1);
19098
19099 TestCompletionCallback callback1;
19100
19101 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
19102 ConnectedHandler connected_handler;
19103 trans.SetConnectedCallback(connected_handler.Callback());
19104
19105 int rv = trans.Start(&request, callback1.callback(),
19106 NetLogWithSource::Make(NetLogSourceType::NONE));
19107 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
19108
19109 rv = callback1.WaitForResult();
19110 EXPECT_THAT(rv, IsOk());
19111
19112 const HttpResponseInfo* response = trans.GetResponseInfo();
19113 ASSERT_TRUE(response);
19114
19115 EXPECT_TRUE(response->headers->IsKeepAlive());
19116 EXPECT_EQ(200, response->headers->response_code());
19117 EXPECT_EQ(100, response->headers->GetContentLength());
19118 EXPECT_TRUE(response->was_fetched_via_proxy);
19119 EXPECT_FALSE(response->proxy_chain.is_for_ip_protection());
19120 EXPECT_EQ(ProxyChain(ProxyServer::SCHEME_HTTP,
19121 HostPortPair::FromString("myproxy:70")),
19122 response->proxy_chain);
19123 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
19124
19125 TransportInfo expected_transport;
19126 expected_transport.type = TransportType::kProxied;
19127 expected_transport.endpoint = IPEndPoint(IPAddress::IPv4Localhost(), 70);
19128 expected_transport.negotiated_protocol = kProtoUnknown;
19129 EXPECT_THAT(connected_handler.transports(), ElementsAre(expected_transport));
19130
19131 LoadTimingInfo load_timing_info;
19132 EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info));
19133 TestLoadTimingNotReusedWithPac(load_timing_info,
19134 CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY);
19135 }
19136
19137 // Test a basic HTTPS GET request through a proxy.
TEST_P(HttpNetworkTransactionTest,ProxyTunnelGet)19138 TEST_P(HttpNetworkTransactionTest, ProxyTunnelGet) {
19139 session_deps_.proxy_resolution_service =
19140 ConfiguredProxyResolutionService::CreateFixedFromPacResultForTest(
19141 "PROXY myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
19142 RecordingNetLogObserver net_log_observer;
19143 session_deps_.net_log = NetLog::Get();
19144 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
19145
19146 HttpRequestInfo request;
19147 request.method = "GET";
19148 request.url = GURL("https://www.example.org/");
19149 request.traffic_annotation =
19150 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
19151
19152 // Since we have proxy, should try to establish tunnel.
19153 MockWrite data_writes1[] = {
19154 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
19155 "Host: www.example.org:443\r\n"
19156 "Proxy-Connection: keep-alive\r\n\r\n"),
19157
19158 MockWrite("GET / HTTP/1.1\r\n"
19159 "Host: www.example.org\r\n"
19160 "Connection: keep-alive\r\n\r\n"),
19161 };
19162
19163 MockRead data_reads1[] = {
19164 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
19165
19166 MockRead("HTTP/1.1 200 OK\r\n"),
19167 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
19168 MockRead("Content-Length: 100\r\n\r\n"),
19169 MockRead(SYNCHRONOUS, OK),
19170 };
19171
19172 StaticSocketDataProvider data1(data_reads1, data_writes1);
19173 session_deps_.socket_factory->AddSocketDataProvider(&data1);
19174 SSLSocketDataProvider ssl(ASYNC, OK);
19175 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
19176
19177 TestCompletionCallback callback1;
19178
19179 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
19180 ConnectedHandler connected_handler;
19181 trans.SetConnectedCallback(connected_handler.Callback());
19182
19183 int rv = trans.Start(&request, callback1.callback(),
19184 NetLogWithSource::Make(NetLogSourceType::NONE));
19185 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
19186
19187 rv = callback1.WaitForResult();
19188 EXPECT_THAT(rv, IsOk());
19189 auto entries = net_log_observer.GetEntries();
19190 size_t pos = ExpectLogContainsSomewhere(
19191 entries, 0, NetLogEventType::HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
19192 NetLogEventPhase::NONE);
19193 ExpectLogContainsSomewhere(
19194 entries, pos,
19195 NetLogEventType::HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
19196 NetLogEventPhase::NONE);
19197
19198 const HttpResponseInfo* response = trans.GetResponseInfo();
19199 ASSERT_TRUE(response);
19200
19201 EXPECT_TRUE(response->headers->IsKeepAlive());
19202 EXPECT_EQ(200, response->headers->response_code());
19203 EXPECT_EQ(100, response->headers->GetContentLength());
19204 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
19205 EXPECT_TRUE(response->was_fetched_via_proxy);
19206 EXPECT_EQ(ProxyChain(ProxyServer::SCHEME_HTTP,
19207 HostPortPair::FromString("myproxy:70")),
19208 response->proxy_chain);
19209
19210 TransportInfo expected_transport;
19211 expected_transport.type = TransportType::kProxied;
19212 expected_transport.endpoint = IPEndPoint(IPAddress::IPv4Localhost(), 70);
19213 expected_transport.negotiated_protocol = kProtoUnknown;
19214 EXPECT_THAT(connected_handler.transports(), ElementsAre(expected_transport));
19215
19216 LoadTimingInfo load_timing_info;
19217 EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info));
19218 TestLoadTimingNotReusedWithPac(load_timing_info,
19219 CONNECT_TIMING_HAS_SSL_TIMES);
19220 }
19221
19222 // Test a basic HTTPS GET request through a proxy, connecting to an IPv6
19223 // literal host.
TEST_P(HttpNetworkTransactionTest,ProxyTunnelGetIPv6)19224 TEST_P(HttpNetworkTransactionTest, ProxyTunnelGetIPv6) {
19225 session_deps_.proxy_resolution_service =
19226 ConfiguredProxyResolutionService::CreateFixedFromPacResultForTest(
19227 "PROXY myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
19228 RecordingNetLogObserver net_log_observer;
19229 session_deps_.net_log = NetLog::Get();
19230 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
19231
19232 HttpRequestInfo request;
19233 request.method = "GET";
19234 request.url = GURL("https://[::2]:443/");
19235 request.traffic_annotation =
19236 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
19237
19238 // Since we have proxy, should try to establish tunnel.
19239 MockWrite data_writes1[] = {
19240 MockWrite("CONNECT [::2]:443 HTTP/1.1\r\n"
19241 "Host: [::2]:443\r\n"
19242 "Proxy-Connection: keep-alive\r\n\r\n"),
19243
19244 MockWrite("GET / HTTP/1.1\r\n"
19245 "Host: [::2]\r\n"
19246 "Connection: keep-alive\r\n\r\n"),
19247 };
19248
19249 MockRead data_reads1[] = {
19250 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
19251
19252 MockRead("HTTP/1.1 200 OK\r\n"),
19253 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
19254 MockRead("Content-Length: 100\r\n\r\n"),
19255 MockRead(SYNCHRONOUS, OK),
19256 };
19257
19258 StaticSocketDataProvider data1(data_reads1, data_writes1);
19259 session_deps_.socket_factory->AddSocketDataProvider(&data1);
19260 SSLSocketDataProvider ssl(ASYNC, OK);
19261 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
19262
19263 TestCompletionCallback callback1;
19264
19265 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
19266
19267 int rv = trans.Start(&request, callback1.callback(),
19268 NetLogWithSource::Make(NetLogSourceType::NONE));
19269 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
19270
19271 rv = callback1.WaitForResult();
19272 EXPECT_THAT(rv, IsOk());
19273 auto entries = net_log_observer.GetEntries();
19274 size_t pos = ExpectLogContainsSomewhere(
19275 entries, 0, NetLogEventType::HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
19276 NetLogEventPhase::NONE);
19277 ExpectLogContainsSomewhere(
19278 entries, pos,
19279 NetLogEventType::HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
19280 NetLogEventPhase::NONE);
19281
19282 const HttpResponseInfo* response = trans.GetResponseInfo();
19283 ASSERT_TRUE(response);
19284
19285 EXPECT_TRUE(response->headers->IsKeepAlive());
19286 EXPECT_EQ(200, response->headers->response_code());
19287 EXPECT_EQ(100, response->headers->GetContentLength());
19288 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
19289 EXPECT_TRUE(response->was_fetched_via_proxy);
19290 EXPECT_EQ(ProxyChain(ProxyServer::SCHEME_HTTP,
19291 HostPortPair::FromString("myproxy:70")),
19292 response->proxy_chain);
19293
19294 LoadTimingInfo load_timing_info;
19295 EXPECT_TRUE(trans.GetLoadTimingInfo(&load_timing_info));
19296 TestLoadTimingNotReusedWithPac(load_timing_info,
19297 CONNECT_TIMING_HAS_SSL_TIMES);
19298 }
19299
19300 // Test a basic HTTPS GET request through a proxy, but the server hangs up
19301 // while establishing the tunnel.
TEST_P(HttpNetworkTransactionTest,ProxyTunnelGetHangup)19302 TEST_P(HttpNetworkTransactionTest, ProxyTunnelGetHangup) {
19303 session_deps_.proxy_resolution_service =
19304 ConfiguredProxyResolutionService::CreateFixedForTest(
19305 "myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
19306 RecordingNetLogObserver net_log_observer;
19307 session_deps_.net_log = NetLog::Get();
19308 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
19309
19310 HttpRequestInfo request;
19311 request.method = "GET";
19312 request.url = GURL("https://www.example.org/");
19313 request.traffic_annotation =
19314 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
19315
19316 // Since we have proxy, should try to establish tunnel.
19317 MockWrite data_writes1[] = {
19318 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
19319 "Host: www.example.org:443\r\n"
19320 "Proxy-Connection: keep-alive\r\n\r\n"),
19321
19322 MockWrite("GET / HTTP/1.1\r\n"
19323 "Host: www.example.org\r\n"
19324 "Connection: keep-alive\r\n\r\n"),
19325 };
19326
19327 MockRead data_reads1[] = {
19328 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
19329 MockRead(ASYNC, 0, 0), // EOF
19330 };
19331
19332 StaticSocketDataProvider data1(data_reads1, data_writes1);
19333 session_deps_.socket_factory->AddSocketDataProvider(&data1);
19334 SSLSocketDataProvider ssl(ASYNC, OK);
19335 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
19336
19337 TestCompletionCallback callback1;
19338
19339 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
19340
19341 int rv = trans.Start(&request, callback1.callback(),
19342 NetLogWithSource::Make(NetLogSourceType::NONE));
19343 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
19344
19345 rv = callback1.WaitForResult();
19346 EXPECT_THAT(rv, IsError(ERR_EMPTY_RESPONSE));
19347 auto entries = net_log_observer.GetEntries();
19348 size_t pos = ExpectLogContainsSomewhere(
19349 entries, 0, NetLogEventType::HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
19350 NetLogEventPhase::NONE);
19351 ExpectLogContainsSomewhere(
19352 entries, pos,
19353 NetLogEventType::HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
19354 NetLogEventPhase::NONE);
19355 }
19356
19357 // Test for crbug.com/55424.
TEST_P(HttpNetworkTransactionTest,PreconnectWithExistingSpdySession)19358 TEST_P(HttpNetworkTransactionTest, PreconnectWithExistingSpdySession) {
19359 spdy::SpdySerializedFrame req(
19360 spdy_util_.ConstructSpdyGet("https://www.example.org", 1, LOWEST));
19361 MockWrite spdy_writes[] = {CreateMockWrite(req, 0)};
19362
19363 spdy::SpdySerializedFrame resp(
19364 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
19365 spdy::SpdySerializedFrame data(spdy_util_.ConstructSpdyDataFrame(1, true));
19366 MockRead spdy_reads[] = {
19367 CreateMockRead(resp, 1),
19368 CreateMockRead(data, 2),
19369 MockRead(ASYNC, 0, 3),
19370 };
19371
19372 SequencedSocketData spdy_data(spdy_reads, spdy_writes);
19373 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
19374
19375 SSLSocketDataProvider ssl(ASYNC, OK);
19376 ssl.next_proto = kProtoHTTP2;
19377 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
19378
19379 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
19380
19381 // Set up an initial SpdySession in the pool to reuse.
19382 HostPortPair host_port_pair("www.example.org", 443);
19383 SpdySessionKey key(host_port_pair, PRIVACY_MODE_DISABLED,
19384 ProxyChain::Direct(), SessionUsage::kDestination,
19385 SocketTag(), NetworkAnonymizationKey(),
19386 SecureDnsPolicy::kAllow,
19387 /*disable_cert_verification_network_fetches=*/false);
19388 base::WeakPtr<SpdySession> spdy_session =
19389 CreateSpdySession(session.get(), key, NetLogWithSource());
19390
19391 HttpRequestInfo request;
19392 request.method = "GET";
19393 request.url = GURL("https://www.example.org/");
19394 request.traffic_annotation =
19395 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
19396
19397 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
19398
19399 TestCompletionCallback callback;
19400 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
19401 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
19402 EXPECT_THAT(callback.WaitForResult(), IsOk());
19403 }
19404
19405 // Given a net error, cause that error to be returned from the first Write()
19406 // call and verify that the HttpNetworkTransaction fails with that error.
CheckErrorIsPassedBack(int error,IoMode mode)19407 void HttpNetworkTransactionTestBase::CheckErrorIsPassedBack(int error,
19408 IoMode mode) {
19409 HttpRequestInfo request_info;
19410 request_info.url = GURL("https://www.example.com/");
19411 request_info.method = "GET";
19412 request_info.load_flags = LOAD_NORMAL;
19413 request_info.traffic_annotation =
19414 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
19415
19416 SSLSocketDataProvider ssl_data(mode, OK);
19417 MockWrite data_writes[] = {
19418 MockWrite(mode, error),
19419 };
19420 StaticSocketDataProvider data(base::span<MockRead>(), data_writes);
19421 session_deps_.socket_factory->AddSocketDataProvider(&data);
19422 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data);
19423
19424 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
19425 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
19426
19427 TestCompletionCallback callback;
19428 int rv = trans.Start(&request_info, callback.callback(), NetLogWithSource());
19429 if (rv == ERR_IO_PENDING) {
19430 rv = callback.WaitForResult();
19431 }
19432 ASSERT_EQ(error, rv);
19433 }
19434
TEST_P(HttpNetworkTransactionTest,SSLWriteCertError)19435 TEST_P(HttpNetworkTransactionTest, SSLWriteCertError) {
19436 // Just check a grab bag of cert errors.
19437 static const int kErrors[] = {
19438 ERR_CERT_COMMON_NAME_INVALID,
19439 ERR_CERT_AUTHORITY_INVALID,
19440 ERR_CERT_DATE_INVALID,
19441 };
19442 for (int error : kErrors) {
19443 CheckErrorIsPassedBack(error, ASYNC);
19444 CheckErrorIsPassedBack(error, SYNCHRONOUS);
19445 }
19446 }
19447
19448 // Ensure that a client certificate is removed from the SSL client auth
19449 // cache when:
19450 // 1) No proxy is involved.
19451 // 2) TLS False Start is disabled.
19452 // 3) The initial TLS handshake requests a client certificate.
19453 // 4) The client supplies an invalid/unacceptable certificate.
TEST_P(HttpNetworkTransactionTest,ClientAuthCertCache_Direct_NoFalseStart)19454 TEST_P(HttpNetworkTransactionTest, ClientAuthCertCache_Direct_NoFalseStart) {
19455 HttpRequestInfo request_info;
19456 request_info.url = GURL("https://www.example.com/");
19457 request_info.method = "GET";
19458 request_info.load_flags = LOAD_NORMAL;
19459 request_info.traffic_annotation =
19460 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
19461
19462 auto cert_request = base::MakeRefCounted<SSLCertRequestInfo>();
19463 cert_request->host_and_port = HostPortPair("www.example.com", 443);
19464
19465 // [ssl_]data1 contains the data for the first SSL handshake. When a
19466 // CertificateRequest is received for the first time, the handshake will
19467 // be aborted to allow the caller to provide a certificate.
19468 SSLSocketDataProvider ssl_data1(ASYNC, ERR_SSL_CLIENT_AUTH_CERT_NEEDED);
19469 ssl_data1.cert_request_info = cert_request;
19470 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data1);
19471 StaticSocketDataProvider data1;
19472 session_deps_.socket_factory->AddSocketDataProvider(&data1);
19473
19474 // [ssl_]data2 contains the data for the second SSL handshake. When TLS
19475 // False Start is not being used, the result of the SSL handshake will be
19476 // returned as part of the SSLClientSocket::Connect() call. This test
19477 // matches the result of a server sending a handshake_failure alert,
19478 // rather than a Finished message, because it requires a client
19479 // certificate and none was supplied.
19480 SSLSocketDataProvider ssl_data2(ASYNC, ERR_SSL_PROTOCOL_ERROR);
19481 ssl_data2.cert_request_info = cert_request;
19482 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data2);
19483 StaticSocketDataProvider data2;
19484 session_deps_.socket_factory->AddSocketDataProvider(&data2);
19485
19486 // [ssl_]data3 contains the data for the third SSL handshake. When a
19487 // connection to a server fails during an SSL handshake,
19488 // HttpNetworkTransaction will attempt to fallback with legacy cryptography
19489 // enabled on some errors. This is transparent to the caller
19490 // of the HttpNetworkTransaction. Because this test failure is due to
19491 // requiring a client certificate, this fallback handshake should also
19492 // fail.
19493 SSLSocketDataProvider ssl_data3(ASYNC, ERR_SSL_PROTOCOL_ERROR);
19494 ssl_data3.cert_request_info = cert_request;
19495 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data3);
19496 StaticSocketDataProvider data3;
19497 session_deps_.socket_factory->AddSocketDataProvider(&data3);
19498
19499 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
19500 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
19501
19502 // Begin the SSL handshake with the peer. This consumes ssl_data1.
19503 TestCompletionCallback callback;
19504 int rv = trans.Start(&request_info, callback.callback(), NetLogWithSource());
19505 ASSERT_THAT(rv, IsError(ERR_IO_PENDING));
19506
19507 // Complete the SSL handshake, which should abort due to requiring a
19508 // client certificate.
19509 rv = callback.WaitForResult();
19510 ASSERT_THAT(rv, IsError(ERR_SSL_CLIENT_AUTH_CERT_NEEDED));
19511
19512 // Indicate that no certificate should be supplied. From the perspective
19513 // of SSLClientCertCache, NULL is just as meaningful as a real
19514 // certificate, so this is the same as supply a
19515 // legitimate-but-unacceptable certificate.
19516 rv = trans.RestartWithCertificate(nullptr, nullptr, callback.callback());
19517 ASSERT_THAT(rv, IsError(ERR_IO_PENDING));
19518
19519 // Ensure the certificate was added to the client auth cache before
19520 // allowing the connection to continue restarting.
19521 scoped_refptr<X509Certificate> client_cert;
19522 scoped_refptr<SSLPrivateKey> client_private_key;
19523 ASSERT_TRUE(session->ssl_client_context()->GetClientCertificate(
19524 HostPortPair("www.example.com", 443), &client_cert, &client_private_key));
19525 ASSERT_FALSE(client_cert);
19526
19527 // Restart the handshake. This will consume ssl_data2, which fails, and
19528 // then consume ssl_data3 and ssl_data4, both of which should also fail.
19529 // The result code is checked against what ssl_data4 should return.
19530 rv = callback.WaitForResult();
19531 ASSERT_THAT(rv, IsError(ERR_SSL_PROTOCOL_ERROR));
19532
19533 // Ensure that the client certificate is removed from the cache on a
19534 // handshake failure.
19535 ASSERT_FALSE(session->ssl_client_context()->GetClientCertificate(
19536 HostPortPair("www.example.com", 443), &client_cert, &client_private_key));
19537 }
19538
19539 // Ensure that a client certificate is removed from the SSL client auth
19540 // cache when:
19541 // 1) No proxy is involved.
19542 // 2) TLS False Start is enabled.
19543 // 3) The initial TLS handshake requests a client certificate.
19544 // 4) The client supplies an invalid/unacceptable certificate.
TEST_P(HttpNetworkTransactionTest,ClientAuthCertCache_Direct_FalseStart)19545 TEST_P(HttpNetworkTransactionTest, ClientAuthCertCache_Direct_FalseStart) {
19546 HttpRequestInfo request_info;
19547 request_info.url = GURL("https://www.example.com/");
19548 request_info.method = "GET";
19549 request_info.load_flags = LOAD_NORMAL;
19550 request_info.traffic_annotation =
19551 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
19552
19553 auto cert_request = base::MakeRefCounted<SSLCertRequestInfo>();
19554 cert_request->host_and_port = HostPortPair("www.example.com", 443);
19555
19556 // When TLS False Start is used, SSLClientSocket::Connect() calls will
19557 // return successfully after reading up to the peer's Certificate message.
19558 // This is to allow the caller to call SSLClientSocket::Write(), which can
19559 // enqueue application data to be sent in the same packet as the
19560 // ChangeCipherSpec and Finished messages.
19561 // The actual handshake will be finished when SSLClientSocket::Read() is
19562 // called, which expects to process the peer's ChangeCipherSpec and
19563 // Finished messages. If there was an error negotiating with the peer,
19564 // such as due to the peer requiring a client certificate when none was
19565 // supplied, the alert sent by the peer won't be processed until Read() is
19566 // called.
19567
19568 // Like the non-False Start case, when a client certificate is requested by
19569 // the peer, the handshake is aborted during the Connect() call.
19570 // [ssl_]data1 represents the initial SSL handshake with the peer.
19571 SSLSocketDataProvider ssl_data1(ASYNC, ERR_SSL_CLIENT_AUTH_CERT_NEEDED);
19572 ssl_data1.cert_request_info = cert_request;
19573 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data1);
19574 StaticSocketDataProvider data1;
19575 session_deps_.socket_factory->AddSocketDataProvider(&data1);
19576
19577 // When a client certificate is supplied, Connect() will not be aborted
19578 // when the peer requests the certificate. Instead, the handshake will
19579 // artificially succeed, allowing the caller to write the HTTP request to
19580 // the socket. The handshake messages are not processed until Read() is
19581 // called, which then detects that the handshake was aborted, due to the
19582 // peer sending a handshake_failure because it requires a client
19583 // certificate.
19584 SSLSocketDataProvider ssl_data2(ASYNC, OK);
19585 ssl_data2.cert_request_info = cert_request;
19586 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data2);
19587 MockRead data2_reads[] = {
19588 MockRead(ASYNC /* async */, ERR_SSL_PROTOCOL_ERROR),
19589 };
19590 StaticSocketDataProvider data2(data2_reads, base::span<MockWrite>());
19591 session_deps_.socket_factory->AddSocketDataProvider(&data2);
19592
19593 // As described in ClientAuthCertCache_Direct_NoFalseStart, [ssl_]data3 is
19594 // the data for the SSL handshake once the TLSv1.1 connection falls back to
19595 // TLSv1. It has the same behaviour as [ssl_]data2.
19596 SSLSocketDataProvider ssl_data3(ASYNC, OK);
19597 ssl_data3.cert_request_info = cert_request;
19598 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data3);
19599 StaticSocketDataProvider data3(data2_reads, base::span<MockWrite>());
19600 session_deps_.socket_factory->AddSocketDataProvider(&data3);
19601
19602 // [ssl_]data4 is the data for the SSL handshake once the TLSv1 connection
19603 // falls back to SSLv3. It has the same behaviour as [ssl_]data2.
19604 SSLSocketDataProvider ssl_data4(ASYNC, OK);
19605 ssl_data4.cert_request_info = cert_request;
19606 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data4);
19607 StaticSocketDataProvider data4(data2_reads, base::span<MockWrite>());
19608 session_deps_.socket_factory->AddSocketDataProvider(&data4);
19609
19610 // Need one more if TLSv1.2 is enabled.
19611 SSLSocketDataProvider ssl_data5(ASYNC, OK);
19612 ssl_data5.cert_request_info = cert_request;
19613 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data5);
19614 StaticSocketDataProvider data5(data2_reads, base::span<MockWrite>());
19615 session_deps_.socket_factory->AddSocketDataProvider(&data5);
19616
19617 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
19618 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
19619
19620 // Begin the initial SSL handshake.
19621 TestCompletionCallback callback;
19622 int rv = trans.Start(&request_info, callback.callback(), NetLogWithSource());
19623 ASSERT_THAT(rv, IsError(ERR_IO_PENDING));
19624
19625 // Complete the SSL handshake, which should abort due to requiring a
19626 // client certificate.
19627 rv = callback.WaitForResult();
19628 ASSERT_THAT(rv, IsError(ERR_SSL_CLIENT_AUTH_CERT_NEEDED));
19629
19630 // Indicate that no certificate should be supplied. From the perspective
19631 // of SSLClientCertCache, NULL is just as meaningful as a real
19632 // certificate, so this is the same as supply a
19633 // legitimate-but-unacceptable certificate.
19634 rv = trans.RestartWithCertificate(nullptr, nullptr, callback.callback());
19635 ASSERT_THAT(rv, IsError(ERR_IO_PENDING));
19636
19637 // Ensure the certificate was added to the client auth cache before
19638 // allowing the connection to continue restarting.
19639 scoped_refptr<X509Certificate> client_cert;
19640 scoped_refptr<SSLPrivateKey> client_private_key;
19641 ASSERT_TRUE(session->ssl_client_context()->GetClientCertificate(
19642 HostPortPair("www.example.com", 443), &client_cert, &client_private_key));
19643 ASSERT_FALSE(client_cert);
19644
19645 // Restart the handshake. This will consume ssl_data2, which fails, and
19646 // then consume ssl_data3 and ssl_data4, both of which should also fail.
19647 // The result code is checked against what ssl_data4 should return.
19648 rv = callback.WaitForResult();
19649 ASSERT_THAT(rv, IsError(ERR_SSL_PROTOCOL_ERROR));
19650
19651 // Ensure that the client certificate is removed from the cache on a
19652 // handshake failure.
19653 ASSERT_FALSE(session->ssl_client_context()->GetClientCertificate(
19654 HostPortPair("www.example.com", 443), &client_cert, &client_private_key));
19655 }
19656
19657 // Ensure that a client certificate is removed from the SSL client auth
19658 // cache when:
19659 // 1) An HTTPS proxy is involved.
19660 // 3) The HTTPS proxy requests a client certificate.
19661 // 4) The client supplies an invalid/unacceptable certificate for the
19662 // proxy.
TEST_P(HttpNetworkTransactionTest,ClientAuthCertCache_Proxy_Fail)19663 TEST_P(HttpNetworkTransactionTest, ClientAuthCertCache_Proxy_Fail) {
19664 session_deps_.proxy_resolution_service =
19665 ConfiguredProxyResolutionService::CreateFixedForTest(
19666 "https://proxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
19667 session_deps_.net_log = NetLog::Get();
19668
19669 auto cert_request = base::MakeRefCounted<SSLCertRequestInfo>();
19670 cert_request->host_and_port = HostPortPair("proxy", 70);
19671
19672 // Repeat the test for connecting to an HTTPS endpoint, then for connecting to
19673 // an HTTP endpoint.
19674 HttpRequestInfo requests[2];
19675 requests[0].url = GURL("https://www.example.com/");
19676 requests[0].method = "GET";
19677 requests[0].load_flags = LOAD_NORMAL;
19678 requests[0].traffic_annotation =
19679 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
19680
19681 // HTTPS requests are tunneled.
19682 MockWrite https_writes[] = {
19683 MockWrite("CONNECT www.example.com:443 HTTP/1.1\r\n"
19684 "Host: www.example.com:443\r\n"
19685 "Proxy-Connection: keep-alive\r\n\r\n"),
19686 };
19687
19688 requests[1].url = GURL("http://www.example.com/");
19689 requests[1].method = "GET";
19690 requests[1].load_flags = LOAD_NORMAL;
19691 requests[1].traffic_annotation =
19692 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
19693
19694 // HTTP requests are not.
19695 MockWrite http_writes[] = {
19696 MockWrite("GET http://www.example.com/ HTTP/1.1\r\n"
19697 "Host: www.example.com\r\n"
19698 "Proxy-Connection: keep-alive\r\n\r\n"),
19699 };
19700
19701 // When the server rejects the client certificate, it will close the
19702 // connection. In TLS 1.2, this is signaled out of Connect(). In TLS 1.3 (or
19703 // TLS 1.2 with False Start), the error is returned out of the first Read().
19704 for (bool reject_in_connect : {true, false}) {
19705 SCOPED_TRACE(reject_in_connect);
19706 // Client certificate errors are typically signaled with
19707 // ERR_BAD_SSL_CLIENT_AUTH_CERT, but sometimes the server gives an arbitrary
19708 // protocol error.
19709 for (Error reject_error :
19710 {ERR_SSL_PROTOCOL_ERROR, ERR_BAD_SSL_CLIENT_AUTH_CERT}) {
19711 SCOPED_TRACE(reject_error);
19712 // Tunneled and non-tunneled requests are handled differently. Test both.
19713 for (const HttpRequestInfo& request : requests) {
19714 SCOPED_TRACE(request.url);
19715
19716 session_deps_.socket_factory =
19717 std::make_unique<MockClientSocketFactory>();
19718
19719 // See ClientAuthCertCache_Direct_NoFalseStart for the explanation of
19720 // [ssl_]data[1-3].
19721 SSLSocketDataProvider ssl_data1(ASYNC, ERR_SSL_CLIENT_AUTH_CERT_NEEDED);
19722 ssl_data1.cert_request_info = cert_request;
19723 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data1);
19724 StaticSocketDataProvider data1;
19725 session_deps_.socket_factory->AddSocketDataProvider(&data1);
19726
19727 std::optional<SSLSocketDataProvider> ssl_data2;
19728 std::optional<StaticSocketDataProvider> data2;
19729 MockRead error_in_read[] = {MockRead(ASYNC, reject_error)};
19730 if (reject_in_connect) {
19731 ssl_data2.emplace(ASYNC, reject_error);
19732 // There are no reads or writes.
19733 data2.emplace();
19734 } else {
19735 ssl_data2.emplace(ASYNC, OK);
19736 // We will get one Write() in before observing the error in Read().
19737 if (request.url.SchemeIsCryptographic()) {
19738 data2.emplace(error_in_read, https_writes);
19739 } else {
19740 data2.emplace(error_in_read, http_writes);
19741 }
19742 }
19743 ssl_data2->cert_request_info = cert_request.get();
19744 session_deps_.socket_factory->AddSSLSocketDataProvider(
19745 &ssl_data2.value());
19746 session_deps_.socket_factory->AddSocketDataProvider(&data2.value());
19747
19748 // If the handshake returns ERR_SSL_PROTOCOL_ERROR, we attempt to
19749 // connect twice.
19750 std::optional<SSLSocketDataProvider> ssl_data3;
19751 std::optional<StaticSocketDataProvider> data3;
19752 if (reject_in_connect && reject_error == ERR_SSL_PROTOCOL_ERROR) {
19753 ssl_data3.emplace(ASYNC, reject_error);
19754 data3.emplace(); // There are no reads or writes.
19755 ssl_data3->cert_request_info = cert_request.get();
19756 session_deps_.socket_factory->AddSSLSocketDataProvider(
19757 &ssl_data3.value());
19758 session_deps_.socket_factory->AddSocketDataProvider(&data3.value());
19759 }
19760
19761 std::unique_ptr<HttpNetworkSession> session =
19762 CreateSession(&session_deps_);
19763 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
19764
19765 // Begin the SSL handshake with the proxy.
19766 TestCompletionCallback callback;
19767 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
19768 ASSERT_THAT(rv, IsError(ERR_IO_PENDING));
19769
19770 // Complete the SSL handshake, which should abort due to requiring a
19771 // client certificate.
19772 rv = callback.WaitForResult();
19773 ASSERT_THAT(rv, IsError(ERR_SSL_CLIENT_AUTH_CERT_NEEDED));
19774
19775 // Indicate that no certificate should be supplied. From the
19776 // perspective of SSLClientCertCache, NULL is just as meaningful as a
19777 // real certificate, so this is the same as supply a
19778 // legitimate-but-unacceptable certificate.
19779 rv =
19780 trans.RestartWithCertificate(nullptr, nullptr, callback.callback());
19781 ASSERT_THAT(rv, IsError(ERR_IO_PENDING));
19782
19783 // Ensure the certificate was added to the client auth cache before
19784 // allowing the connection to continue restarting.
19785 scoped_refptr<X509Certificate> client_cert;
19786 scoped_refptr<SSLPrivateKey> client_private_key;
19787 ASSERT_TRUE(session->ssl_client_context()->GetClientCertificate(
19788 HostPortPair("proxy", 70), &client_cert, &client_private_key));
19789 ASSERT_FALSE(client_cert);
19790 // Ensure the certificate was NOT cached for the endpoint. This only
19791 // applies to HTTPS requests, but is fine to check for HTTP requests.
19792 ASSERT_FALSE(session->ssl_client_context()->GetClientCertificate(
19793 HostPortPair("www.example.com", 443), &client_cert,
19794 &client_private_key));
19795
19796 // Restart the handshake. This will consume ssl_data2. The result code
19797 // is checked against what ssl_data2 should return.
19798 rv = callback.WaitForResult();
19799 ASSERT_THAT(rv, AnyOf(IsError(ERR_PROXY_CONNECTION_FAILED),
19800 IsError(reject_error)));
19801
19802 // Now that the new handshake has failed, ensure that the client
19803 // certificate was removed from the client auth cache.
19804 ASSERT_FALSE(session->ssl_client_context()->GetClientCertificate(
19805 HostPortPair("proxy", 70), &client_cert, &client_private_key));
19806 ASSERT_FALSE(session->ssl_client_context()->GetClientCertificate(
19807 HostPortPair("www.example.com", 443), &client_cert,
19808 &client_private_key));
19809 }
19810 }
19811 }
19812 }
19813
19814 // Test that HttpNetworkTransaction correctly handles (mocked) certificate
19815 // requests during a TLS renegotiation.
TEST_P(HttpNetworkTransactionTest,CertificateRequestInRenego)19816 TEST_P(HttpNetworkTransactionTest, CertificateRequestInRenego) {
19817 HttpRequestInfo request_info;
19818 request_info.url = GURL("https://www.example.com/");
19819 request_info.method = "GET";
19820 request_info.load_flags = LOAD_NORMAL;
19821 request_info.traffic_annotation =
19822 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
19823
19824 auto cert_request = base::MakeRefCounted<SSLCertRequestInfo>();
19825 cert_request->host_and_port = HostPortPair("www.example.com", 443);
19826
19827 std::unique_ptr<FakeClientCertIdentity> identity =
19828 FakeClientCertIdentity::CreateFromCertAndKeyFiles(
19829 GetTestCertsDirectory(), "client_1.pem", "client_1.pk8");
19830 ASSERT_TRUE(identity);
19831
19832 // The first connection's handshake succeeds, but we get
19833 // ERR_SSL_CLIENT_AUTH_CERT_NEEDED instead of an HTTP response.
19834 SSLSocketDataProvider ssl_data1(ASYNC, OK);
19835 ssl_data1.cert_request_info = cert_request;
19836 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data1);
19837 MockWrite data1_writes[] = {
19838 MockWrite("GET / HTTP/1.1\r\n"
19839 "Host: www.example.com\r\n"
19840 "Connection: keep-alive\r\n\r\n"),
19841 };
19842 MockRead data1_reads[] = {
19843 MockRead(ASYNC, ERR_SSL_CLIENT_AUTH_CERT_NEEDED),
19844 };
19845 StaticSocketDataProvider data1(data1_reads, data1_writes);
19846 session_deps_.socket_factory->AddSocketDataProvider(&data1);
19847
19848 // After supplying with certificate, we restart the request from the top,
19849 // which succeeds this time.
19850 SSLSocketDataProvider ssl_data2(ASYNC, OK);
19851 ssl_data2.expected_send_client_cert = true;
19852 ssl_data2.expected_client_cert = identity->certificate();
19853 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data2);
19854 MockWrite data2_writes[] = {
19855 MockWrite("GET / HTTP/1.1\r\n"
19856 "Host: www.example.com\r\n"
19857 "Connection: keep-alive\r\n\r\n"),
19858 };
19859 MockRead data2_reads[] = {
19860 MockRead("HTTP/1.1 200 OK\r\n"
19861 "Content-Length: 0\r\n\r\n"),
19862 };
19863 StaticSocketDataProvider data2(data2_reads, data2_writes);
19864 session_deps_.socket_factory->AddSocketDataProvider(&data2);
19865
19866 std::unique_ptr<HttpNetworkSession> session = CreateSession(&session_deps_);
19867 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
19868
19869 TestCompletionCallback callback;
19870 int rv = callback.GetResult(
19871 trans.Start(&request_info, callback.callback(), NetLogWithSource()));
19872 ASSERT_THAT(rv, IsError(ERR_SSL_CLIENT_AUTH_CERT_NEEDED));
19873
19874 rv = trans.RestartWithCertificate(identity->certificate(),
19875 identity->ssl_private_key(),
19876 callback.callback());
19877 ASSERT_THAT(rv, IsError(ERR_IO_PENDING));
19878
19879 // Ensure the certificate was added to the client auth cache
19880 // allowing the connection to continue restarting.
19881 scoped_refptr<X509Certificate> client_cert;
19882 scoped_refptr<SSLPrivateKey> client_private_key;
19883 ASSERT_TRUE(session->ssl_client_context()->GetClientCertificate(
19884 HostPortPair("www.example.com", 443), &client_cert, &client_private_key));
19885 EXPECT_TRUE(client_cert->EqualsIncludingChain(identity->certificate()));
19886
19887 // Complete the handshake. The request now succeeds.
19888 rv = callback.WaitForResult();
19889 ASSERT_THAT(rv, IsError(OK));
19890 EXPECT_EQ(200, trans.GetResponseInfo()->headers->response_code());
19891
19892 // The client certificate remains in the cache.
19893 ASSERT_TRUE(session->ssl_client_context()->GetClientCertificate(
19894 HostPortPair("www.example.com", 443), &client_cert, &client_private_key));
19895 EXPECT_TRUE(client_cert->EqualsIncludingChain(identity->certificate()));
19896 }
19897
TEST_P(HttpNetworkTransactionTest,UseIPConnectionPooling)19898 TEST_P(HttpNetworkTransactionTest, UseIPConnectionPooling) {
19899 // Set up a special HttpNetworkSession with a MockCachingHostResolver.
19900 session_deps_.host_resolver = std::make_unique<MockCachingHostResolver>();
19901 session_deps_.host_resolver->rules()->AddRule("www.example.org", "1.2.3.4");
19902 session_deps_.host_resolver->rules()->AddRule("mail.example.com", "1.2.3.4");
19903 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
19904
19905 AddSSLSocketData();
19906
19907 spdy::SpdySerializedFrame host1_req(
19908 spdy_util_.ConstructSpdyGet("https://www.example.org", 1, LOWEST));
19909 spdy_util_.UpdateWithStreamDestruction(1);
19910 spdy::SpdySerializedFrame host2_req(
19911 spdy_util_.ConstructSpdyGet("https://mail.example.com", 3, LOWEST));
19912 MockWrite spdy_writes[] = {
19913 CreateMockWrite(host1_req, 0),
19914 CreateMockWrite(host2_req, 3),
19915 };
19916 spdy::SpdySerializedFrame host1_resp(
19917 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
19918 spdy::SpdySerializedFrame host1_resp_body(
19919 spdy_util_.ConstructSpdyDataFrame(1, true));
19920 spdy::SpdySerializedFrame host2_resp(
19921 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 3));
19922 spdy::SpdySerializedFrame host2_resp_body(
19923 spdy_util_.ConstructSpdyDataFrame(3, true));
19924 MockRead spdy_reads[] = {
19925 CreateMockRead(host1_resp, 1), CreateMockRead(host1_resp_body, 2),
19926 CreateMockRead(host2_resp, 4), CreateMockRead(host2_resp_body, 5),
19927 MockRead(ASYNC, 0, 6),
19928 };
19929
19930 IPEndPoint peer_addr(IPAddress::IPv4Localhost(), 443);
19931 MockConnect connect(ASYNC, OK, peer_addr);
19932 SequencedSocketData spdy_data(connect, spdy_reads, spdy_writes);
19933 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
19934
19935 TestCompletionCallback callback;
19936 HttpRequestInfo request1;
19937 request1.method = "GET";
19938 request1.url = GURL("https://www.example.org/");
19939 request1.load_flags = 0;
19940 request1.traffic_annotation =
19941 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
19942 HttpNetworkTransaction trans1(DEFAULT_PRIORITY, session.get());
19943
19944 int rv = trans1.Start(&request1, callback.callback(), NetLogWithSource());
19945 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
19946 EXPECT_THAT(callback.WaitForResult(), IsOk());
19947
19948 const HttpResponseInfo* response = trans1.GetResponseInfo();
19949 ASSERT_TRUE(response);
19950 ASSERT_TRUE(response->headers);
19951 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
19952
19953 std::string response_data;
19954 ASSERT_THAT(ReadTransaction(&trans1, &response_data), IsOk());
19955 EXPECT_EQ("hello!", response_data);
19956
19957 // Preload mail.example.com into HostCache.
19958 rv = session_deps_.host_resolver->LoadIntoCache(
19959 HostPortPair("mail.example.com", 443), NetworkAnonymizationKey(),
19960 std::nullopt);
19961 EXPECT_THAT(rv, IsOk());
19962
19963 HttpRequestInfo request2;
19964 request2.method = "GET";
19965 request2.url = GURL("https://mail.example.com/");
19966 request2.load_flags = 0;
19967 request2.traffic_annotation =
19968 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
19969 HttpNetworkTransaction trans2(DEFAULT_PRIORITY, session.get());
19970
19971 ConnectedHandler connected_handler2;
19972 trans2.SetConnectedCallback(connected_handler2.Callback());
19973
19974 rv = trans2.Start(&request2, callback.callback(), NetLogWithSource());
19975 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
19976 EXPECT_THAT(callback.WaitForResult(), IsOk());
19977
19978 TransportInfo expected_transport;
19979 expected_transport.type = TransportType::kDirect;
19980 expected_transport.endpoint =
19981 net::IPEndPoint(net::IPAddress(1, 2, 3, 4), 443);
19982 expected_transport.negotiated_protocol = kProtoHTTP2;
19983 EXPECT_THAT(connected_handler2.transports(), ElementsAre(expected_transport));
19984
19985 response = trans2.GetResponseInfo();
19986 ASSERT_TRUE(response);
19987 ASSERT_TRUE(response->headers);
19988 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
19989 EXPECT_TRUE(response->was_fetched_via_spdy);
19990 EXPECT_TRUE(response->was_alpn_negotiated);
19991 ASSERT_THAT(ReadTransaction(&trans2, &response_data), IsOk());
19992 EXPECT_EQ("hello!", response_data);
19993 }
19994
TEST_P(HttpNetworkTransactionTest,UseIPConnectionPoolingAfterResolution)19995 TEST_P(HttpNetworkTransactionTest, UseIPConnectionPoolingAfterResolution) {
19996 // Set up a special HttpNetworkSession with a MockCachingHostResolver.
19997 session_deps_.host_resolver = std::make_unique<MockCachingHostResolver>();
19998 session_deps_.host_resolver->rules()->AddRule("www.example.org", "1.2.3.4");
19999 session_deps_.host_resolver->rules()->AddRule("mail.example.com", "1.2.3.4");
20000 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
20001
20002 AddSSLSocketData();
20003
20004 spdy::SpdySerializedFrame host1_req(
20005 spdy_util_.ConstructSpdyGet("https://www.example.org", 1, LOWEST));
20006 spdy_util_.UpdateWithStreamDestruction(1);
20007 spdy::SpdySerializedFrame host2_req(
20008 spdy_util_.ConstructSpdyGet("https://mail.example.com", 3, LOWEST));
20009 MockWrite spdy_writes[] = {
20010 CreateMockWrite(host1_req, 0),
20011 CreateMockWrite(host2_req, 3),
20012 };
20013 spdy::SpdySerializedFrame host1_resp(
20014 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
20015 spdy::SpdySerializedFrame host1_resp_body(
20016 spdy_util_.ConstructSpdyDataFrame(1, true));
20017 spdy::SpdySerializedFrame host2_resp(
20018 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 3));
20019 spdy::SpdySerializedFrame host2_resp_body(
20020 spdy_util_.ConstructSpdyDataFrame(3, true));
20021 MockRead spdy_reads[] = {
20022 CreateMockRead(host1_resp, 1), CreateMockRead(host1_resp_body, 2),
20023 CreateMockRead(host2_resp, 4), CreateMockRead(host2_resp_body, 5),
20024 MockRead(ASYNC, 0, 6),
20025 };
20026
20027 IPEndPoint peer_addr(IPAddress::IPv4Localhost(), 443);
20028 MockConnect connect(ASYNC, OK, peer_addr);
20029 SequencedSocketData spdy_data(connect, spdy_reads, spdy_writes);
20030 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
20031
20032 TestCompletionCallback callback;
20033 HttpRequestInfo request1;
20034 request1.method = "GET";
20035 request1.url = GURL("https://www.example.org/");
20036 request1.load_flags = 0;
20037 request1.traffic_annotation =
20038 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
20039 HttpNetworkTransaction trans1(DEFAULT_PRIORITY, session.get());
20040
20041 int rv = trans1.Start(&request1, callback.callback(), NetLogWithSource());
20042 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
20043 EXPECT_THAT(callback.WaitForResult(), IsOk());
20044
20045 const HttpResponseInfo* response = trans1.GetResponseInfo();
20046 ASSERT_TRUE(response);
20047 ASSERT_TRUE(response->headers);
20048 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
20049
20050 std::string response_data;
20051 ASSERT_THAT(ReadTransaction(&trans1, &response_data), IsOk());
20052 EXPECT_EQ("hello!", response_data);
20053
20054 HttpRequestInfo request2;
20055 request2.method = "GET";
20056 request2.url = GURL("https://mail.example.com/");
20057 request2.load_flags = 0;
20058 request2.traffic_annotation =
20059 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
20060 HttpNetworkTransaction trans2(DEFAULT_PRIORITY, session.get());
20061
20062 rv = trans2.Start(&request2, callback.callback(), NetLogWithSource());
20063 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
20064 EXPECT_THAT(callback.WaitForResult(), IsOk());
20065
20066 response = trans2.GetResponseInfo();
20067 ASSERT_TRUE(response);
20068 ASSERT_TRUE(response->headers);
20069 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
20070 EXPECT_TRUE(response->was_fetched_via_spdy);
20071 EXPECT_TRUE(response->was_alpn_negotiated);
20072 ASSERT_THAT(ReadTransaction(&trans2, &response_data), IsOk());
20073 EXPECT_EQ("hello!", response_data);
20074 }
20075
20076 // Tests that a SPDY session to an HTTPS proxy for the purposes of proxying
20077 // won't alias with a session directly to a host even if direct connections to
20078 // the proxy server host and to the other host would alias. The request through
20079 // the proxy is made using SPDY.
TEST_P(HttpNetworkTransactionTest,NoIPConnectionPoolingForProxyAndHostSpdy)20080 TEST_P(HttpNetworkTransactionTest, NoIPConnectionPoolingForProxyAndHostSpdy) {
20081 // Set up a special HttpNetworkSession with a MockCachingHostResolver.
20082 session_deps_.host_resolver = std::make_unique<MockCachingHostResolver>();
20083 session_deps_.host_resolver->rules()->AddRule("www.example.org", "1.2.3.4");
20084 session_deps_.host_resolver->rules()->AddRule("mail.example.com", "1.2.3.4");
20085
20086 const ProxyServer kProxyServer1{ProxyServer::SCHEME_HTTPS,
20087 HostPortPair("www.example.org", 443)};
20088 const ProxyChain kProxyServer1Chain{{
20089 kProxyServer1,
20090 }};
20091
20092 session_deps_.proxy_delegate = std::make_unique<TestProxyDelegate>();
20093 auto* proxy_delegate =
20094 static_cast<TestProxyDelegate*>(session_deps_.proxy_delegate.get());
20095 proxy_delegate->set_proxy_chain(kProxyServer1Chain);
20096
20097 session_deps_.proxy_resolution_service =
20098 ConfiguredProxyResolutionService::CreateFixedForTest(
20099 "https://not-used:70", TRAFFIC_ANNOTATION_FOR_TESTS);
20100 session_deps_.proxy_resolution_service->SetProxyDelegate(proxy_delegate);
20101 session_deps_.net_log = NetLog::Get();
20102 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
20103
20104 // CONNECT to request1.test:443 via SPDY.
20105 spdy::SpdySerializedFrame connect1(spdy_util_.ConstructSpdyConnect(
20106 nullptr, 0, 1, HttpProxyConnectJob::kH2QuicTunnelPriority,
20107 HostPortPair("request1.test", 443)));
20108 spdy::SpdySerializedFrame conn_resp1(
20109 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
20110
20111 // Fetch https://www.example.org/ via SPDY.
20112 SpdyTestUtil req1_spdy_util(/*use_priority_header=*/true);
20113 spdy::SpdySerializedFrame get1(
20114 req1_spdy_util.ConstructSpdyGet("https://request1.test/", 1, LOWEST));
20115 spdy::SpdySerializedFrame wrapped_get1(
20116 spdy_util_.ConstructWrappedSpdyFrame(get1, 1));
20117 spdy::SpdySerializedFrame get_resp1(
20118 req1_spdy_util.ConstructSpdyGetReply(nullptr, 0, 1));
20119 spdy::SpdySerializedFrame wrapped_get_resp1(
20120 spdy_util_.ConstructWrappedSpdyFrame(get_resp1, 1));
20121
20122 spdy::SpdySerializedFrame body1(
20123 req1_spdy_util.ConstructSpdyDataFrame(1, true));
20124 spdy::SpdySerializedFrame wrapped_body1(
20125 spdy_util_.ConstructWrappedSpdyFrame(body1, 1));
20126
20127 MockWrite spdy_writes[] = {
20128 CreateMockWrite(connect1, 0),
20129 CreateMockWrite(wrapped_get1, 2),
20130 };
20131
20132 MockRead spdy_reads[] = {
20133 CreateMockRead(conn_resp1, 1),
20134 // TODO(https://crbug.com/497228): We have to manually delay this read so
20135 // that the higher-level SPDY stream doesn't get notified of an available
20136 // read before the write it initiated (the second CONNECT) finishes,
20137 // triggering a DCHECK.
20138 MockRead(ASYNC, ERR_IO_PENDING, 3), CreateMockRead(wrapped_get_resp1, 4),
20139 CreateMockRead(wrapped_body1, 5),
20140 // Pause reads so that the socket will remain open (so we can see whether
20141 // it gets re-used below).
20142 MockRead(ASYNC, ERR_IO_PENDING, 6), MockRead(ASYNC, 0, 7)};
20143
20144 IPEndPoint peer_addr(IPAddress::IPv4Localhost(), 443);
20145 MockConnect connect(ASYNC, OK, peer_addr);
20146 SequencedSocketData spdy_data(connect, spdy_reads, spdy_writes);
20147 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
20148
20149 AddSSLSocketData();
20150 AddSSLSocketData();
20151
20152 HttpRequestInfo request1;
20153 request1.method = "GET";
20154 request1.url = GURL("https://request1.test/");
20155 request1.traffic_annotation =
20156 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
20157
20158 TestCompletionCallback callback1;
20159
20160 HttpNetworkTransaction trans1(DEFAULT_PRIORITY, session.get());
20161
20162 int rv = trans1.Start(&request1, callback1.callback(),
20163 NetLogWithSource::Make(NetLogSourceType::NONE));
20164 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
20165
20166 spdy_data.RunUntilPaused();
20167 base::RunLoop().RunUntilIdle();
20168 spdy_data.Resume();
20169
20170 rv = callback1.WaitForResult();
20171 ASSERT_THAT(rv, IsOk());
20172
20173 const HttpResponseInfo* response = trans1.GetResponseInfo();
20174 ASSERT_TRUE(response);
20175 ASSERT_TRUE(response->headers);
20176 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
20177
20178 std::string response_data;
20179 ASSERT_THAT(ReadTransaction(&trans1, &response_data), IsOk());
20180 EXPECT_EQ(kUploadData, response_data);
20181
20182 proxy_delegate->set_proxy_chain(ProxyChain::Direct());
20183
20184 SpdyTestUtil req2_spdy_util(/*use_priority_header=*/true);
20185 spdy::SpdySerializedFrame req2(
20186 req2_spdy_util.ConstructSpdyGet("https://mail.example.com/", 1, LOWEST));
20187
20188 spdy::SpdySerializedFrame resp2(
20189 req2_spdy_util.ConstructSpdyGetReply(nullptr, 0, 1));
20190 spdy::SpdySerializedFrame data2(
20191 req2_spdy_util.ConstructSpdyDataFrame(1, true));
20192
20193 MockWrite spdy_writes2[] = {
20194 CreateMockWrite(req2, 0),
20195 };
20196 MockRead spdy_reads2[] = {
20197 CreateMockRead(resp2, 1),
20198 CreateMockRead(data2, 2),
20199 MockRead(ASYNC, 0, 3),
20200 };
20201 SequencedSocketData spdy_data2(connect, spdy_reads2, spdy_writes2);
20202 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data2);
20203
20204 AddSSLSocketData();
20205
20206 HttpRequestInfo request2;
20207 request2.method = "GET";
20208 request2.url = GURL("https://mail.example.com/");
20209 request2.traffic_annotation =
20210 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
20211
20212 TestCompletionCallback callback2;
20213
20214 HttpNetworkTransaction trans2(DEFAULT_PRIORITY, session.get());
20215
20216 rv = trans2.Start(&request2, callback2.callback(),
20217 NetLogWithSource::Make(NetLogSourceType::NONE));
20218 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
20219
20220 rv = callback2.WaitForResult();
20221 ASSERT_THAT(rv, IsOk());
20222
20223 response = trans2.GetResponseInfo();
20224 ASSERT_TRUE(response);
20225 ASSERT_TRUE(response->headers);
20226 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
20227 }
20228
20229 // Tests that a SPDY session to an HTTPS proxy for the purposes of proxying
20230 // won't alias with a session directly to a host even if direct connections to
20231 // the proxy server host and to the other host would alias. The request through
20232 // the proxy is made using HTTP.
TEST_P(HttpNetworkTransactionTest,NoIPConnectionPoolingForProxyAndHostHttp)20233 TEST_P(HttpNetworkTransactionTest, NoIPConnectionPoolingForProxyAndHostHttp) {
20234 // Set up a special HttpNetworkSession with a MockCachingHostResolver.
20235 session_deps_.host_resolver = std::make_unique<MockCachingHostResolver>();
20236 session_deps_.host_resolver->rules()->AddRule("www.example.org", "1.2.3.4");
20237 session_deps_.host_resolver->rules()->AddRule("mail.example.com", "1.2.3.4");
20238
20239 const ProxyServer kProxyServer1{ProxyServer::SCHEME_HTTPS,
20240 HostPortPair("www.example.org", 443)};
20241 const ProxyChain kProxyServer1Chain{{
20242 kProxyServer1,
20243 }};
20244
20245 session_deps_.proxy_delegate = std::make_unique<TestProxyDelegate>();
20246 auto* proxy_delegate =
20247 static_cast<TestProxyDelegate*>(session_deps_.proxy_delegate.get());
20248 proxy_delegate->set_proxy_chain(kProxyServer1Chain);
20249
20250 session_deps_.proxy_resolution_service =
20251 ConfiguredProxyResolutionService::CreateFixedForTest(
20252 "https://not-used:70", TRAFFIC_ANNOTATION_FOR_TESTS);
20253 session_deps_.proxy_resolution_service->SetProxyDelegate(proxy_delegate);
20254
20255 session_deps_.net_log = NetLog::Get();
20256 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
20257
20258 spdy::SpdySerializedFrame req(
20259 spdy_util_.ConstructSpdyGet("http://request1.test/", 1, LOWEST));
20260 spdy::SpdySerializedFrame resp(
20261 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
20262 spdy::SpdySerializedFrame data(spdy_util_.ConstructSpdyDataFrame(1, true));
20263
20264 MockWrite spdy_writes[] = {CreateMockWrite(req, 0)};
20265
20266 MockRead spdy_reads[] = {CreateMockRead(resp, 1), CreateMockRead(data, 2),
20267 // Pause reads so that the socket will remain open
20268 // (so we can see whether it gets re-used below).
20269 MockRead(ASYNC, ERR_IO_PENDING, 3),
20270 MockRead(ASYNC, 0, 4)};
20271
20272 IPEndPoint peer_addr(IPAddress::IPv4Localhost(), 443);
20273 MockConnect connect(ASYNC, OK, peer_addr);
20274 SequencedSocketData spdy_data(connect, spdy_reads, spdy_writes);
20275 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
20276
20277 AddSSLSocketData();
20278
20279 HttpRequestInfo request1;
20280 request1.method = "GET";
20281 request1.url = GURL("http://request1.test/");
20282 request1.traffic_annotation =
20283 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
20284
20285 TestCompletionCallback callback1;
20286
20287 HttpNetworkTransaction trans1(DEFAULT_PRIORITY, session.get());
20288
20289 int rv = trans1.Start(&request1, callback1.callback(),
20290 NetLogWithSource::Make(NetLogSourceType::NONE));
20291 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
20292
20293 rv = callback1.WaitForResult();
20294 ASSERT_THAT(rv, IsOk());
20295
20296 const HttpResponseInfo* response = trans1.GetResponseInfo();
20297 ASSERT_TRUE(response);
20298 ASSERT_TRUE(response->headers);
20299 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
20300
20301 std::string response_data;
20302 ASSERT_THAT(ReadTransaction(&trans1, &response_data), IsOk());
20303 EXPECT_EQ(kUploadData, response_data);
20304
20305 proxy_delegate->set_proxy_chain(ProxyChain::Direct());
20306
20307 SpdyTestUtil req2_spdy_util(/*use_priority_header=*/true);
20308 spdy::SpdySerializedFrame req2(
20309 req2_spdy_util.ConstructSpdyGet("https://mail.example.com/", 1, LOWEST));
20310
20311 spdy::SpdySerializedFrame resp2(
20312 req2_spdy_util.ConstructSpdyGetReply(nullptr, 0, 1));
20313 spdy::SpdySerializedFrame data2(
20314 req2_spdy_util.ConstructSpdyDataFrame(1, true));
20315
20316 MockWrite spdy_writes2[] = {
20317 CreateMockWrite(req2, 0),
20318 };
20319 MockRead spdy_reads2[] = {
20320 CreateMockRead(resp2, 1),
20321 CreateMockRead(data2, 2),
20322 MockRead(ASYNC, 0, 3),
20323 };
20324 SequencedSocketData spdy_data2(connect, spdy_reads2, spdy_writes2);
20325 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data2);
20326
20327 AddSSLSocketData();
20328
20329 HttpRequestInfo request2;
20330 request2.method = "GET";
20331 request2.url = GURL("https://mail.example.com/");
20332 request2.traffic_annotation =
20333 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
20334
20335 TestCompletionCallback callback2;
20336
20337 HttpNetworkTransaction trans2(DEFAULT_PRIORITY, session.get());
20338
20339 rv = trans2.Start(&request2, callback2.callback(),
20340 NetLogWithSource::Make(NetLogSourceType::NONE));
20341 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
20342
20343 rv = callback2.WaitForResult();
20344 ASSERT_THAT(rv, IsOk());
20345
20346 response = trans2.GetResponseInfo();
20347 ASSERT_TRUE(response);
20348 ASSERT_TRUE(response->headers);
20349 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
20350 }
20351
20352 // Tests that a SPDY session to an HTTPS proxy for the purposes of proxying
20353 // won't alias with another proxy session even if direct connections to the
20354 // proxy servers hosts themselves would alias. The requests through the proxy
20355 // are made using SPDY.
TEST_P(HttpNetworkTransactionTest,NoIPConnectionPoolingForTwoProxiesSpdy)20356 TEST_P(HttpNetworkTransactionTest, NoIPConnectionPoolingForTwoProxiesSpdy) {
20357 // Set up a special HttpNetworkSession with a MockCachingHostResolver.
20358 session_deps_.host_resolver = std::make_unique<MockCachingHostResolver>();
20359 session_deps_.host_resolver->rules()->AddRule("www.example.org", "1.2.3.4");
20360 session_deps_.host_resolver->rules()->AddRule("mail.example.com", "1.2.3.4");
20361
20362 const ProxyServer kProxyServer1{ProxyServer::SCHEME_HTTPS,
20363 HostPortPair("www.example.org", 443)};
20364 const ProxyChain kProxyServer1Chain{{
20365 kProxyServer1,
20366 }};
20367
20368 const ProxyServer kProxyServer2{ProxyServer::SCHEME_HTTPS,
20369 HostPortPair("mail.example.com", 443)};
20370 const ProxyChain kProxyServer2Chain{{
20371 kProxyServer2,
20372 }};
20373
20374 session_deps_.proxy_delegate = std::make_unique<TestProxyDelegate>();
20375 auto* proxy_delegate =
20376 static_cast<TestProxyDelegate*>(session_deps_.proxy_delegate.get());
20377 proxy_delegate->set_proxy_chain(kProxyServer1Chain);
20378
20379 session_deps_.proxy_resolution_service =
20380 ConfiguredProxyResolutionService::CreateFixedForTest(
20381 "https://not-used:70", TRAFFIC_ANNOTATION_FOR_TESTS);
20382 session_deps_.proxy_resolution_service->SetProxyDelegate(proxy_delegate);
20383
20384 session_deps_.net_log = NetLog::Get();
20385 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
20386
20387 // CONNECT to request1.test:443 via SPDY.
20388 spdy::SpdySerializedFrame connect1(spdy_util_.ConstructSpdyConnect(
20389 nullptr, 0, 1, HttpProxyConnectJob::kH2QuicTunnelPriority,
20390 HostPortPair("request1.test", 443)));
20391 spdy::SpdySerializedFrame conn_resp1(
20392 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
20393
20394 // Fetch https://www.example.org/ via SPDY.
20395 SpdyTestUtil req1_spdy_util(/*use_priority_header=*/true);
20396 spdy::SpdySerializedFrame get1(
20397 req1_spdy_util.ConstructSpdyGet("https://request1.test/", 1, LOWEST));
20398 spdy::SpdySerializedFrame wrapped_get1(
20399 spdy_util_.ConstructWrappedSpdyFrame(get1, 1));
20400 spdy::SpdySerializedFrame get_resp1(
20401 req1_spdy_util.ConstructSpdyGetReply(nullptr, 0, 1));
20402 spdy::SpdySerializedFrame wrapped_get_resp1(
20403 spdy_util_.ConstructWrappedSpdyFrame(get_resp1, 1));
20404
20405 spdy::SpdySerializedFrame body1(
20406 req1_spdy_util.ConstructSpdyDataFrame(1, true));
20407 spdy::SpdySerializedFrame wrapped_body1(
20408 spdy_util_.ConstructWrappedSpdyFrame(body1, 1));
20409
20410 MockWrite spdy_writes[] = {
20411 CreateMockWrite(connect1, 0),
20412 CreateMockWrite(wrapped_get1, 2),
20413 };
20414
20415 MockRead spdy_reads[] = {
20416 CreateMockRead(conn_resp1, 1),
20417 // TODO(https://crbug.com/497228): We have to manually delay this read so
20418 // that the higher-level SPDY stream doesn't get notified of an available
20419 // read before the write it initiated (the second CONNECT) finishes,
20420 // triggering a DCHECK.
20421 MockRead(ASYNC, ERR_IO_PENDING, 3), CreateMockRead(wrapped_get_resp1, 4),
20422 CreateMockRead(wrapped_body1, 5),
20423 // Pause reads so that the socket will remain open (so we can see whether
20424 // it gets re-used below).
20425 MockRead(ASYNC, ERR_IO_PENDING, 6), MockRead(ASYNC, 0, 7)};
20426
20427 IPEndPoint peer_addr(IPAddress::IPv4Localhost(), 443);
20428 MockConnect connect(ASYNC, OK, peer_addr);
20429 SequencedSocketData spdy_data(connect, spdy_reads, spdy_writes);
20430 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
20431
20432 AddSSLSocketData();
20433 AddSSLSocketData();
20434
20435 HttpRequestInfo request1;
20436 request1.method = "GET";
20437 request1.url = GURL("https://request1.test/");
20438 request1.traffic_annotation =
20439 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
20440
20441 TestCompletionCallback callback1;
20442
20443 HttpNetworkTransaction trans1(DEFAULT_PRIORITY, session.get());
20444
20445 int rv = trans1.Start(&request1, callback1.callback(),
20446 NetLogWithSource::Make(NetLogSourceType::NONE));
20447 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
20448
20449 spdy_data.RunUntilPaused();
20450 base::RunLoop().RunUntilIdle();
20451 spdy_data.Resume();
20452
20453 rv = callback1.WaitForResult();
20454 ASSERT_THAT(rv, IsOk());
20455
20456 const HttpResponseInfo* response = trans1.GetResponseInfo();
20457 ASSERT_TRUE(response);
20458 ASSERT_TRUE(response->headers);
20459 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
20460
20461 std::string response_data;
20462 ASSERT_THAT(ReadTransaction(&trans1, &response_data), IsOk());
20463 EXPECT_EQ(kUploadData, response_data);
20464
20465 proxy_delegate->set_proxy_chain(kProxyServer2Chain);
20466
20467 // CONNECT to request2.test:443 via SPDY.
20468 SpdyTestUtil req2_spdy_util(/*use_priority_header=*/true);
20469 spdy::SpdySerializedFrame connect2(req2_spdy_util.ConstructSpdyConnect(
20470 nullptr, 0, 1, HttpProxyConnectJob::kH2QuicTunnelPriority,
20471 HostPortPair("request2.test", 443)));
20472 spdy::SpdySerializedFrame conn_resp2(
20473 req2_spdy_util.ConstructSpdyGetReply(nullptr, 0, 1));
20474
20475 // Fetch https://www.example.org/ via SPDY.
20476 SpdyTestUtil wrapped_req2_spdy_util(/*use_priority_header=*/true);
20477 spdy::SpdySerializedFrame get2(wrapped_req2_spdy_util.ConstructSpdyGet(
20478 "https://request2.test/", 1, LOWEST));
20479 spdy::SpdySerializedFrame wrapped_get2(
20480 req2_spdy_util.ConstructWrappedSpdyFrame(get2, 1));
20481 spdy::SpdySerializedFrame get_resp2(
20482 wrapped_req2_spdy_util.ConstructSpdyGetReply(nullptr, 0, 1));
20483 spdy::SpdySerializedFrame wrapped_get_resp2(
20484 req2_spdy_util.ConstructWrappedSpdyFrame(get_resp2, 1));
20485
20486 spdy::SpdySerializedFrame body2(
20487 wrapped_req2_spdy_util.ConstructSpdyDataFrame(1, true));
20488 spdy::SpdySerializedFrame wrapped_body2(
20489 req2_spdy_util.ConstructWrappedSpdyFrame(body2, 1));
20490
20491 MockWrite spdy_writes2[] = {
20492 CreateMockWrite(connect2, 0),
20493 CreateMockWrite(wrapped_get2, 2),
20494 };
20495
20496 MockRead spdy_reads2[] = {
20497 CreateMockRead(conn_resp2, 1),
20498 // TODO(https://crbug.com/497228): We have to manually delay this read so
20499 // that the higher-level SPDY stream doesn't get notified of an available
20500 // read before the write it initiated (the second CONNECT) finishes,
20501 // triggering a DCHECK.
20502 MockRead(ASYNC, ERR_IO_PENDING, 3),
20503 CreateMockRead(wrapped_get_resp2, 4),
20504 CreateMockRead(wrapped_body2, 5),
20505 MockRead(ASYNC, 0, 6),
20506 };
20507
20508 SequencedSocketData spdy_data2(connect, spdy_reads2, spdy_writes2);
20509 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data2);
20510
20511 AddSSLSocketData();
20512 AddSSLSocketData();
20513
20514 HttpRequestInfo request2;
20515 request2.method = "GET";
20516 request2.url = GURL("https://request2.test/");
20517 request2.traffic_annotation =
20518 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
20519
20520 TestCompletionCallback callback2;
20521
20522 HttpNetworkTransaction trans2(DEFAULT_PRIORITY, session.get());
20523
20524 rv = trans2.Start(&request2, callback2.callback(),
20525 NetLogWithSource::Make(NetLogSourceType::NONE));
20526 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
20527
20528 spdy_data2.RunUntilPaused();
20529 base::RunLoop().RunUntilIdle();
20530 spdy_data2.Resume();
20531
20532 rv = callback2.WaitForResult();
20533 ASSERT_THAT(rv, IsOk());
20534
20535 response = trans2.GetResponseInfo();
20536 ASSERT_TRUE(response);
20537 ASSERT_TRUE(response->headers);
20538 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
20539 }
20540
20541 // Tests that a SPDY session to an HTTPS proxy for the purposes of proxying
20542 // won't alias with another proxy session even if direct connections to the
20543 // proxy servers hosts themselves would alias. The requests through the proxy
20544 // are made using HTTP.
TEST_P(HttpNetworkTransactionTest,NoIPConnectionPoolingForTwoProxiesHttp)20545 TEST_P(HttpNetworkTransactionTest, NoIPConnectionPoolingForTwoProxiesHttp) {
20546 // Set up a special HttpNetworkSession with a MockCachingHostResolver.
20547 session_deps_.host_resolver = std::make_unique<MockCachingHostResolver>();
20548 session_deps_.host_resolver->rules()->AddRule("www.example.org", "1.2.3.4");
20549 session_deps_.host_resolver->rules()->AddRule("mail.example.com", "1.2.3.4");
20550
20551 const ProxyServer kProxyServer1{ProxyServer::SCHEME_HTTPS,
20552 HostPortPair("www.example.org", 443)};
20553 const ProxyChain kProxyServer1Chain{{
20554 kProxyServer1,
20555 }};
20556
20557 const ProxyServer kProxyServer2{ProxyServer::SCHEME_HTTPS,
20558 HostPortPair("mail.example.com", 443)};
20559 const ProxyChain kProxyServer2Chain{{
20560 kProxyServer2,
20561 }};
20562
20563 session_deps_.proxy_delegate = std::make_unique<TestProxyDelegate>();
20564 auto* proxy_delegate =
20565 static_cast<TestProxyDelegate*>(session_deps_.proxy_delegate.get());
20566 proxy_delegate->set_proxy_chain(kProxyServer1Chain);
20567
20568 session_deps_.proxy_resolution_service =
20569 ConfiguredProxyResolutionService::CreateFixedForTest(
20570 "https://not-used:70", TRAFFIC_ANNOTATION_FOR_TESTS);
20571 session_deps_.proxy_resolution_service->SetProxyDelegate(proxy_delegate);
20572 session_deps_.net_log = NetLog::Get();
20573 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
20574
20575 spdy::SpdySerializedFrame req(
20576 spdy_util_.ConstructSpdyGet("http://request1.test/", 1, LOWEST));
20577 spdy::SpdySerializedFrame resp(
20578 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
20579 spdy::SpdySerializedFrame data(spdy_util_.ConstructSpdyDataFrame(1, true));
20580
20581 MockWrite spdy_writes[] = {CreateMockWrite(req, 0)};
20582
20583 MockRead spdy_reads[] = {CreateMockRead(resp, 1), CreateMockRead(data, 2),
20584 // Pause reads so that the socket will remain open
20585 // (so we can see whether it gets re-used below).
20586 MockRead(ASYNC, ERR_IO_PENDING, 3),
20587 MockRead(ASYNC, 0, 4)};
20588
20589 IPEndPoint peer_addr(IPAddress::IPv4Localhost(), 443);
20590 MockConnect connect(ASYNC, OK, peer_addr);
20591 SequencedSocketData spdy_data(connect, spdy_reads, spdy_writes);
20592 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
20593
20594 AddSSLSocketData();
20595
20596 HttpRequestInfo request1;
20597 request1.method = "GET";
20598 request1.url = GURL("http://request1.test/");
20599 request1.traffic_annotation =
20600 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
20601
20602 TestCompletionCallback callback1;
20603
20604 HttpNetworkTransaction trans1(DEFAULT_PRIORITY, session.get());
20605
20606 int rv = trans1.Start(&request1, callback1.callback(),
20607 NetLogWithSource::Make(NetLogSourceType::NONE));
20608 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
20609
20610 rv = callback1.WaitForResult();
20611 ASSERT_THAT(rv, IsOk());
20612
20613 const HttpResponseInfo* response = trans1.GetResponseInfo();
20614 ASSERT_TRUE(response);
20615 ASSERT_TRUE(response->headers);
20616 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
20617
20618 std::string response_data;
20619 ASSERT_THAT(ReadTransaction(&trans1, &response_data), IsOk());
20620 EXPECT_EQ(kUploadData, response_data);
20621
20622 proxy_delegate->set_proxy_chain(kProxyServer2Chain);
20623
20624 SpdyTestUtil req2_spdy_util(/*use_priority_header=*/true);
20625 spdy::SpdySerializedFrame req2(
20626 req2_spdy_util.ConstructSpdyGet("http://request2.test/", 1, LOWEST));
20627
20628 spdy::SpdySerializedFrame resp2(
20629 req2_spdy_util.ConstructSpdyGetReply(nullptr, 0, 1));
20630 spdy::SpdySerializedFrame data2(
20631 req2_spdy_util.ConstructSpdyDataFrame(1, true));
20632
20633 MockWrite spdy_writes2[] = {CreateMockWrite(req2, 0)};
20634
20635 MockRead spdy_reads2[] = {
20636 CreateMockRead(resp2, 1),
20637 CreateMockRead(data2, 2),
20638 MockRead(ASYNC, 0, 3),
20639 };
20640
20641 SequencedSocketData spdy_data2(connect, spdy_reads2, spdy_writes2);
20642 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data2);
20643
20644 AddSSLSocketData();
20645
20646 HttpRequestInfo request2;
20647 request2.method = "GET";
20648 request2.url = GURL("http://request2.test/");
20649 request2.traffic_annotation =
20650 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
20651
20652 TestCompletionCallback callback2;
20653
20654 HttpNetworkTransaction trans2(DEFAULT_PRIORITY, session.get());
20655
20656 rv = trans2.Start(&request2, callback2.callback(),
20657 NetLogWithSource::Make(NetLogSourceType::NONE));
20658 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
20659
20660 rv = callback2.WaitForResult();
20661 ASSERT_THAT(rv, IsOk());
20662
20663 response = trans2.GetResponseInfo();
20664 ASSERT_TRUE(response);
20665 ASSERT_TRUE(response->headers);
20666 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
20667 }
20668
20669 // Regression test for https://crbug.com/546991.
20670 // The server might not be able to serve an IP pooled request, and might send a
20671 // 421 Misdirected Request response status to indicate this.
20672 // HttpNetworkTransaction should reset the request and retry without IP pooling.
TEST_P(HttpNetworkTransactionTest,RetryWithoutConnectionPooling)20673 TEST_P(HttpNetworkTransactionTest, RetryWithoutConnectionPooling) {
20674 // Two hosts resolve to the same IP address.
20675 const std::string ip_addr = "1.2.3.4";
20676 IPAddress ip;
20677 ASSERT_TRUE(ip.AssignFromIPLiteral(ip_addr));
20678 IPEndPoint peer_addr = IPEndPoint(ip, 443);
20679
20680 session_deps_.host_resolver = std::make_unique<MockCachingHostResolver>();
20681 session_deps_.host_resolver->rules()->AddRule("www.example.org", ip_addr);
20682 session_deps_.host_resolver->rules()->AddRule("mail.example.org", ip_addr);
20683
20684 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
20685
20686 // Two requests on the first connection.
20687 spdy::SpdySerializedFrame req1(
20688 spdy_util_.ConstructSpdyGet("https://www.example.org", 1, LOWEST));
20689 spdy_util_.UpdateWithStreamDestruction(1);
20690 spdy::SpdySerializedFrame req2(
20691 spdy_util_.ConstructSpdyGet("https://mail.example.org", 3, LOWEST));
20692 spdy::SpdySerializedFrame rst(
20693 spdy_util_.ConstructSpdyRstStream(3, spdy::ERROR_CODE_CANCEL));
20694 MockWrite writes1[] = {
20695 CreateMockWrite(req1, 0),
20696 CreateMockWrite(req2, 3),
20697 CreateMockWrite(rst, 6),
20698 };
20699
20700 // The first one succeeds, the second gets error 421 Misdirected Request.
20701 spdy::SpdySerializedFrame resp1(
20702 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
20703 spdy::SpdySerializedFrame body1(spdy_util_.ConstructSpdyDataFrame(1, true));
20704 spdy::Http2HeaderBlock response_headers;
20705 response_headers[spdy::kHttp2StatusHeader] = "421";
20706 spdy::SpdySerializedFrame resp2(
20707 spdy_util_.ConstructSpdyReply(3, std::move(response_headers)));
20708 MockRead reads1[] = {CreateMockRead(resp1, 1), CreateMockRead(body1, 2),
20709 CreateMockRead(resp2, 4), MockRead(ASYNC, 0, 5)};
20710
20711 MockConnect connect1(ASYNC, OK, peer_addr);
20712 SequencedSocketData data1(connect1, reads1, writes1);
20713 session_deps_.socket_factory->AddSocketDataProvider(&data1);
20714
20715 AddSSLSocketData();
20716
20717 // Retry the second request on a second connection.
20718 SpdyTestUtil spdy_util2(/*use_priority_header=*/true);
20719 spdy::SpdySerializedFrame req3(
20720 spdy_util2.ConstructSpdyGet("https://mail.example.org", 1, LOWEST));
20721 MockWrite writes2[] = {
20722 CreateMockWrite(req3, 0),
20723 };
20724
20725 spdy::SpdySerializedFrame resp3(
20726 spdy_util2.ConstructSpdyGetReply(nullptr, 0, 1));
20727 spdy::SpdySerializedFrame body3(spdy_util2.ConstructSpdyDataFrame(1, true));
20728 MockRead reads2[] = {CreateMockRead(resp3, 1), CreateMockRead(body3, 2),
20729 MockRead(ASYNC, 0, 3)};
20730
20731 MockConnect connect2(ASYNC, OK, peer_addr);
20732 SequencedSocketData data2(connect2, reads2, writes2);
20733 session_deps_.socket_factory->AddSocketDataProvider(&data2);
20734
20735 AddSSLSocketData();
20736
20737 // Preload mail.example.org into HostCache.
20738 int rv = session_deps_.host_resolver->LoadIntoCache(
20739 HostPortPair("mail.example.org", 443), NetworkAnonymizationKey(),
20740 std::nullopt);
20741 EXPECT_THAT(rv, IsOk());
20742
20743 HttpRequestInfo request1;
20744 request1.method = "GET";
20745 request1.url = GURL("https://www.example.org/");
20746 request1.load_flags = 0;
20747 request1.traffic_annotation =
20748 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
20749 HttpNetworkTransaction trans1(DEFAULT_PRIORITY, session.get());
20750
20751 TestCompletionCallback callback;
20752 rv = trans1.Start(&request1, callback.callback(), NetLogWithSource());
20753 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
20754 rv = callback.WaitForResult();
20755 EXPECT_THAT(rv, IsOk());
20756
20757 const HttpResponseInfo* response = trans1.GetResponseInfo();
20758 ASSERT_TRUE(response);
20759 ASSERT_TRUE(response->headers);
20760 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
20761 EXPECT_TRUE(response->was_fetched_via_spdy);
20762 EXPECT_TRUE(response->was_alpn_negotiated);
20763 std::string response_data;
20764 ASSERT_THAT(ReadTransaction(&trans1, &response_data), IsOk());
20765 EXPECT_EQ("hello!", response_data);
20766
20767 HttpRequestInfo request2;
20768 request2.method = "GET";
20769 request2.url = GURL("https://mail.example.org/");
20770 request2.load_flags = 0;
20771 request2.traffic_annotation =
20772 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
20773 HttpNetworkTransaction trans2(DEFAULT_PRIORITY, session.get());
20774
20775 RecordingNetLogObserver net_log_observer;
20776 rv = trans2.Start(&request2, callback.callback(),
20777 NetLogWithSource::Make(NetLogSourceType::NONE));
20778 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
20779 rv = callback.WaitForResult();
20780 EXPECT_THAT(rv, IsOk());
20781
20782 response = trans2.GetResponseInfo();
20783 ASSERT_TRUE(response);
20784 ASSERT_TRUE(response->headers);
20785 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
20786 EXPECT_TRUE(response->was_fetched_via_spdy);
20787 EXPECT_TRUE(response->was_alpn_negotiated);
20788 ASSERT_THAT(ReadTransaction(&trans2, &response_data), IsOk());
20789 EXPECT_EQ("hello!", response_data);
20790
20791 auto entries = net_log_observer.GetEntries();
20792 ExpectLogContainsSomewhere(
20793 entries, 0, NetLogEventType::HTTP_TRANSACTION_RESTART_MISDIRECTED_REQUEST,
20794 NetLogEventPhase::NONE);
20795 }
20796
20797 // Test that HTTP 421 responses are properly returned to the caller if received
20798 // on the retry as well. HttpNetworkTransaction should not infinite loop or lose
20799 // portions of the response.
TEST_P(HttpNetworkTransactionTest,ReturnHTTP421OnRetry)20800 TEST_P(HttpNetworkTransactionTest, ReturnHTTP421OnRetry) {
20801 // Two hosts resolve to the same IP address.
20802 const std::string ip_addr = "1.2.3.4";
20803 IPAddress ip;
20804 ASSERT_TRUE(ip.AssignFromIPLiteral(ip_addr));
20805 IPEndPoint peer_addr = IPEndPoint(ip, 443);
20806
20807 session_deps_.host_resolver = std::make_unique<MockCachingHostResolver>();
20808 session_deps_.host_resolver->rules()->AddRule("www.example.org", ip_addr);
20809 session_deps_.host_resolver->rules()->AddRule("mail.example.org", ip_addr);
20810
20811 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
20812
20813 // Two requests on the first connection.
20814 spdy::SpdySerializedFrame req1(
20815 spdy_util_.ConstructSpdyGet("https://www.example.org", 1, LOWEST));
20816 spdy_util_.UpdateWithStreamDestruction(1);
20817 spdy::SpdySerializedFrame req2(
20818 spdy_util_.ConstructSpdyGet("https://mail.example.org", 3, LOWEST));
20819 spdy::SpdySerializedFrame rst(
20820 spdy_util_.ConstructSpdyRstStream(3, spdy::ERROR_CODE_CANCEL));
20821 MockWrite writes1[] = {
20822 CreateMockWrite(req1, 0),
20823 CreateMockWrite(req2, 3),
20824 CreateMockWrite(rst, 6),
20825 };
20826
20827 // The first one succeeds, the second gets error 421 Misdirected Request.
20828 spdy::SpdySerializedFrame resp1(
20829 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
20830 spdy::SpdySerializedFrame body1(spdy_util_.ConstructSpdyDataFrame(1, true));
20831 spdy::Http2HeaderBlock response_headers;
20832 response_headers[spdy::kHttp2StatusHeader] = "421";
20833 spdy::SpdySerializedFrame resp2(
20834 spdy_util_.ConstructSpdyReply(3, response_headers.Clone()));
20835 MockRead reads1[] = {CreateMockRead(resp1, 1), CreateMockRead(body1, 2),
20836 CreateMockRead(resp2, 4), MockRead(ASYNC, 0, 5)};
20837
20838 MockConnect connect1(ASYNC, OK, peer_addr);
20839 SequencedSocketData data1(connect1, reads1, writes1);
20840 session_deps_.socket_factory->AddSocketDataProvider(&data1);
20841
20842 AddSSLSocketData();
20843
20844 // Retry the second request on a second connection. It returns 421 Misdirected
20845 // Retry again.
20846 SpdyTestUtil spdy_util2(/*use_priority_header=*/true);
20847 spdy::SpdySerializedFrame req3(
20848 spdy_util2.ConstructSpdyGet("https://mail.example.org", 1, LOWEST));
20849 MockWrite writes2[] = {
20850 CreateMockWrite(req3, 0),
20851 };
20852
20853 spdy::SpdySerializedFrame resp3(
20854 spdy_util2.ConstructSpdyReply(1, std::move(response_headers)));
20855 spdy::SpdySerializedFrame body3(spdy_util2.ConstructSpdyDataFrame(1, true));
20856 MockRead reads2[] = {CreateMockRead(resp3, 1), CreateMockRead(body3, 2),
20857 MockRead(ASYNC, 0, 3)};
20858
20859 MockConnect connect2(ASYNC, OK, peer_addr);
20860 SequencedSocketData data2(connect2, reads2, writes2);
20861 session_deps_.socket_factory->AddSocketDataProvider(&data2);
20862
20863 AddSSLSocketData();
20864
20865 // Preload mail.example.org into HostCache.
20866 int rv = session_deps_.host_resolver->LoadIntoCache(
20867 HostPortPair("mail.example.org", 443), NetworkAnonymizationKey(),
20868 std::nullopt);
20869 EXPECT_THAT(rv, IsOk());
20870
20871 HttpRequestInfo request1;
20872 request1.method = "GET";
20873 request1.url = GURL("https://www.example.org/");
20874 request1.load_flags = 0;
20875 request1.traffic_annotation =
20876 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
20877 HttpNetworkTransaction trans1(DEFAULT_PRIORITY, session.get());
20878
20879 TestCompletionCallback callback;
20880 rv = trans1.Start(&request1, callback.callback(), NetLogWithSource());
20881 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
20882 rv = callback.WaitForResult();
20883 EXPECT_THAT(rv, IsOk());
20884
20885 const HttpResponseInfo* response = trans1.GetResponseInfo();
20886 ASSERT_TRUE(response);
20887 ASSERT_TRUE(response->headers);
20888 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
20889 EXPECT_TRUE(response->was_fetched_via_spdy);
20890 EXPECT_TRUE(response->was_alpn_negotiated);
20891 std::string response_data;
20892 ASSERT_THAT(ReadTransaction(&trans1, &response_data), IsOk());
20893 EXPECT_EQ("hello!", response_data);
20894
20895 HttpRequestInfo request2;
20896 request2.method = "GET";
20897 request2.url = GURL("https://mail.example.org/");
20898 request2.load_flags = 0;
20899 request2.traffic_annotation =
20900 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
20901 HttpNetworkTransaction trans2(DEFAULT_PRIORITY, session.get());
20902
20903 rv = trans2.Start(&request2, callback.callback(),
20904 NetLogWithSource::Make(NetLogSourceType::NONE));
20905 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
20906 rv = callback.WaitForResult();
20907 EXPECT_THAT(rv, IsOk());
20908
20909 // After a retry, the 421 Misdirected Request is reported back up to the
20910 // caller.
20911 response = trans2.GetResponseInfo();
20912 ASSERT_TRUE(response);
20913 ASSERT_TRUE(response->headers);
20914 EXPECT_EQ("HTTP/1.1 421", response->headers->GetStatusLine());
20915 EXPECT_TRUE(response->was_fetched_via_spdy);
20916 EXPECT_TRUE(response->was_alpn_negotiated);
20917 EXPECT_TRUE(response->ssl_info.cert);
20918 ASSERT_THAT(ReadTransaction(&trans2, &response_data), IsOk());
20919 EXPECT_EQ("hello!", response_data);
20920 }
20921
TEST_P(HttpNetworkTransactionTest,Response421WithStreamingBodyWithNonNullSource)20922 TEST_P(HttpNetworkTransactionTest,
20923 Response421WithStreamingBodyWithNonNullSource) {
20924 const std::string ip_addr = "1.2.3.4";
20925 IPAddress ip;
20926 ASSERT_TRUE(ip.AssignFromIPLiteral(ip_addr));
20927 IPEndPoint peer_addr = IPEndPoint(ip, 443);
20928
20929 session_deps_.host_resolver = std::make_unique<MockCachingHostResolver>();
20930 session_deps_.host_resolver->rules()->AddRule("www.example.org", ip_addr);
20931 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
20932
20933 const std::string request_body = "hello";
20934 spdy::SpdySerializedFrame req1 = spdy_util_.ConstructChunkedSpdyPost({}, 0);
20935 spdy::SpdySerializedFrame req1_body =
20936 spdy_util_.ConstructSpdyDataFrame(1, request_body, /*fin=*/true);
20937 spdy::SpdySerializedFrame rst =
20938 spdy_util_.ConstructSpdyRstStream(1, spdy::ERROR_CODE_CANCEL);
20939 MockWrite writes1[] = {
20940 CreateMockWrite(req1, 0),
20941 CreateMockWrite(req1_body, 1),
20942 CreateMockWrite(rst, 4),
20943 };
20944
20945 spdy::Http2HeaderBlock response_headers;
20946 response_headers[spdy::kHttp2StatusHeader] = "421";
20947 spdy::SpdySerializedFrame resp1 =
20948 spdy_util_.ConstructSpdyReply(1, std::move(response_headers));
20949 MockRead reads1[] = {CreateMockRead(resp1, 2), MockRead(ASYNC, 0, 3)};
20950
20951 MockConnect connect1(ASYNC, OK, peer_addr);
20952 SequencedSocketData data1(connect1, reads1, writes1);
20953 session_deps_.socket_factory->AddSocketDataProvider(&data1);
20954
20955 AddSSLSocketData();
20956
20957 SpdyTestUtil spdy_util2(/*use_priority_header=*/true);
20958 spdy::SpdySerializedFrame req2 = spdy_util2.ConstructChunkedSpdyPost({}, 0);
20959 spdy::SpdySerializedFrame req2_body =
20960 spdy_util2.ConstructSpdyDataFrame(1, request_body, /*fin=*/true);
20961 MockWrite writes2[] = {
20962 CreateMockWrite(req2, 0),
20963 CreateMockWrite(req2_body, 1),
20964 };
20965
20966 spdy::Http2HeaderBlock resp2_headers;
20967 resp2_headers[spdy::kHttp2StatusHeader] = "200";
20968 spdy::SpdySerializedFrame resp2 =
20969 spdy_util2.ConstructSpdyReply(1, std::move(resp2_headers));
20970 spdy::SpdySerializedFrame resp2_body(
20971 spdy_util2.ConstructSpdyDataFrame(1, true));
20972 MockRead reads2[] = {CreateMockRead(resp2, 2), CreateMockRead(resp2_body, 3),
20973 MockRead(ASYNC, 0, 4)};
20974
20975 MockConnect connect2(ASYNC, OK, peer_addr);
20976 SequencedSocketData data2(connect2, reads2, writes2);
20977 session_deps_.socket_factory->AddSocketDataProvider(&data2);
20978
20979 AddSSLSocketData();
20980
20981 TestCompletionCallback callback;
20982 HttpRequestInfo request;
20983 ChunkedUploadDataStream upload_data_stream(0, /*has_null_source=*/false);
20984 upload_data_stream.AppendData(request_body.data(), request_body.size(),
20985 /*is_done=*/true);
20986 request.method = "POST";
20987 request.url = GURL("https://www.example.org");
20988 request.load_flags = 0;
20989 request.traffic_annotation =
20990 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
20991 request.upload_data_stream = &upload_data_stream;
20992 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
20993
20994 int rv = trans.Start(&request, callback.callback(),
20995 NetLogWithSource::Make(NetLogSourceType::NONE));
20996 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
20997 rv = callback.WaitForResult();
20998 EXPECT_THAT(rv, IsOk());
20999
21000 const HttpResponseInfo* response = trans.GetResponseInfo();
21001 std::string response_data;
21002 ASSERT_TRUE(response);
21003 ASSERT_TRUE(response->headers);
21004 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
21005 EXPECT_TRUE(response->was_fetched_via_spdy);
21006 EXPECT_TRUE(response->was_alpn_negotiated);
21007 EXPECT_TRUE(response->ssl_info.cert);
21008 ASSERT_THAT(ReadTransaction(&trans, &response_data), IsOk());
21009 EXPECT_EQ("hello!", response_data);
21010 }
21011
TEST_P(HttpNetworkTransactionTest,Response421WithStreamingBodyWithNullSource)21012 TEST_P(HttpNetworkTransactionTest, Response421WithStreamingBodyWithNullSource) {
21013 const std::string ip_addr = "1.2.3.4";
21014 IPAddress ip;
21015 ASSERT_TRUE(ip.AssignFromIPLiteral(ip_addr));
21016 IPEndPoint peer_addr = IPEndPoint(ip, 443);
21017
21018 session_deps_.host_resolver = std::make_unique<MockCachingHostResolver>();
21019 session_deps_.host_resolver->rules()->AddRule("www.example.org", ip_addr);
21020 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
21021
21022 const std::string request_body = "hello";
21023 spdy::SpdySerializedFrame req1 = spdy_util_.ConstructChunkedSpdyPost({}, 0);
21024 spdy::SpdySerializedFrame req1_body =
21025 spdy_util_.ConstructSpdyDataFrame(1, request_body, /*fin=*/true);
21026 spdy::SpdySerializedFrame rst =
21027 spdy_util_.ConstructSpdyRstStream(1, spdy::ERROR_CODE_CANCEL);
21028 MockWrite writes1[] = {
21029 CreateMockWrite(req1, 0),
21030 CreateMockWrite(req1_body, 1),
21031 CreateMockWrite(rst, 5),
21032 };
21033
21034 spdy::Http2HeaderBlock response_headers;
21035 response_headers[spdy::kHttp2StatusHeader] = "421";
21036 spdy::SpdySerializedFrame resp1 =
21037 spdy_util_.ConstructSpdyReply(1, std::move(response_headers));
21038 spdy::SpdySerializedFrame resp1_body(
21039 spdy_util_.ConstructSpdyDataFrame(1, true));
21040 MockRead reads1[] = {CreateMockRead(resp1, 2), CreateMockRead(resp1_body, 3),
21041 MockRead(ASYNC, 0, 4)};
21042
21043 MockConnect connect1(ASYNC, OK, peer_addr);
21044 SequencedSocketData data1(connect1, reads1, writes1);
21045 session_deps_.socket_factory->AddSocketDataProvider(&data1);
21046
21047 AddSSLSocketData();
21048
21049 TestCompletionCallback callback;
21050 HttpRequestInfo request;
21051 ChunkedUploadDataStream upload_data_stream(0, /*has_null_source=*/true);
21052 upload_data_stream.AppendData(request_body.data(), request_body.size(),
21053 /*is_done=*/true);
21054 request.method = "POST";
21055 request.url = GURL("https://www.example.org");
21056 request.load_flags = 0;
21057 request.traffic_annotation =
21058 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
21059 request.upload_data_stream = &upload_data_stream;
21060 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
21061
21062 int rv = trans.Start(&request, callback.callback(),
21063 NetLogWithSource::Make(NetLogSourceType::NONE));
21064 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
21065 rv = callback.WaitForResult();
21066 EXPECT_THAT(rv, IsOk());
21067
21068 const HttpResponseInfo* response = trans.GetResponseInfo();
21069 std::string response_data;
21070 ASSERT_TRUE(response);
21071 ASSERT_TRUE(response->headers);
21072 EXPECT_EQ("HTTP/1.1 421", response->headers->GetStatusLine());
21073 EXPECT_TRUE(response->was_fetched_via_spdy);
21074 EXPECT_TRUE(response->was_alpn_negotiated);
21075 EXPECT_TRUE(response->ssl_info.cert);
21076 ASSERT_THAT(ReadTransaction(&trans, &response_data), IsOk());
21077 EXPECT_EQ("hello!", response_data);
21078 }
21079
TEST_P(HttpNetworkTransactionTest,UseIPConnectionPoolingWithHostCacheExpiration)21080 TEST_P(HttpNetworkTransactionTest,
21081 UseIPConnectionPoolingWithHostCacheExpiration) {
21082 // Set up HostResolver to invalidate cached entries after 1 cached resolve.
21083 session_deps_.host_resolver =
21084 std::make_unique<MockCachingHostResolver>(1 /* cache_invalidation_num */);
21085 session_deps_.host_resolver->rules()->AddRule("www.example.org", "1.2.3.4");
21086 session_deps_.host_resolver->rules()->AddRule("mail.example.com", "1.2.3.4");
21087 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
21088
21089 AddSSLSocketData();
21090
21091 spdy::SpdySerializedFrame host1_req(
21092 spdy_util_.ConstructSpdyGet("https://www.example.org", 1, LOWEST));
21093 spdy_util_.UpdateWithStreamDestruction(1);
21094 spdy::SpdySerializedFrame host2_req(
21095 spdy_util_.ConstructSpdyGet("https://mail.example.com", 3, LOWEST));
21096 MockWrite spdy_writes[] = {
21097 CreateMockWrite(host1_req, 0),
21098 CreateMockWrite(host2_req, 3),
21099 };
21100 spdy::SpdySerializedFrame host1_resp(
21101 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
21102 spdy::SpdySerializedFrame host1_resp_body(
21103 spdy_util_.ConstructSpdyDataFrame(1, true));
21104 spdy::SpdySerializedFrame host2_resp(
21105 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 3));
21106 spdy::SpdySerializedFrame host2_resp_body(
21107 spdy_util_.ConstructSpdyDataFrame(3, true));
21108 MockRead spdy_reads[] = {
21109 CreateMockRead(host1_resp, 1), CreateMockRead(host1_resp_body, 2),
21110 CreateMockRead(host2_resp, 4), CreateMockRead(host2_resp_body, 5),
21111 MockRead(ASYNC, 0, 6),
21112 };
21113
21114 IPEndPoint peer_addr(IPAddress::IPv4Localhost(), 443);
21115 MockConnect connect(ASYNC, OK, peer_addr);
21116 SequencedSocketData spdy_data(connect, spdy_reads, spdy_writes);
21117 session_deps_.socket_factory->AddSocketDataProvider(&spdy_data);
21118
21119 TestCompletionCallback callback;
21120 HttpRequestInfo request1;
21121 request1.method = "GET";
21122 request1.url = GURL("https://www.example.org/");
21123 request1.load_flags = 0;
21124 request1.traffic_annotation =
21125 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
21126 HttpNetworkTransaction trans1(DEFAULT_PRIORITY, session.get());
21127
21128 int rv = trans1.Start(&request1, callback.callback(), NetLogWithSource());
21129 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
21130 EXPECT_THAT(callback.WaitForResult(), IsOk());
21131
21132 const HttpResponseInfo* response = trans1.GetResponseInfo();
21133 ASSERT_TRUE(response);
21134 ASSERT_TRUE(response->headers);
21135 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
21136
21137 std::string response_data;
21138 ASSERT_THAT(ReadTransaction(&trans1, &response_data), IsOk());
21139 EXPECT_EQ("hello!", response_data);
21140
21141 // Preload cache entries into HostCache.
21142 rv = session_deps_.host_resolver->LoadIntoCache(
21143 HostPortPair("mail.example.com", 443), NetworkAnonymizationKey(),
21144 std::nullopt);
21145 EXPECT_THAT(rv, IsOk());
21146
21147 HttpRequestInfo request2;
21148 request2.method = "GET";
21149 request2.url = GURL("https://mail.example.com/");
21150 request2.load_flags = 0;
21151 request2.traffic_annotation =
21152 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
21153 HttpNetworkTransaction trans2(DEFAULT_PRIORITY, session.get());
21154
21155 rv = trans2.Start(&request2, callback.callback(), NetLogWithSource());
21156 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
21157 EXPECT_THAT(callback.WaitForResult(), IsOk());
21158
21159 response = trans2.GetResponseInfo();
21160 ASSERT_TRUE(response);
21161 ASSERT_TRUE(response->headers);
21162 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
21163 EXPECT_TRUE(response->was_fetched_via_spdy);
21164 EXPECT_TRUE(response->was_alpn_negotiated);
21165 ASSERT_THAT(ReadTransaction(&trans2, &response_data), IsOk());
21166 EXPECT_EQ("hello!", response_data);
21167 }
21168
TEST_P(HttpNetworkTransactionTest,DoNotUseSpdySessionForHttp)21169 TEST_P(HttpNetworkTransactionTest, DoNotUseSpdySessionForHttp) {
21170 const std::string https_url = "https://www.example.org:8080/";
21171 const std::string http_url = "http://www.example.org:8080/";
21172
21173 // SPDY GET for HTTPS URL
21174 spdy::SpdySerializedFrame req1(
21175 spdy_util_.ConstructSpdyGet(https_url.c_str(), 1, LOWEST));
21176
21177 MockWrite writes1[] = {
21178 CreateMockWrite(req1, 0),
21179 };
21180
21181 spdy::SpdySerializedFrame resp1(
21182 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
21183 spdy::SpdySerializedFrame body1(spdy_util_.ConstructSpdyDataFrame(1, true));
21184 MockRead reads1[] = {CreateMockRead(resp1, 1), CreateMockRead(body1, 2),
21185 MockRead(SYNCHRONOUS, ERR_IO_PENDING, 3)};
21186
21187 SequencedSocketData data1(reads1, writes1);
21188 MockConnect connect_data1(ASYNC, OK);
21189 data1.set_connect_data(connect_data1);
21190
21191 // HTTP GET for the HTTP URL
21192 MockWrite writes2[] = {
21193 MockWrite(ASYNC, 0,
21194 "GET / HTTP/1.1\r\n"
21195 "Host: www.example.org:8080\r\n"
21196 "Connection: keep-alive\r\n\r\n"),
21197 };
21198
21199 MockRead reads2[] = {
21200 MockRead(ASYNC, 1, "HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
21201 MockRead(ASYNC, 2, "hello"),
21202 MockRead(ASYNC, OK, 3),
21203 };
21204
21205 SequencedSocketData data2(reads2, writes2);
21206
21207 SSLSocketDataProvider ssl(ASYNC, OK);
21208 ssl.next_proto = kProtoHTTP2;
21209 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
21210 session_deps_.socket_factory->AddSocketDataProvider(&data1);
21211 session_deps_.socket_factory->AddSocketDataProvider(&data2);
21212
21213 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
21214
21215 // Start the first transaction to set up the SpdySession
21216 HttpRequestInfo request1;
21217 request1.method = "GET";
21218 request1.url = GURL(https_url);
21219 request1.load_flags = 0;
21220 request1.traffic_annotation =
21221 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
21222 HttpNetworkTransaction trans1(LOWEST, session.get());
21223 TestCompletionCallback callback1;
21224 EXPECT_EQ(ERR_IO_PENDING,
21225 trans1.Start(&request1, callback1.callback(), NetLogWithSource()));
21226 base::RunLoop().RunUntilIdle();
21227
21228 EXPECT_THAT(callback1.WaitForResult(), IsOk());
21229 EXPECT_TRUE(trans1.GetResponseInfo()->was_fetched_via_spdy);
21230
21231 // Now, start the HTTP request
21232 HttpRequestInfo request2;
21233 request2.method = "GET";
21234 request2.url = GURL(http_url);
21235 request2.load_flags = 0;
21236 request2.traffic_annotation =
21237 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
21238 HttpNetworkTransaction trans2(MEDIUM, session.get());
21239 TestCompletionCallback callback2;
21240 EXPECT_EQ(ERR_IO_PENDING,
21241 trans2.Start(&request2, callback2.callback(), NetLogWithSource()));
21242 base::RunLoop().RunUntilIdle();
21243
21244 EXPECT_THAT(callback2.WaitForResult(), IsOk());
21245 EXPECT_FALSE(trans2.GetResponseInfo()->was_fetched_via_spdy);
21246 }
21247
21248 // Alternative service requires HTTP/2 (or SPDY), but HTTP/1.1 is negotiated
21249 // with the alternative server. That connection should not be used.
TEST_P(HttpNetworkTransactionTest,AlternativeServiceNotOnHttp11)21250 TEST_P(HttpNetworkTransactionTest, AlternativeServiceNotOnHttp11) {
21251 url::SchemeHostPort server("https", "www.example.org", 443);
21252 HostPortPair alternative("www.example.org", 444);
21253
21254 // Negotiate HTTP/1.1 with alternative.
21255 SSLSocketDataProvider ssl(ASYNC, OK);
21256 ssl.next_proto = kProtoHTTP11;
21257 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
21258
21259 // No data should be read from the alternative, because HTTP/1.1 is
21260 // negotiated.
21261 StaticSocketDataProvider data;
21262 session_deps_.socket_factory->AddSocketDataProvider(&data);
21263
21264 // This test documents that an alternate Job should not be used if HTTP/1.1 is
21265 // negotiated. In order to test this, a failed connection to the server is
21266 // mocked. This way the request relies on the alternate Job.
21267 StaticSocketDataProvider data_refused;
21268 data_refused.set_connect_data(MockConnect(ASYNC, ERR_CONNECTION_REFUSED));
21269 session_deps_.socket_factory->AddSocketDataProvider(&data_refused);
21270
21271 // Set up alternative service for server.
21272 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
21273 HttpServerProperties* http_server_properties =
21274 session->http_server_properties();
21275 AlternativeService alternative_service(kProtoHTTP2, alternative);
21276 base::Time expiration = base::Time::Now() + base::Days(1);
21277 http_server_properties->SetHttp2AlternativeService(
21278 server, NetworkAnonymizationKey(), alternative_service, expiration);
21279
21280 HttpRequestInfo request;
21281 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
21282 request.method = "GET";
21283 request.url = GURL("https://www.example.org:443");
21284 request.traffic_annotation =
21285 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
21286 TestCompletionCallback callback;
21287
21288 // HTTP/2 (or SPDY) is required for alternative service, if HTTP/1.1 is
21289 // negotiated, the alternate Job should fail with ERR_ALPN_NEGOTIATION_FAILED.
21290 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
21291 EXPECT_THAT(callback.GetResult(rv), IsError(ERR_ALPN_NEGOTIATION_FAILED));
21292 }
21293
21294 // A request to a server with an alternative service fires two Jobs: one to the
21295 // server, and an alternate one to the alternative server. If the former
21296 // succeeds, the request should succeed, even if the latter fails because
21297 // HTTP/1.1 is negotiated which is insufficient for alternative service.
TEST_P(HttpNetworkTransactionTest,FailedAlternativeServiceIsNotUserVisible)21298 TEST_P(HttpNetworkTransactionTest, FailedAlternativeServiceIsNotUserVisible) {
21299 url::SchemeHostPort server("https", "www.example.org", 443);
21300 HostPortPair alternative("www.example.org", 444);
21301
21302 // Negotiate HTTP/1.1 with alternative.
21303 SSLSocketDataProvider alternative_ssl(ASYNC, OK);
21304 alternative_ssl.next_proto = kProtoHTTP11;
21305 session_deps_.socket_factory->AddSSLSocketDataProvider(&alternative_ssl);
21306
21307 // No data should be read from the alternative, because HTTP/1.1 is
21308 // negotiated.
21309 StaticSocketDataProvider data;
21310 session_deps_.socket_factory->AddSocketDataProvider(&data);
21311
21312 // Negotiate HTTP/1.1 with server.
21313 SSLSocketDataProvider origin_ssl(ASYNC, OK);
21314 origin_ssl.next_proto = kProtoHTTP11;
21315 session_deps_.socket_factory->AddSSLSocketDataProvider(&origin_ssl);
21316
21317 MockWrite http_writes[] = {
21318 MockWrite("GET / HTTP/1.1\r\n"
21319 "Host: www.example.org\r\n"
21320 "Connection: keep-alive\r\n\r\n"),
21321 MockWrite("GET /second HTTP/1.1\r\n"
21322 "Host: www.example.org\r\n"
21323 "Connection: keep-alive\r\n\r\n"),
21324 };
21325
21326 MockRead http_reads[] = {
21327 MockRead("HTTP/1.1 200 OK\r\n"),
21328 MockRead("Content-Type: text/html\r\n"),
21329 MockRead("Content-Length: 6\r\n\r\n"),
21330 MockRead("foobar"),
21331 MockRead("HTTP/1.1 200 OK\r\n"),
21332 MockRead("Content-Type: text/html\r\n"),
21333 MockRead("Content-Length: 7\r\n\r\n"),
21334 MockRead("another"),
21335 };
21336 StaticSocketDataProvider http_data(http_reads, http_writes);
21337 session_deps_.socket_factory->AddSocketDataProvider(&http_data);
21338
21339 // Set up alternative service for server.
21340 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
21341 HttpServerProperties* http_server_properties =
21342 session->http_server_properties();
21343 AlternativeService alternative_service(kProtoHTTP2, alternative);
21344 base::Time expiration = base::Time::Now() + base::Days(1);
21345 http_server_properties->SetHttp2AlternativeService(
21346 server, NetworkAnonymizationKey(), alternative_service, expiration);
21347
21348 HttpNetworkTransaction trans1(DEFAULT_PRIORITY, session.get());
21349 HttpRequestInfo request1;
21350 request1.method = "GET";
21351 request1.url = GURL("https://www.example.org:443");
21352 request1.load_flags = 0;
21353 request1.traffic_annotation =
21354 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
21355 TestCompletionCallback callback1;
21356
21357 int rv = trans1.Start(&request1, callback1.callback(), NetLogWithSource());
21358 rv = callback1.GetResult(rv);
21359 EXPECT_THAT(rv, IsOk());
21360
21361 const HttpResponseInfo* response1 = trans1.GetResponseInfo();
21362 ASSERT_TRUE(response1);
21363 ASSERT_TRUE(response1->headers);
21364 EXPECT_EQ("HTTP/1.1 200 OK", response1->headers->GetStatusLine());
21365
21366 std::string response_data1;
21367 ASSERT_THAT(ReadTransaction(&trans1, &response_data1), IsOk());
21368 EXPECT_EQ("foobar", response_data1);
21369
21370 // Alternative should be marked as broken, because HTTP/1.1 is not sufficient
21371 // for alternative service.
21372 EXPECT_TRUE(http_server_properties->IsAlternativeServiceBroken(
21373 alternative_service, NetworkAnonymizationKey()));
21374
21375 // Since |alternative_service| is broken, a second transaction to server
21376 // should not start an alternate Job. It should pool to existing connection
21377 // to server.
21378 HttpNetworkTransaction trans2(DEFAULT_PRIORITY, session.get());
21379 HttpRequestInfo request2;
21380 request2.method = "GET";
21381 request2.url = GURL("https://www.example.org:443/second");
21382 request2.load_flags = 0;
21383 request2.traffic_annotation =
21384 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
21385 TestCompletionCallback callback2;
21386
21387 rv = trans2.Start(&request2, callback2.callback(), NetLogWithSource());
21388 rv = callback2.GetResult(rv);
21389 EXPECT_THAT(rv, IsOk());
21390
21391 const HttpResponseInfo* response2 = trans2.GetResponseInfo();
21392 ASSERT_TRUE(response2);
21393 ASSERT_TRUE(response2->headers);
21394 EXPECT_EQ("HTTP/1.1 200 OK", response2->headers->GetStatusLine());
21395
21396 std::string response_data2;
21397 ASSERT_THAT(ReadTransaction(&trans2, &response_data2), IsOk());
21398 EXPECT_EQ("another", response_data2);
21399 }
21400
21401 // Alternative service requires HTTP/2 (or SPDY), but there is already a
21402 // HTTP/1.1 socket open to the alternative server. That socket should not be
21403 // used.
TEST_P(HttpNetworkTransactionTest,AlternativeServiceShouldNotPoolToHttp11)21404 TEST_P(HttpNetworkTransactionTest, AlternativeServiceShouldNotPoolToHttp11) {
21405 url::SchemeHostPort server("https", "origin.example.org", 443);
21406 HostPortPair alternative("alternative.example.org", 443);
21407 std::string origin_url = "https://origin.example.org:443";
21408 std::string alternative_url = "https://alternative.example.org:443";
21409
21410 // Negotiate HTTP/1.1 with alternative.example.org.
21411 SSLSocketDataProvider ssl(ASYNC, OK);
21412 ssl.next_proto = kProtoHTTP11;
21413 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
21414
21415 // HTTP/1.1 data for |request1| and |request2|.
21416 MockWrite http_writes[] = {
21417 MockWrite("GET / HTTP/1.1\r\n"
21418 "Host: alternative.example.org\r\n"
21419 "Connection: keep-alive\r\n\r\n"),
21420 MockWrite("GET / HTTP/1.1\r\n"
21421 "Host: alternative.example.org\r\n"
21422 "Connection: keep-alive\r\n\r\n"),
21423 };
21424
21425 MockRead http_reads[] = {
21426 MockRead("HTTP/1.1 200 OK\r\n"
21427 "Content-Type: text/html; charset=iso-8859-1\r\n"
21428 "Content-Length: 40\r\n\r\n"
21429 "first HTTP/1.1 response from alternative"),
21430 MockRead("HTTP/1.1 200 OK\r\n"
21431 "Content-Type: text/html; charset=iso-8859-1\r\n"
21432 "Content-Length: 41\r\n\r\n"
21433 "second HTTP/1.1 response from alternative"),
21434 };
21435 StaticSocketDataProvider http_data(http_reads, http_writes);
21436 session_deps_.socket_factory->AddSocketDataProvider(&http_data);
21437
21438 // This test documents that an alternate Job should not pool to an already
21439 // existing HTTP/1.1 connection. In order to test this, a failed connection
21440 // to the server is mocked. This way |request2| relies on the alternate Job.
21441 StaticSocketDataProvider data_refused;
21442 data_refused.set_connect_data(MockConnect(ASYNC, ERR_CONNECTION_REFUSED));
21443 session_deps_.socket_factory->AddSocketDataProvider(&data_refused);
21444
21445 // Set up alternative service for server.
21446 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
21447 HttpServerProperties* http_server_properties =
21448 session->http_server_properties();
21449 AlternativeService alternative_service(kProtoHTTP2, alternative);
21450 base::Time expiration = base::Time::Now() + base::Days(1);
21451 http_server_properties->SetHttp2AlternativeService(
21452 server, NetworkAnonymizationKey(), alternative_service, expiration);
21453
21454 // First transaction to alternative to open an HTTP/1.1 socket.
21455 HttpRequestInfo request1;
21456 HttpNetworkTransaction trans1(DEFAULT_PRIORITY, session.get());
21457 request1.method = "GET";
21458 request1.url = GURL(alternative_url);
21459 request1.load_flags = 0;
21460 request1.traffic_annotation =
21461 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
21462 TestCompletionCallback callback1;
21463
21464 int rv = trans1.Start(&request1, callback1.callback(), NetLogWithSource());
21465 EXPECT_THAT(callback1.GetResult(rv), IsOk());
21466 const HttpResponseInfo* response1 = trans1.GetResponseInfo();
21467 ASSERT_TRUE(response1);
21468 ASSERT_TRUE(response1->headers);
21469 EXPECT_EQ("HTTP/1.1 200 OK", response1->headers->GetStatusLine());
21470 EXPECT_TRUE(response1->was_alpn_negotiated);
21471 EXPECT_FALSE(response1->was_fetched_via_spdy);
21472 std::string response_data1;
21473 ASSERT_THAT(ReadTransaction(&trans1, &response_data1), IsOk());
21474 EXPECT_EQ("first HTTP/1.1 response from alternative", response_data1);
21475
21476 // Request for origin.example.org, which has an alternative service. This
21477 // will start two Jobs: the alternative looks for connections to pool to,
21478 // finds one which is HTTP/1.1, and should ignore it, and should not try to
21479 // open other connections to alternative server. The Job to server fails, so
21480 // this request fails.
21481 HttpRequestInfo request2;
21482 HttpNetworkTransaction trans2(DEFAULT_PRIORITY, session.get());
21483 request2.method = "GET";
21484 request2.url = GURL(origin_url);
21485 request2.load_flags = 0;
21486 request2.traffic_annotation =
21487 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
21488 TestCompletionCallback callback2;
21489
21490 rv = trans2.Start(&request2, callback2.callback(), NetLogWithSource());
21491 EXPECT_THAT(callback2.GetResult(rv), IsError(ERR_CONNECTION_REFUSED));
21492
21493 // Another transaction to alternative. This is to test that the HTTP/1.1
21494 // socket is still open and in the pool.
21495 HttpRequestInfo request3;
21496 HttpNetworkTransaction trans3(DEFAULT_PRIORITY, session.get());
21497 request3.method = "GET";
21498 request3.url = GURL(alternative_url);
21499 request3.load_flags = 0;
21500 request3.traffic_annotation =
21501 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
21502 TestCompletionCallback callback3;
21503
21504 rv = trans3.Start(&request3, callback3.callback(), NetLogWithSource());
21505 EXPECT_THAT(callback3.GetResult(rv), IsOk());
21506 const HttpResponseInfo* response3 = trans3.GetResponseInfo();
21507 ASSERT_TRUE(response3);
21508 ASSERT_TRUE(response3->headers);
21509 EXPECT_EQ("HTTP/1.1 200 OK", response3->headers->GetStatusLine());
21510 EXPECT_TRUE(response3->was_alpn_negotiated);
21511 EXPECT_FALSE(response3->was_fetched_via_spdy);
21512 std::string response_data3;
21513 ASSERT_THAT(ReadTransaction(&trans3, &response_data3), IsOk());
21514 EXPECT_EQ("second HTTP/1.1 response from alternative", response_data3);
21515 }
21516
TEST_P(HttpNetworkTransactionTest,DoNotUseSpdySessionForHttpOverTunnel)21517 TEST_P(HttpNetworkTransactionTest, DoNotUseSpdySessionForHttpOverTunnel) {
21518 const std::string https_url = "https://www.example.org:8080/";
21519 const std::string http_url = "http://www.example.org:8080/";
21520
21521 // Separate SPDY util instance for naked and wrapped requests.
21522 SpdyTestUtil spdy_util_wrapped(/*use_priority_header=*/true);
21523
21524 // SPDY GET for HTTPS URL (through CONNECT tunnel)
21525 const HostPortPair host_port_pair("www.example.org", 8080);
21526 spdy::SpdySerializedFrame connect(spdy_util_.ConstructSpdyConnect(
21527 nullptr, 0, 1, HttpProxyConnectJob::kH2QuicTunnelPriority,
21528 host_port_pair));
21529 spdy::SpdySerializedFrame req1(
21530 spdy_util_wrapped.ConstructSpdyGet(https_url.c_str(), 1, LOWEST));
21531 spdy::SpdySerializedFrame wrapped_req1(
21532 spdy_util_.ConstructWrappedSpdyFrame(req1, 1));
21533
21534 // SPDY GET for HTTP URL (through the proxy, but not the tunnel).
21535 spdy::Http2HeaderBlock req2_block;
21536 req2_block[spdy::kHttp2MethodHeader] = "GET";
21537 req2_block[spdy::kHttp2AuthorityHeader] = "www.example.org:8080";
21538 req2_block[spdy::kHttp2SchemeHeader] = "http";
21539 req2_block[spdy::kHttp2PathHeader] = "/";
21540 spdy::SpdySerializedFrame req2(
21541 spdy_util_.ConstructSpdyHeaders(3, std::move(req2_block), MEDIUM, true));
21542
21543 MockWrite writes1[] = {
21544 CreateMockWrite(connect, 0),
21545 CreateMockWrite(wrapped_req1, 2),
21546 CreateMockWrite(req2, 6),
21547 };
21548
21549 spdy::SpdySerializedFrame conn_resp(
21550 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
21551 spdy::SpdySerializedFrame resp1(
21552 spdy_util_wrapped.ConstructSpdyGetReply(nullptr, 0, 1));
21553 spdy::SpdySerializedFrame body1(
21554 spdy_util_wrapped.ConstructSpdyDataFrame(1, true));
21555 spdy::SpdySerializedFrame wrapped_resp1(
21556 spdy_util_wrapped.ConstructWrappedSpdyFrame(resp1, 1));
21557 spdy::SpdySerializedFrame wrapped_body1(
21558 spdy_util_wrapped.ConstructWrappedSpdyFrame(body1, 1));
21559 spdy::SpdySerializedFrame resp2(
21560 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 3));
21561 spdy::SpdySerializedFrame body2(spdy_util_.ConstructSpdyDataFrame(3, true));
21562 MockRead reads1[] = {
21563 CreateMockRead(conn_resp, 1),
21564 MockRead(ASYNC, ERR_IO_PENDING, 3),
21565 CreateMockRead(wrapped_resp1, 4),
21566 CreateMockRead(wrapped_body1, 5),
21567 MockRead(ASYNC, ERR_IO_PENDING, 7),
21568 CreateMockRead(resp2, 8),
21569 CreateMockRead(body2, 9),
21570 MockRead(SYNCHRONOUS, ERR_IO_PENDING, 10),
21571 };
21572
21573 SequencedSocketData data1(reads1, writes1);
21574 MockConnect connect_data1(ASYNC, OK);
21575 data1.set_connect_data(connect_data1);
21576
21577 session_deps_.proxy_resolution_service =
21578 ConfiguredProxyResolutionService::CreateFixedFromPacResultForTest(
21579 "HTTPS proxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
21580 session_deps_.net_log = net::NetLog::Get();
21581 SSLSocketDataProvider ssl1(ASYNC, OK); // to the proxy
21582 ssl1.next_proto = kProtoHTTP2;
21583 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl1);
21584 SSLSocketDataProvider ssl2(ASYNC, OK); // to the server
21585 ssl2.next_proto = kProtoHTTP2;
21586 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
21587 session_deps_.socket_factory->AddSocketDataProvider(&data1);
21588
21589 std::unique_ptr<HttpNetworkSession> session = CreateSession(&session_deps_);
21590
21591 // Start the first transaction to set up the SpdySession
21592 HttpRequestInfo request1;
21593 request1.method = "GET";
21594 request1.url = GURL(https_url);
21595 request1.load_flags = 0;
21596 request1.traffic_annotation =
21597 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
21598 HttpNetworkTransaction trans1(LOWEST, session.get());
21599 TestCompletionCallback callback1;
21600 int rv = trans1.Start(&request1, callback1.callback(), NetLogWithSource());
21601
21602 // This pause is a hack to avoid running into https://crbug.com/497228.
21603 data1.RunUntilPaused();
21604 base::RunLoop().RunUntilIdle();
21605 data1.Resume();
21606 EXPECT_THAT(callback1.GetResult(rv), IsOk());
21607 EXPECT_TRUE(trans1.GetResponseInfo()->was_fetched_via_spdy);
21608
21609 LoadTimingInfo load_timing_info1;
21610 EXPECT_TRUE(trans1.GetLoadTimingInfo(&load_timing_info1));
21611 TestLoadTimingNotReusedWithPac(load_timing_info1,
21612 CONNECT_TIMING_HAS_SSL_TIMES);
21613
21614 // Now, start the HTTP request.
21615 HttpRequestInfo request2;
21616 request2.method = "GET";
21617 request2.url = GURL(http_url);
21618 request2.load_flags = 0;
21619 request2.traffic_annotation =
21620 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
21621 HttpNetworkTransaction trans2(MEDIUM, session.get());
21622 TestCompletionCallback callback2;
21623 rv = trans2.Start(&request2, callback2.callback(), NetLogWithSource());
21624
21625 // This pause is a hack to avoid running into https://crbug.com/497228.
21626 data1.RunUntilPaused();
21627 base::RunLoop().RunUntilIdle();
21628 data1.Resume();
21629 EXPECT_THAT(callback2.GetResult(rv), IsOk());
21630
21631 EXPECT_TRUE(trans2.GetResponseInfo()->was_fetched_via_spdy);
21632
21633 LoadTimingInfo load_timing_info2;
21634 EXPECT_TRUE(trans2.GetLoadTimingInfo(&load_timing_info2));
21635 // The established SPDY sessions is considered reused by the HTTP request.
21636 TestLoadTimingReusedWithPac(load_timing_info2);
21637 // HTTP requests over a SPDY session should have a different connection
21638 // socket_log_id than requests over a tunnel.
21639 EXPECT_NE(load_timing_info1.socket_log_id, load_timing_info2.socket_log_id);
21640 }
21641
21642 // Test that in the case where we have a SPDY session to a SPDY proxy
21643 // that we do not pool other origins that resolve to the same IP when
21644 // the certificate does not match the new origin.
21645 // http://crbug.com/134690
TEST_P(HttpNetworkTransactionTest,DoNotUseSpdySessionIfCertDoesNotMatch)21646 TEST_P(HttpNetworkTransactionTest, DoNotUseSpdySessionIfCertDoesNotMatch) {
21647 const std::string url1 = "http://www.example.org/";
21648 const std::string url2 = "https://news.example.org/";
21649 const std::string ip_addr = "1.2.3.4";
21650
21651 // Second SpdyTestUtil instance for the second socket.
21652 SpdyTestUtil spdy_util_secure(/*use_priority_header=*/true);
21653
21654 // SPDY GET for HTTP URL (through SPDY proxy)
21655 spdy::Http2HeaderBlock headers(
21656 spdy_util_.ConstructGetHeaderBlockForProxy("http://www.example.org/"));
21657 spdy::SpdySerializedFrame req1(
21658 spdy_util_.ConstructSpdyHeaders(1, std::move(headers), LOWEST, true));
21659
21660 MockWrite writes1[] = {
21661 CreateMockWrite(req1, 0),
21662 };
21663
21664 spdy::SpdySerializedFrame resp1(
21665 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
21666 spdy::SpdySerializedFrame body1(spdy_util_.ConstructSpdyDataFrame(1, true));
21667 MockRead reads1[] = {
21668 MockRead(ASYNC, ERR_IO_PENDING, 1), CreateMockRead(resp1, 2),
21669 CreateMockRead(body1, 3), MockRead(ASYNC, OK, 4), // EOF
21670 };
21671
21672 SequencedSocketData data1(reads1, writes1);
21673 IPAddress ip;
21674 ASSERT_TRUE(ip.AssignFromIPLiteral(ip_addr));
21675 IPEndPoint peer_addr = IPEndPoint(ip, 443);
21676 MockConnect connect_data1(ASYNC, OK, peer_addr);
21677 data1.set_connect_data(connect_data1);
21678
21679 // SPDY GET for HTTPS URL (direct)
21680 spdy::SpdySerializedFrame req2(
21681 spdy_util_secure.ConstructSpdyGet(url2.c_str(), 1, MEDIUM));
21682
21683 MockWrite writes2[] = {
21684 CreateMockWrite(req2, 0),
21685 };
21686
21687 spdy::SpdySerializedFrame resp2(
21688 spdy_util_secure.ConstructSpdyGetReply(nullptr, 0, 1));
21689 spdy::SpdySerializedFrame body2(
21690 spdy_util_secure.ConstructSpdyDataFrame(1, true));
21691 MockRead reads2[] = {CreateMockRead(resp2, 1), CreateMockRead(body2, 2),
21692 MockRead(ASYNC, OK, 3)};
21693
21694 SequencedSocketData data2(reads2, writes2);
21695 MockConnect connect_data2(ASYNC, OK);
21696 data2.set_connect_data(connect_data2);
21697
21698 // Set up a proxy config that sends HTTP requests to a proxy, and
21699 // all others direct.
21700 ProxyConfig proxy_config;
21701 proxy_config.proxy_rules().ParseFromString("http=https://proxy:443");
21702 session_deps_.proxy_resolution_service =
21703 ConfiguredProxyResolutionService::CreateFixedForTest(
21704 ProxyConfigWithAnnotation(proxy_config,
21705 TRAFFIC_ANNOTATION_FOR_TESTS));
21706
21707 SSLSocketDataProvider ssl1(ASYNC, OK); // to the proxy
21708 ssl1.next_proto = kProtoHTTP2;
21709 // Load a valid cert. Note, that this does not need to
21710 // be valid for proxy because the MockSSLClientSocket does
21711 // not actually verify it. But SpdySession will use this
21712 // to see if it is valid for the new origin
21713 ssl1.ssl_info.cert =
21714 ImportCertFromFile(GetTestCertsDirectory(), "ok_cert.pem");
21715 ASSERT_TRUE(ssl1.ssl_info.cert);
21716 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl1);
21717 session_deps_.socket_factory->AddSocketDataProvider(&data1);
21718
21719 SSLSocketDataProvider ssl2(ASYNC, OK); // to the server
21720 ssl2.next_proto = kProtoHTTP2;
21721 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
21722 session_deps_.socket_factory->AddSocketDataProvider(&data2);
21723
21724 session_deps_.host_resolver = std::make_unique<MockCachingHostResolver>();
21725 session_deps_.host_resolver->rules()->AddRule("news.example.org", ip_addr);
21726 session_deps_.host_resolver->rules()->AddRule("proxy", ip_addr);
21727
21728 std::unique_ptr<HttpNetworkSession> session = CreateSession(&session_deps_);
21729
21730 // Start the first transaction to set up the SpdySession
21731 HttpRequestInfo request1;
21732 request1.method = "GET";
21733 request1.url = GURL(url1);
21734 request1.load_flags = 0;
21735 request1.traffic_annotation =
21736 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
21737 HttpNetworkTransaction trans1(LOWEST, session.get());
21738 TestCompletionCallback callback1;
21739 ASSERT_EQ(ERR_IO_PENDING,
21740 trans1.Start(&request1, callback1.callback(), NetLogWithSource()));
21741 // This pause is a hack to avoid running into https://crbug.com/497228.
21742 data1.RunUntilPaused();
21743 base::RunLoop().RunUntilIdle();
21744 data1.Resume();
21745
21746 EXPECT_THAT(callback1.WaitForResult(), IsOk());
21747 EXPECT_TRUE(trans1.GetResponseInfo()->was_fetched_via_spdy);
21748
21749 // Now, start the HTTP request
21750 HttpRequestInfo request2;
21751 request2.method = "GET";
21752 request2.url = GURL(url2);
21753 request2.load_flags = 0;
21754 request2.traffic_annotation =
21755 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
21756 HttpNetworkTransaction trans2(MEDIUM, session.get());
21757 TestCompletionCallback callback2;
21758 EXPECT_EQ(ERR_IO_PENDING,
21759 trans2.Start(&request2, callback2.callback(), NetLogWithSource()));
21760 base::RunLoop().RunUntilIdle();
21761
21762 ASSERT_TRUE(callback2.have_result());
21763 EXPECT_THAT(callback2.WaitForResult(), IsOk());
21764 EXPECT_TRUE(trans2.GetResponseInfo()->was_fetched_via_spdy);
21765 }
21766
21767 // Test to verify that a failed socket read (due to an ERR_CONNECTION_CLOSED
21768 // error) in SPDY session, removes the socket from pool and closes the SPDY
21769 // session. Verify that new url's from the same HttpNetworkSession (and a new
21770 // SpdySession) do work. http://crbug.com/224701
TEST_P(HttpNetworkTransactionTest,ErrorSocketNotConnected)21771 TEST_P(HttpNetworkTransactionTest, ErrorSocketNotConnected) {
21772 const std::string https_url = "https://www.example.org/";
21773
21774 MockRead reads1[] = {MockRead(SYNCHRONOUS, ERR_CONNECTION_CLOSED, 0)};
21775
21776 SequencedSocketData data1(reads1, base::span<MockWrite>());
21777
21778 spdy::SpdySerializedFrame req2(
21779 spdy_util_.ConstructSpdyGet(https_url.c_str(), 1, MEDIUM));
21780 MockWrite writes2[] = {
21781 CreateMockWrite(req2, 0),
21782 };
21783
21784 spdy::SpdySerializedFrame resp2(
21785 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
21786 spdy::SpdySerializedFrame body2(spdy_util_.ConstructSpdyDataFrame(1, true));
21787 MockRead reads2[] = {
21788 CreateMockRead(resp2, 1), CreateMockRead(body2, 2),
21789 MockRead(ASYNC, OK, 3) // EOF
21790 };
21791
21792 SequencedSocketData data2(reads2, writes2);
21793
21794 SSLSocketDataProvider ssl1(ASYNC, OK);
21795 ssl1.next_proto = kProtoHTTP2;
21796 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl1);
21797 session_deps_.socket_factory->AddSocketDataProvider(&data1);
21798
21799 SSLSocketDataProvider ssl2(ASYNC, OK);
21800 ssl2.next_proto = kProtoHTTP2;
21801 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
21802 session_deps_.socket_factory->AddSocketDataProvider(&data2);
21803
21804 std::unique_ptr<HttpNetworkSession> session(
21805 SpdySessionDependencies::SpdyCreateSession(&session_deps_));
21806
21807 // Start the first transaction to set up the SpdySession and verify that
21808 // connection was closed.
21809 HttpRequestInfo request1;
21810 request1.method = "GET";
21811 request1.url = GURL(https_url);
21812 request1.load_flags = 0;
21813 request1.traffic_annotation =
21814 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
21815 HttpNetworkTransaction trans1(MEDIUM, session.get());
21816 TestCompletionCallback callback1;
21817 EXPECT_EQ(ERR_IO_PENDING,
21818 trans1.Start(&request1, callback1.callback(), NetLogWithSource()));
21819 EXPECT_THAT(callback1.WaitForResult(), IsError(ERR_CONNECTION_CLOSED));
21820
21821 // Now, start the second request and make sure it succeeds.
21822 HttpRequestInfo request2;
21823 request2.method = "GET";
21824 request2.url = GURL(https_url);
21825 request2.load_flags = 0;
21826 request2.traffic_annotation =
21827 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
21828 HttpNetworkTransaction trans2(MEDIUM, session.get());
21829 TestCompletionCallback callback2;
21830 EXPECT_EQ(ERR_IO_PENDING,
21831 trans2.Start(&request2, callback2.callback(), NetLogWithSource()));
21832
21833 ASSERT_THAT(callback2.WaitForResult(), IsOk());
21834 EXPECT_TRUE(trans2.GetResponseInfo()->was_fetched_via_spdy);
21835 }
21836
TEST_P(HttpNetworkTransactionTest,CloseIdleSpdySessionToOpenNewOne)21837 TEST_P(HttpNetworkTransactionTest, CloseIdleSpdySessionToOpenNewOne) {
21838 ClientSocketPoolManager::set_max_sockets_per_group(
21839 HttpNetworkSession::NORMAL_SOCKET_POOL, 1);
21840 ClientSocketPoolManager::set_max_sockets_per_pool(
21841 HttpNetworkSession::NORMAL_SOCKET_POOL, 1);
21842
21843 // Use two different hosts with different IPs so they don't get pooled.
21844 session_deps_.host_resolver->rules()->AddRule("www.a.com", "10.0.0.1");
21845 session_deps_.host_resolver->rules()->AddRule("www.b.com", "10.0.0.2");
21846 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
21847
21848 SSLSocketDataProvider ssl1(ASYNC, OK);
21849 ssl1.next_proto = kProtoHTTP2;
21850 SSLSocketDataProvider ssl2(ASYNC, OK);
21851 ssl2.next_proto = kProtoHTTP2;
21852 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl1);
21853 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
21854
21855 spdy::SpdySerializedFrame host1_req(
21856 spdy_util_.ConstructSpdyGet("https://www.a.com", 1, DEFAULT_PRIORITY));
21857 MockWrite spdy1_writes[] = {
21858 CreateMockWrite(host1_req, 0),
21859 };
21860 spdy::SpdySerializedFrame host1_resp(
21861 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
21862 spdy::SpdySerializedFrame host1_resp_body(
21863 spdy_util_.ConstructSpdyDataFrame(1, true));
21864 MockRead spdy1_reads[] = {
21865 CreateMockRead(host1_resp, 1),
21866 CreateMockRead(host1_resp_body, 2),
21867 MockRead(SYNCHRONOUS, ERR_IO_PENDING, 3),
21868 };
21869
21870 // Use a separate test instance for the separate SpdySession that will be
21871 // created.
21872 SpdyTestUtil spdy_util_2(/*use_priority_header=*/true);
21873 SequencedSocketData spdy1_data(spdy1_reads, spdy1_writes);
21874 session_deps_.socket_factory->AddSocketDataProvider(&spdy1_data);
21875
21876 spdy::SpdySerializedFrame host2_req(
21877 spdy_util_2.ConstructSpdyGet("https://www.b.com", 1, DEFAULT_PRIORITY));
21878 MockWrite spdy2_writes[] = {
21879 CreateMockWrite(host2_req, 0),
21880 };
21881 spdy::SpdySerializedFrame host2_resp(
21882 spdy_util_2.ConstructSpdyGetReply(nullptr, 0, 1));
21883 spdy::SpdySerializedFrame host2_resp_body(
21884 spdy_util_2.ConstructSpdyDataFrame(1, true));
21885 MockRead spdy2_reads[] = {
21886 CreateMockRead(host2_resp, 1),
21887 CreateMockRead(host2_resp_body, 2),
21888 MockRead(SYNCHRONOUS, ERR_IO_PENDING, 3),
21889 };
21890
21891 SequencedSocketData spdy2_data(spdy2_reads, spdy2_writes);
21892 session_deps_.socket_factory->AddSocketDataProvider(&spdy2_data);
21893
21894 MockWrite http_write[] = {
21895 MockWrite("GET / HTTP/1.1\r\n"
21896 "Host: www.a.com\r\n"
21897 "Connection: keep-alive\r\n\r\n"),
21898 };
21899
21900 MockRead http_read[] = {
21901 MockRead("HTTP/1.1 200 OK\r\n"),
21902 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
21903 MockRead("Content-Length: 6\r\n\r\n"),
21904 MockRead("hello!"),
21905 };
21906 StaticSocketDataProvider http_data(http_read, http_write);
21907 session_deps_.socket_factory->AddSocketDataProvider(&http_data);
21908
21909 HostPortPair host_port_pair_a("www.a.com", 443);
21910 SpdySessionKey spdy_session_key_a(
21911 host_port_pair_a, PRIVACY_MODE_DISABLED, ProxyChain::Direct(),
21912 SessionUsage::kDestination, SocketTag(), NetworkAnonymizationKey(),
21913 SecureDnsPolicy::kAllow,
21914 /*disable_cert_verification_network_fetches=*/false);
21915 EXPECT_FALSE(
21916 HasSpdySession(session->spdy_session_pool(), spdy_session_key_a));
21917
21918 TestCompletionCallback callback;
21919 HttpRequestInfo request1;
21920 request1.method = "GET";
21921 request1.url = GURL("https://www.a.com/");
21922 request1.load_flags = 0;
21923 request1.traffic_annotation =
21924 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
21925 auto trans =
21926 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
21927
21928 int rv = trans->Start(&request1, callback.callback(), NetLogWithSource());
21929 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
21930 EXPECT_THAT(callback.WaitForResult(), IsOk());
21931
21932 const HttpResponseInfo* response = trans->GetResponseInfo();
21933 ASSERT_TRUE(response);
21934 ASSERT_TRUE(response->headers);
21935 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
21936 EXPECT_TRUE(response->was_fetched_via_spdy);
21937 EXPECT_TRUE(response->was_alpn_negotiated);
21938
21939 std::string response_data;
21940 ASSERT_THAT(ReadTransaction(trans.get(), &response_data), IsOk());
21941 EXPECT_EQ("hello!", response_data);
21942 trans.reset();
21943 EXPECT_TRUE(HasSpdySession(session->spdy_session_pool(), spdy_session_key_a));
21944
21945 HostPortPair host_port_pair_b("www.b.com", 443);
21946 SpdySessionKey spdy_session_key_b(
21947 host_port_pair_b, PRIVACY_MODE_DISABLED, ProxyChain::Direct(),
21948 SessionUsage::kDestination, SocketTag(), NetworkAnonymizationKey(),
21949 SecureDnsPolicy::kAllow,
21950 /*disable_cert_verification_network_fetches=*/false);
21951 EXPECT_FALSE(
21952 HasSpdySession(session->spdy_session_pool(), spdy_session_key_b));
21953 HttpRequestInfo request2;
21954 request2.method = "GET";
21955 request2.url = GURL("https://www.b.com/");
21956 request2.load_flags = 0;
21957 request2.traffic_annotation =
21958 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
21959 trans =
21960 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
21961
21962 rv = trans->Start(&request2, callback.callback(), NetLogWithSource());
21963 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
21964 EXPECT_THAT(callback.WaitForResult(), IsOk());
21965
21966 response = trans->GetResponseInfo();
21967 ASSERT_TRUE(response);
21968 ASSERT_TRUE(response->headers);
21969 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
21970 EXPECT_TRUE(response->was_fetched_via_spdy);
21971 EXPECT_TRUE(response->was_alpn_negotiated);
21972 ASSERT_THAT(ReadTransaction(trans.get(), &response_data), IsOk());
21973 EXPECT_EQ("hello!", response_data);
21974 EXPECT_FALSE(
21975 HasSpdySession(session->spdy_session_pool(), spdy_session_key_a));
21976 EXPECT_TRUE(HasSpdySession(session->spdy_session_pool(), spdy_session_key_b));
21977
21978 HostPortPair host_port_pair_a1("www.a.com", 80);
21979 SpdySessionKey spdy_session_key_a1(
21980 host_port_pair_a1, PRIVACY_MODE_DISABLED, ProxyChain::Direct(),
21981 SessionUsage::kDestination, SocketTag(), NetworkAnonymizationKey(),
21982 SecureDnsPolicy::kAllow,
21983 /*disable_cert_verification_network_fetches=*/false);
21984 EXPECT_FALSE(
21985 HasSpdySession(session->spdy_session_pool(), spdy_session_key_a1));
21986 HttpRequestInfo request3;
21987 request3.method = "GET";
21988 request3.url = GURL("http://www.a.com/");
21989 request3.load_flags = 0;
21990 request3.traffic_annotation =
21991 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
21992 trans =
21993 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
21994
21995 rv = trans->Start(&request3, callback.callback(), NetLogWithSource());
21996 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
21997 EXPECT_THAT(callback.WaitForResult(), IsOk());
21998
21999 response = trans->GetResponseInfo();
22000 ASSERT_TRUE(response);
22001 ASSERT_TRUE(response->headers);
22002 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
22003 EXPECT_FALSE(response->was_fetched_via_spdy);
22004 EXPECT_FALSE(response->was_alpn_negotiated);
22005 ASSERT_THAT(ReadTransaction(trans.get(), &response_data), IsOk());
22006 EXPECT_EQ("hello!", response_data);
22007 EXPECT_FALSE(
22008 HasSpdySession(session->spdy_session_pool(), spdy_session_key_a));
22009 EXPECT_FALSE(
22010 HasSpdySession(session->spdy_session_pool(), spdy_session_key_b));
22011 }
22012
TEST_P(HttpNetworkTransactionTest,HttpSyncConnectError)22013 TEST_P(HttpNetworkTransactionTest, HttpSyncConnectError) {
22014 HttpRequestInfo request;
22015 request.method = "GET";
22016 request.url = GURL("http://www.example.org/");
22017 request.traffic_annotation =
22018 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
22019
22020 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
22021 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
22022
22023 MockConnect mock_connect(SYNCHRONOUS, ERR_NAME_NOT_RESOLVED);
22024 StaticSocketDataProvider data;
22025 data.set_connect_data(mock_connect);
22026 session_deps_.socket_factory->AddSocketDataProvider(&data);
22027
22028 TestCompletionCallback callback;
22029
22030 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
22031 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
22032
22033 rv = callback.WaitForResult();
22034 EXPECT_THAT(rv, IsError(ERR_NAME_NOT_RESOLVED));
22035
22036 ConnectionAttempts attempts = trans.GetConnectionAttempts();
22037 ASSERT_EQ(1u, attempts.size());
22038 EXPECT_THAT(attempts[0].result, IsError(ERR_NAME_NOT_RESOLVED));
22039
22040 IPEndPoint endpoint;
22041 EXPECT_FALSE(trans.GetRemoteEndpoint(&endpoint));
22042 EXPECT_TRUE(endpoint.address().empty());
22043 }
22044
TEST_P(HttpNetworkTransactionTest,HttpAsyncConnectError)22045 TEST_P(HttpNetworkTransactionTest, HttpAsyncConnectError) {
22046 HttpRequestInfo request;
22047 request.method = "GET";
22048 request.url = GURL("http://www.example.org/");
22049 request.traffic_annotation =
22050 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
22051
22052 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
22053 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
22054
22055 MockConnect mock_connect(ASYNC, ERR_NAME_NOT_RESOLVED);
22056 StaticSocketDataProvider data;
22057 data.set_connect_data(mock_connect);
22058 session_deps_.socket_factory->AddSocketDataProvider(&data);
22059
22060 TestCompletionCallback callback;
22061
22062 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
22063 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
22064
22065 rv = callback.WaitForResult();
22066 EXPECT_THAT(rv, IsError(ERR_NAME_NOT_RESOLVED));
22067
22068 ConnectionAttempts attempts = trans.GetConnectionAttempts();
22069 ASSERT_EQ(1u, attempts.size());
22070 EXPECT_THAT(attempts[0].result, IsError(ERR_NAME_NOT_RESOLVED));
22071
22072 IPEndPoint endpoint;
22073 EXPECT_FALSE(trans.GetRemoteEndpoint(&endpoint));
22074 EXPECT_TRUE(endpoint.address().empty());
22075 }
22076
TEST_P(HttpNetworkTransactionTest,HttpSyncWriteError)22077 TEST_P(HttpNetworkTransactionTest, HttpSyncWriteError) {
22078 HttpRequestInfo request;
22079 request.method = "GET";
22080 request.url = GURL("http://www.example.org/");
22081 request.traffic_annotation =
22082 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
22083
22084 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
22085 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
22086
22087 MockWrite data_writes[] = {
22088 MockWrite(SYNCHRONOUS, ERR_CONNECTION_RESET),
22089 };
22090 MockRead data_reads[] = {
22091 MockRead(SYNCHRONOUS, ERR_UNEXPECTED), // Should not be reached.
22092 };
22093
22094 StaticSocketDataProvider data(data_reads, data_writes);
22095 session_deps_.socket_factory->AddSocketDataProvider(&data);
22096
22097 TestCompletionCallback callback;
22098
22099 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
22100 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
22101
22102 rv = callback.WaitForResult();
22103 EXPECT_THAT(rv, IsError(ERR_CONNECTION_RESET));
22104 }
22105
TEST_P(HttpNetworkTransactionTest,HttpAsyncWriteError)22106 TEST_P(HttpNetworkTransactionTest, HttpAsyncWriteError) {
22107 HttpRequestInfo request;
22108 request.method = "GET";
22109 request.url = GURL("http://www.example.org/");
22110 request.traffic_annotation =
22111 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
22112
22113 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
22114 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
22115
22116 MockWrite data_writes[] = {
22117 MockWrite(ASYNC, ERR_CONNECTION_RESET),
22118 };
22119 MockRead data_reads[] = {
22120 MockRead(SYNCHRONOUS, ERR_UNEXPECTED), // Should not be reached.
22121 };
22122
22123 StaticSocketDataProvider data(data_reads, data_writes);
22124 session_deps_.socket_factory->AddSocketDataProvider(&data);
22125
22126 TestCompletionCallback callback;
22127
22128 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
22129 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
22130
22131 rv = callback.WaitForResult();
22132 EXPECT_THAT(rv, IsError(ERR_CONNECTION_RESET));
22133 }
22134
TEST_P(HttpNetworkTransactionTest,HttpSyncReadError)22135 TEST_P(HttpNetworkTransactionTest, HttpSyncReadError) {
22136 HttpRequestInfo request;
22137 request.method = "GET";
22138 request.url = GURL("http://www.example.org/");
22139 request.traffic_annotation =
22140 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
22141
22142 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
22143 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
22144
22145 MockWrite data_writes[] = {
22146 MockWrite("GET / HTTP/1.1\r\n"
22147 "Host: www.example.org\r\n"
22148 "Connection: keep-alive\r\n\r\n"),
22149 };
22150 MockRead data_reads[] = {
22151 MockRead(SYNCHRONOUS, ERR_CONNECTION_RESET),
22152 };
22153
22154 StaticSocketDataProvider data(data_reads, data_writes);
22155 session_deps_.socket_factory->AddSocketDataProvider(&data);
22156
22157 TestCompletionCallback callback;
22158
22159 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
22160 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
22161
22162 rv = callback.WaitForResult();
22163 EXPECT_THAT(rv, IsError(ERR_CONNECTION_RESET));
22164 }
22165
TEST_P(HttpNetworkTransactionTest,HttpAsyncReadError)22166 TEST_P(HttpNetworkTransactionTest, HttpAsyncReadError) {
22167 HttpRequestInfo request;
22168 request.method = "GET";
22169 request.url = GURL("http://www.example.org/");
22170 request.traffic_annotation =
22171 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
22172
22173 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
22174 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
22175
22176 MockWrite data_writes[] = {
22177 MockWrite("GET / HTTP/1.1\r\n"
22178 "Host: www.example.org\r\n"
22179 "Connection: keep-alive\r\n\r\n"),
22180 };
22181 MockRead data_reads[] = {
22182 MockRead(ASYNC, ERR_CONNECTION_RESET),
22183 };
22184
22185 StaticSocketDataProvider data(data_reads, data_writes);
22186 session_deps_.socket_factory->AddSocketDataProvider(&data);
22187
22188 TestCompletionCallback callback;
22189
22190 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
22191 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
22192
22193 rv = callback.WaitForResult();
22194 EXPECT_THAT(rv, IsError(ERR_CONNECTION_RESET));
22195 }
22196
22197 // Tests that when a used socket is returned to the SSL socket pool, it's closed
22198 // if the transport socket pool is stalled on the global socket limit.
TEST_P(HttpNetworkTransactionTest,CloseSSLSocketOnIdleForHttpRequest)22199 TEST_P(HttpNetworkTransactionTest, CloseSSLSocketOnIdleForHttpRequest) {
22200 ClientSocketPoolManager::set_max_sockets_per_group(
22201 HttpNetworkSession::NORMAL_SOCKET_POOL, 1);
22202 ClientSocketPoolManager::set_max_sockets_per_pool(
22203 HttpNetworkSession::NORMAL_SOCKET_POOL, 1);
22204
22205 // Set up SSL request.
22206
22207 HttpRequestInfo ssl_request;
22208 ssl_request.method = "GET";
22209 ssl_request.url = GURL("https://www.example.org/");
22210 ssl_request.traffic_annotation =
22211 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
22212
22213 MockWrite ssl_writes[] = {
22214 MockWrite("GET / HTTP/1.1\r\n"
22215 "Host: www.example.org\r\n"
22216 "Connection: keep-alive\r\n\r\n"),
22217 };
22218 MockRead ssl_reads[] = {
22219 MockRead("HTTP/1.1 200 OK\r\n"),
22220 MockRead("Content-Length: 11\r\n\r\n"),
22221 MockRead("hello world"),
22222 MockRead(SYNCHRONOUS, OK),
22223 };
22224 StaticSocketDataProvider ssl_data(ssl_reads, ssl_writes);
22225 session_deps_.socket_factory->AddSocketDataProvider(&ssl_data);
22226
22227 SSLSocketDataProvider ssl(ASYNC, OK);
22228 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
22229
22230 // Set up HTTP request.
22231
22232 HttpRequestInfo http_request;
22233 http_request.method = "GET";
22234 http_request.url = GURL("http://www.example.org/");
22235 http_request.traffic_annotation =
22236 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
22237
22238 MockWrite http_writes[] = {
22239 MockWrite("GET / HTTP/1.1\r\n"
22240 "Host: www.example.org\r\n"
22241 "Connection: keep-alive\r\n\r\n"),
22242 };
22243 MockRead http_reads[] = {
22244 MockRead("HTTP/1.1 200 OK\r\n"),
22245 MockRead("Content-Length: 7\r\n\r\n"),
22246 MockRead("falafel"),
22247 MockRead(SYNCHRONOUS, OK),
22248 };
22249 StaticSocketDataProvider http_data(http_reads, http_writes);
22250 session_deps_.socket_factory->AddSocketDataProvider(&http_data);
22251
22252 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
22253
22254 // Start the SSL request.
22255 TestCompletionCallback ssl_callback;
22256 HttpNetworkTransaction ssl_trans(DEFAULT_PRIORITY, session.get());
22257 ASSERT_EQ(ERR_IO_PENDING,
22258 ssl_trans.Start(&ssl_request, ssl_callback.callback(),
22259 NetLogWithSource()));
22260
22261 // Start the HTTP request. Pool should stall.
22262 TestCompletionCallback http_callback;
22263 HttpNetworkTransaction http_trans(DEFAULT_PRIORITY, session.get());
22264 ASSERT_EQ(ERR_IO_PENDING,
22265 http_trans.Start(&http_request, http_callback.callback(),
22266 NetLogWithSource()));
22267 EXPECT_TRUE(IsTransportSocketPoolStalled(session.get()));
22268
22269 // Wait for response from SSL request.
22270 ASSERT_THAT(ssl_callback.WaitForResult(), IsOk());
22271 std::string response_data;
22272 ASSERT_THAT(ReadTransaction(&ssl_trans, &response_data), IsOk());
22273 EXPECT_EQ("hello world", response_data);
22274
22275 // The SSL socket should automatically be closed, so the HTTP request can
22276 // start.
22277 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
22278 ASSERT_FALSE(IsTransportSocketPoolStalled(session.get()));
22279
22280 // The HTTP request can now complete.
22281 ASSERT_THAT(http_callback.WaitForResult(), IsOk());
22282 ASSERT_THAT(ReadTransaction(&http_trans, &response_data), IsOk());
22283 EXPECT_EQ("falafel", response_data);
22284
22285 EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session.get()));
22286 }
22287
22288 // Tests that when a SSL connection is established but there's no corresponding
22289 // request that needs it, the new socket is closed if the transport socket pool
22290 // is stalled on the global socket limit.
TEST_P(HttpNetworkTransactionTest,CloseSSLSocketOnIdleForHttpRequest2)22291 TEST_P(HttpNetworkTransactionTest, CloseSSLSocketOnIdleForHttpRequest2) {
22292 ClientSocketPoolManager::set_max_sockets_per_group(
22293 HttpNetworkSession::NORMAL_SOCKET_POOL, 1);
22294 ClientSocketPoolManager::set_max_sockets_per_pool(
22295 HttpNetworkSession::NORMAL_SOCKET_POOL, 1);
22296
22297 // Set up an ssl request.
22298
22299 HttpRequestInfo ssl_request;
22300 ssl_request.method = "GET";
22301 ssl_request.url = GURL("https://www.foopy.com/");
22302 ssl_request.traffic_annotation =
22303 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
22304
22305 // No data will be sent on the SSL socket.
22306 StaticSocketDataProvider ssl_data;
22307 session_deps_.socket_factory->AddSocketDataProvider(&ssl_data);
22308
22309 SSLSocketDataProvider ssl(ASYNC, OK);
22310 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
22311
22312 // Set up HTTP request.
22313
22314 HttpRequestInfo http_request;
22315 http_request.method = "GET";
22316 http_request.url = GURL("http://www.example.org/");
22317 http_request.traffic_annotation =
22318 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
22319
22320 MockWrite http_writes[] = {
22321 MockWrite("GET / HTTP/1.1\r\n"
22322 "Host: www.example.org\r\n"
22323 "Connection: keep-alive\r\n\r\n"),
22324 };
22325 MockRead http_reads[] = {
22326 MockRead("HTTP/1.1 200 OK\r\n"),
22327 MockRead("Content-Length: 7\r\n\r\n"),
22328 MockRead("falafel"),
22329 MockRead(SYNCHRONOUS, OK),
22330 };
22331 StaticSocketDataProvider http_data(http_reads, http_writes);
22332 session_deps_.socket_factory->AddSocketDataProvider(&http_data);
22333
22334 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
22335
22336 // Preconnect an SSL socket. A preconnect is needed because connect jobs are
22337 // cancelled when a normal transaction is cancelled.
22338 HttpStreamFactory* http_stream_factory = session->http_stream_factory();
22339 http_stream_factory->PreconnectStreams(1, ssl_request);
22340 EXPECT_EQ(0, GetIdleSocketCountInTransportSocketPool(session.get()));
22341
22342 // Start the HTTP request. Pool should stall.
22343 TestCompletionCallback http_callback;
22344 HttpNetworkTransaction http_trans(DEFAULT_PRIORITY, session.get());
22345 ASSERT_EQ(ERR_IO_PENDING,
22346 http_trans.Start(&http_request, http_callback.callback(),
22347 NetLogWithSource()));
22348 EXPECT_TRUE(IsTransportSocketPoolStalled(session.get()));
22349
22350 // The SSL connection will automatically be closed once the connection is
22351 // established, to let the HTTP request start.
22352 ASSERT_THAT(http_callback.WaitForResult(), IsOk());
22353 std::string response_data;
22354 ASSERT_THAT(ReadTransaction(&http_trans, &response_data), IsOk());
22355 EXPECT_EQ("falafel", response_data);
22356
22357 EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session.get()));
22358 }
22359
TEST_P(HttpNetworkTransactionTest,PostReadsErrorResponseAfterReset)22360 TEST_P(HttpNetworkTransactionTest, PostReadsErrorResponseAfterReset) {
22361 std::vector<std::unique_ptr<UploadElementReader>> element_readers;
22362 element_readers.push_back(
22363 std::make_unique<UploadBytesElementReader>("foo", 3));
22364 ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0);
22365
22366 HttpRequestInfo request;
22367 request.method = "POST";
22368 request.url = GURL("http://www.foo.com/");
22369 request.upload_data_stream = &upload_data_stream;
22370 request.traffic_annotation =
22371 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
22372
22373 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
22374 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
22375 // Send headers successfully, but get an error while sending the body.
22376 MockWrite data_writes[] = {
22377 MockWrite("POST / HTTP/1.1\r\n"
22378 "Host: www.foo.com\r\n"
22379 "Connection: keep-alive\r\n"
22380 "Content-Length: 3\r\n\r\n"),
22381 MockWrite(SYNCHRONOUS, ERR_CONNECTION_RESET),
22382 };
22383
22384 MockRead data_reads[] = {
22385 MockRead("HTTP/1.0 400 Not OK\r\n\r\n"),
22386 MockRead("hello world"),
22387 MockRead(SYNCHRONOUS, OK),
22388 };
22389 StaticSocketDataProvider data(data_reads, data_writes);
22390 session_deps_.socket_factory->AddSocketDataProvider(&data);
22391
22392 TestCompletionCallback callback;
22393
22394 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
22395 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
22396
22397 rv = callback.WaitForResult();
22398 EXPECT_THAT(rv, IsOk());
22399
22400 const HttpResponseInfo* response = trans.GetResponseInfo();
22401 ASSERT_TRUE(response);
22402
22403 EXPECT_TRUE(response->headers);
22404 EXPECT_EQ("HTTP/1.0 400 Not OK", response->headers->GetStatusLine());
22405
22406 std::string response_data;
22407 rv = ReadTransaction(&trans, &response_data);
22408 EXPECT_THAT(rv, IsOk());
22409 EXPECT_EQ("hello world", response_data);
22410 }
22411
22412 // This test makes sure the retry logic doesn't trigger when reading an error
22413 // response from a server that rejected a POST with a CONNECTION_RESET.
TEST_P(HttpNetworkTransactionTest,PostReadsErrorResponseAfterResetOnReusedSocket)22414 TEST_P(HttpNetworkTransactionTest,
22415 PostReadsErrorResponseAfterResetOnReusedSocket) {
22416 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
22417 MockWrite data_writes[] = {
22418 MockWrite("GET / HTTP/1.1\r\n"
22419 "Host: www.foo.com\r\n"
22420 "Connection: keep-alive\r\n\r\n"),
22421 MockWrite("POST / HTTP/1.1\r\n"
22422 "Host: www.foo.com\r\n"
22423 "Connection: keep-alive\r\n"
22424 "Content-Length: 3\r\n\r\n"),
22425 MockWrite(SYNCHRONOUS, ERR_CONNECTION_RESET),
22426 };
22427
22428 MockRead data_reads[] = {
22429 MockRead("HTTP/1.1 200 Peachy\r\n"
22430 "Content-Length: 14\r\n\r\n"),
22431 MockRead("first response"),
22432 MockRead("HTTP/1.1 400 Not OK\r\n"
22433 "Content-Length: 15\r\n\r\n"),
22434 MockRead("second response"),
22435 MockRead(SYNCHRONOUS, OK),
22436 };
22437 StaticSocketDataProvider data(data_reads, data_writes);
22438 session_deps_.socket_factory->AddSocketDataProvider(&data);
22439
22440 TestCompletionCallback callback;
22441 HttpRequestInfo request1;
22442 request1.method = "GET";
22443 request1.url = GURL("http://www.foo.com/");
22444 request1.load_flags = 0;
22445 request1.traffic_annotation =
22446 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
22447
22448 auto trans1 =
22449 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
22450 int rv = trans1->Start(&request1, callback.callback(), NetLogWithSource());
22451 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
22452
22453 rv = callback.WaitForResult();
22454 EXPECT_THAT(rv, IsOk());
22455
22456 const HttpResponseInfo* response1 = trans1->GetResponseInfo();
22457 ASSERT_TRUE(response1);
22458
22459 EXPECT_TRUE(response1->headers);
22460 EXPECT_EQ("HTTP/1.1 200 Peachy", response1->headers->GetStatusLine());
22461
22462 std::string response_data1;
22463 rv = ReadTransaction(trans1.get(), &response_data1);
22464 EXPECT_THAT(rv, IsOk());
22465 EXPECT_EQ("first response", response_data1);
22466 // Delete the transaction to release the socket back into the socket pool.
22467 trans1.reset();
22468
22469 std::vector<std::unique_ptr<UploadElementReader>> element_readers;
22470 element_readers.push_back(
22471 std::make_unique<UploadBytesElementReader>("foo", 3));
22472 ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0);
22473
22474 HttpRequestInfo request2;
22475 request2.method = "POST";
22476 request2.url = GURL("http://www.foo.com/");
22477 request2.upload_data_stream = &upload_data_stream;
22478 request2.load_flags = 0;
22479 request2.traffic_annotation =
22480 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
22481
22482 HttpNetworkTransaction trans2(DEFAULT_PRIORITY, session.get());
22483 rv = trans2.Start(&request2, callback.callback(), NetLogWithSource());
22484 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
22485
22486 rv = callback.WaitForResult();
22487 EXPECT_THAT(rv, IsOk());
22488
22489 const HttpResponseInfo* response2 = trans2.GetResponseInfo();
22490 ASSERT_TRUE(response2);
22491
22492 EXPECT_TRUE(response2->headers);
22493 EXPECT_EQ("HTTP/1.1 400 Not OK", response2->headers->GetStatusLine());
22494
22495 std::string response_data2;
22496 rv = ReadTransaction(&trans2, &response_data2);
22497 EXPECT_THAT(rv, IsOk());
22498 EXPECT_EQ("second response", response_data2);
22499 }
22500
TEST_P(HttpNetworkTransactionTest,PostReadsErrorResponseAfterResetPartialBodySent)22501 TEST_P(HttpNetworkTransactionTest,
22502 PostReadsErrorResponseAfterResetPartialBodySent) {
22503 std::vector<std::unique_ptr<UploadElementReader>> element_readers;
22504 element_readers.push_back(
22505 std::make_unique<UploadBytesElementReader>("foo", 3));
22506 ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0);
22507
22508 HttpRequestInfo request;
22509 request.method = "POST";
22510 request.url = GURL("http://www.foo.com/");
22511 request.upload_data_stream = &upload_data_stream;
22512 request.traffic_annotation =
22513 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
22514
22515 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
22516 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
22517 // Send headers successfully, but get an error while sending the body.
22518 MockWrite data_writes[] = {
22519 MockWrite("POST / HTTP/1.1\r\n"
22520 "Host: www.foo.com\r\n"
22521 "Connection: keep-alive\r\n"
22522 "Content-Length: 3\r\n\r\n"
22523 "fo"),
22524 MockWrite(SYNCHRONOUS, ERR_CONNECTION_RESET),
22525 };
22526
22527 MockRead data_reads[] = {
22528 MockRead("HTTP/1.0 400 Not OK\r\n\r\n"),
22529 MockRead("hello world"),
22530 MockRead(SYNCHRONOUS, OK),
22531 };
22532 StaticSocketDataProvider data(data_reads, data_writes);
22533 session_deps_.socket_factory->AddSocketDataProvider(&data);
22534
22535 TestCompletionCallback callback;
22536
22537 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
22538 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
22539
22540 rv = callback.WaitForResult();
22541 EXPECT_THAT(rv, IsOk());
22542
22543 const HttpResponseInfo* response = trans.GetResponseInfo();
22544 ASSERT_TRUE(response);
22545
22546 EXPECT_TRUE(response->headers);
22547 EXPECT_EQ("HTTP/1.0 400 Not OK", response->headers->GetStatusLine());
22548
22549 std::string response_data;
22550 rv = ReadTransaction(&trans, &response_data);
22551 EXPECT_THAT(rv, IsOk());
22552 EXPECT_EQ("hello world", response_data);
22553 }
22554
22555 // This tests the more common case than the previous test, where headers and
22556 // body are not merged into a single request.
TEST_P(HttpNetworkTransactionTest,ChunkedPostReadsErrorResponseAfterReset)22557 TEST_P(HttpNetworkTransactionTest, ChunkedPostReadsErrorResponseAfterReset) {
22558 ChunkedUploadDataStream upload_data_stream(0);
22559
22560 HttpRequestInfo request;
22561 request.method = "POST";
22562 request.url = GURL("http://www.foo.com/");
22563 request.upload_data_stream = &upload_data_stream;
22564 request.traffic_annotation =
22565 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
22566
22567 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
22568 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
22569 // Send headers successfully, but get an error while sending the body.
22570 MockWrite data_writes[] = {
22571 MockWrite("POST / HTTP/1.1\r\n"
22572 "Host: www.foo.com\r\n"
22573 "Connection: keep-alive\r\n"
22574 "Transfer-Encoding: chunked\r\n\r\n"),
22575 MockWrite(SYNCHRONOUS, ERR_CONNECTION_RESET),
22576 };
22577
22578 MockRead data_reads[] = {
22579 MockRead("HTTP/1.0 400 Not OK\r\n\r\n"),
22580 MockRead("hello world"),
22581 MockRead(SYNCHRONOUS, OK),
22582 };
22583 StaticSocketDataProvider data(data_reads, data_writes);
22584 session_deps_.socket_factory->AddSocketDataProvider(&data);
22585
22586 TestCompletionCallback callback;
22587
22588 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
22589 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
22590 // Make sure the headers are sent before adding a chunk. This ensures that
22591 // they can't be merged with the body in a single send. Not currently
22592 // necessary since a chunked body is never merged with headers, but this makes
22593 // the test more future proof.
22594 base::RunLoop().RunUntilIdle();
22595
22596 upload_data_stream.AppendData("last chunk", 10, true);
22597
22598 rv = callback.WaitForResult();
22599 EXPECT_THAT(rv, IsOk());
22600
22601 const HttpResponseInfo* response = trans.GetResponseInfo();
22602 ASSERT_TRUE(response);
22603
22604 EXPECT_TRUE(response->headers);
22605 EXPECT_EQ("HTTP/1.0 400 Not OK", response->headers->GetStatusLine());
22606
22607 std::string response_data;
22608 rv = ReadTransaction(&trans, &response_data);
22609 EXPECT_THAT(rv, IsOk());
22610 EXPECT_EQ("hello world", response_data);
22611 }
22612
TEST_P(HttpNetworkTransactionTest,PostReadsErrorResponseAfterResetAnd100)22613 TEST_P(HttpNetworkTransactionTest, PostReadsErrorResponseAfterResetAnd100) {
22614 std::vector<std::unique_ptr<UploadElementReader>> element_readers;
22615 element_readers.push_back(
22616 std::make_unique<UploadBytesElementReader>("foo", 3));
22617 ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0);
22618
22619 HttpRequestInfo request;
22620 request.method = "POST";
22621 request.url = GURL("http://www.foo.com/");
22622 request.upload_data_stream = &upload_data_stream;
22623 request.traffic_annotation =
22624 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
22625
22626 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
22627 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
22628
22629 MockWrite data_writes[] = {
22630 MockWrite("POST / HTTP/1.1\r\n"
22631 "Host: www.foo.com\r\n"
22632 "Connection: keep-alive\r\n"
22633 "Content-Length: 3\r\n\r\n"),
22634 MockWrite(SYNCHRONOUS, ERR_CONNECTION_RESET),
22635 };
22636
22637 MockRead data_reads[] = {
22638 MockRead("HTTP/1.0 100 Continue\r\n\r\n"),
22639 MockRead("HTTP/1.0 400 Not OK\r\n\r\n"),
22640 MockRead("hello world"),
22641 MockRead(SYNCHRONOUS, OK),
22642 };
22643 StaticSocketDataProvider data(data_reads, data_writes);
22644 session_deps_.socket_factory->AddSocketDataProvider(&data);
22645
22646 TestCompletionCallback callback;
22647
22648 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
22649 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
22650
22651 rv = callback.WaitForResult();
22652 EXPECT_THAT(rv, IsOk());
22653
22654 const HttpResponseInfo* response = trans.GetResponseInfo();
22655 ASSERT_TRUE(response);
22656
22657 EXPECT_TRUE(response->headers);
22658 EXPECT_EQ("HTTP/1.0 400 Not OK", response->headers->GetStatusLine());
22659
22660 std::string response_data;
22661 rv = ReadTransaction(&trans, &response_data);
22662 EXPECT_THAT(rv, IsOk());
22663 EXPECT_EQ("hello world", response_data);
22664 }
22665
TEST_P(HttpNetworkTransactionTest,PostIgnoresNonErrorResponseAfterReset)22666 TEST_P(HttpNetworkTransactionTest, PostIgnoresNonErrorResponseAfterReset) {
22667 std::vector<std::unique_ptr<UploadElementReader>> element_readers;
22668 element_readers.push_back(
22669 std::make_unique<UploadBytesElementReader>("foo", 3));
22670 ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0);
22671
22672 HttpRequestInfo request;
22673 request.method = "POST";
22674 request.url = GURL("http://www.foo.com/");
22675 request.upload_data_stream = &upload_data_stream;
22676 request.traffic_annotation =
22677 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
22678
22679 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
22680 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
22681 // Send headers successfully, but get an error while sending the body.
22682 MockWrite data_writes[] = {
22683 MockWrite("POST / HTTP/1.1\r\n"
22684 "Host: www.foo.com\r\n"
22685 "Connection: keep-alive\r\n"
22686 "Content-Length: 3\r\n\r\n"),
22687 MockWrite(SYNCHRONOUS, ERR_CONNECTION_RESET),
22688 };
22689
22690 MockRead data_reads[] = {
22691 MockRead("HTTP/1.0 200 Just Dandy\r\n\r\n"),
22692 MockRead("hello world"),
22693 MockRead(SYNCHRONOUS, OK),
22694 };
22695 StaticSocketDataProvider data(data_reads, data_writes);
22696 session_deps_.socket_factory->AddSocketDataProvider(&data);
22697
22698 TestCompletionCallback callback;
22699
22700 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
22701 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
22702
22703 rv = callback.WaitForResult();
22704 EXPECT_THAT(rv, IsError(ERR_CONNECTION_RESET));
22705 }
22706
TEST_P(HttpNetworkTransactionTest,PostIgnoresNonErrorResponseAfterResetAnd100)22707 TEST_P(HttpNetworkTransactionTest,
22708 PostIgnoresNonErrorResponseAfterResetAnd100) {
22709 std::vector<std::unique_ptr<UploadElementReader>> element_readers;
22710 element_readers.push_back(
22711 std::make_unique<UploadBytesElementReader>("foo", 3));
22712 ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0);
22713
22714 HttpRequestInfo request;
22715 request.method = "POST";
22716 request.url = GURL("http://www.foo.com/");
22717 request.upload_data_stream = &upload_data_stream;
22718 request.traffic_annotation =
22719 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
22720
22721 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
22722 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
22723 // Send headers successfully, but get an error while sending the body.
22724 MockWrite data_writes[] = {
22725 MockWrite("POST / HTTP/1.1\r\n"
22726 "Host: www.foo.com\r\n"
22727 "Connection: keep-alive\r\n"
22728 "Content-Length: 3\r\n\r\n"),
22729 MockWrite(SYNCHRONOUS, ERR_CONNECTION_RESET),
22730 };
22731
22732 MockRead data_reads[] = {
22733 MockRead("HTTP/1.0 100 Continue\r\n\r\n"),
22734 MockRead("HTTP/1.0 302 Redirect\r\n"),
22735 MockRead("Location: http://somewhere-else.com/\r\n"),
22736 MockRead("Content-Length: 0\r\n\r\n"),
22737 MockRead(SYNCHRONOUS, OK),
22738 };
22739 StaticSocketDataProvider data(data_reads, data_writes);
22740 session_deps_.socket_factory->AddSocketDataProvider(&data);
22741
22742 TestCompletionCallback callback;
22743
22744 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
22745 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
22746
22747 rv = callback.WaitForResult();
22748 EXPECT_THAT(rv, IsError(ERR_CONNECTION_RESET));
22749 }
22750
TEST_P(HttpNetworkTransactionTest,PostIgnoresHttp09ResponseAfterReset)22751 TEST_P(HttpNetworkTransactionTest, PostIgnoresHttp09ResponseAfterReset) {
22752 std::vector<std::unique_ptr<UploadElementReader>> element_readers;
22753 element_readers.push_back(
22754 std::make_unique<UploadBytesElementReader>("foo", 3));
22755 ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0);
22756
22757 HttpRequestInfo request;
22758 request.method = "POST";
22759 request.url = GURL("http://www.foo.com/");
22760 request.upload_data_stream = &upload_data_stream;
22761 request.traffic_annotation =
22762 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
22763
22764 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
22765 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
22766 // Send headers successfully, but get an error while sending the body.
22767 MockWrite data_writes[] = {
22768 MockWrite("POST / HTTP/1.1\r\n"
22769 "Host: www.foo.com\r\n"
22770 "Connection: keep-alive\r\n"
22771 "Content-Length: 3\r\n\r\n"),
22772 MockWrite(SYNCHRONOUS, ERR_CONNECTION_RESET),
22773 };
22774
22775 MockRead data_reads[] = {
22776 MockRead("HTTP 0.9 rocks!"),
22777 MockRead(SYNCHRONOUS, OK),
22778 };
22779 StaticSocketDataProvider data(data_reads, data_writes);
22780 session_deps_.socket_factory->AddSocketDataProvider(&data);
22781
22782 TestCompletionCallback callback;
22783
22784 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
22785 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
22786
22787 rv = callback.WaitForResult();
22788 EXPECT_THAT(rv, IsError(ERR_CONNECTION_RESET));
22789 }
22790
TEST_P(HttpNetworkTransactionTest,PostIgnoresPartial400HeadersAfterReset)22791 TEST_P(HttpNetworkTransactionTest, PostIgnoresPartial400HeadersAfterReset) {
22792 std::vector<std::unique_ptr<UploadElementReader>> element_readers;
22793 element_readers.push_back(
22794 std::make_unique<UploadBytesElementReader>("foo", 3));
22795 ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0);
22796
22797 HttpRequestInfo request;
22798 request.method = "POST";
22799 request.url = GURL("http://www.foo.com/");
22800 request.upload_data_stream = &upload_data_stream;
22801 request.traffic_annotation =
22802 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
22803
22804 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
22805 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
22806 // Send headers successfully, but get an error while sending the body.
22807 MockWrite data_writes[] = {
22808 MockWrite("POST / HTTP/1.1\r\n"
22809 "Host: www.foo.com\r\n"
22810 "Connection: keep-alive\r\n"
22811 "Content-Length: 3\r\n\r\n"),
22812 MockWrite(SYNCHRONOUS, ERR_CONNECTION_RESET),
22813 };
22814
22815 MockRead data_reads[] = {
22816 MockRead("HTTP/1.0 400 Not a Full Response\r\n"),
22817 MockRead(SYNCHRONOUS, OK),
22818 };
22819 StaticSocketDataProvider data(data_reads, data_writes);
22820 session_deps_.socket_factory->AddSocketDataProvider(&data);
22821
22822 TestCompletionCallback callback;
22823
22824 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
22825 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
22826
22827 rv = callback.WaitForResult();
22828 EXPECT_THAT(rv, IsError(ERR_CONNECTION_RESET));
22829 }
22830
22831 #if BUILDFLAG(ENABLE_WEBSOCKETS)
22832
22833 namespace {
22834
AddWebSocketHeaders(HttpRequestHeaders * headers)22835 void AddWebSocketHeaders(HttpRequestHeaders* headers) {
22836 headers->SetHeader("Connection", "Upgrade");
22837 headers->SetHeader("Upgrade", "websocket");
22838 headers->SetHeader("Origin", "http://www.example.org");
22839 headers->SetHeader("Sec-WebSocket-Version", "13");
22840 }
22841
22842 } // namespace
22843
TEST_P(HttpNetworkTransactionTest,CreateWebSocketHandshakeStream)22844 TEST_P(HttpNetworkTransactionTest, CreateWebSocketHandshakeStream) {
22845 for (bool secure : {true, false}) {
22846 MockWrite data_writes[] = {
22847 MockWrite("GET / HTTP/1.1\r\n"
22848 "Host: www.example.org\r\n"
22849 "Connection: Upgrade\r\n"
22850 "Upgrade: websocket\r\n"
22851 "Origin: http://www.example.org\r\n"
22852 "Sec-WebSocket-Version: 13\r\n"
22853 "Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n"
22854 "Sec-WebSocket-Extensions: permessage-deflate; "
22855 "client_max_window_bits\r\n\r\n")};
22856
22857 MockRead data_reads[] = {
22858 MockRead("HTTP/1.1 101 Switching Protocols\r\n"
22859 "Upgrade: websocket\r\n"
22860 "Connection: Upgrade\r\n"
22861 "Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=\r\n\r\n")};
22862
22863 StaticSocketDataProvider data(data_reads, data_writes);
22864 session_deps_.socket_factory->AddSocketDataProvider(&data);
22865 SSLSocketDataProvider ssl(ASYNC, OK);
22866 if (secure) {
22867 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
22868 }
22869
22870 HttpRequestInfo request;
22871 request.method = "GET";
22872 request.url =
22873 GURL(secure ? "ws://www.example.org/" : "wss://www.example.org/");
22874 AddWebSocketHeaders(&request.extra_headers);
22875 request.traffic_annotation =
22876 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
22877
22878 TestWebSocketHandshakeStreamCreateHelper
22879 websocket_handshake_stream_create_helper;
22880
22881 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
22882 HttpNetworkTransaction trans(LOW, session.get());
22883 trans.SetWebSocketHandshakeStreamCreateHelper(
22884 &websocket_handshake_stream_create_helper);
22885
22886 TestCompletionCallback callback;
22887 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
22888 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
22889
22890 const HttpStreamRequest* stream_request = trans.stream_request_.get();
22891 ASSERT_TRUE(stream_request);
22892 EXPECT_EQ(&websocket_handshake_stream_create_helper,
22893 stream_request->websocket_handshake_stream_create_helper());
22894
22895 rv = callback.WaitForResult();
22896 EXPECT_THAT(rv, IsOk());
22897
22898 EXPECT_TRUE(data.AllReadDataConsumed());
22899 EXPECT_TRUE(data.AllWriteDataConsumed());
22900 }
22901 }
22902
22903 // Verify that proxy headers are not sent to the destination server when
22904 // establishing a tunnel for a secure WebSocket connection.
TEST_P(HttpNetworkTransactionTest,ProxyHeadersNotSentOverWssTunnel)22905 TEST_P(HttpNetworkTransactionTest, ProxyHeadersNotSentOverWssTunnel) {
22906 HttpRequestInfo request;
22907 request.method = "GET";
22908 request.url = GURL("wss://www.example.org/");
22909 request.traffic_annotation =
22910 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
22911 AddWebSocketHeaders(&request.extra_headers);
22912
22913 // Configure against proxy server "myproxy:70".
22914 session_deps_.proxy_resolution_service =
22915 ConfiguredProxyResolutionService::CreateFixedFromPacResultForTest(
22916 "PROXY myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
22917
22918 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
22919
22920 // Since a proxy is configured, try to establish a tunnel.
22921 MockWrite data_writes[] = {
22922 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
22923 "Host: www.example.org:443\r\n"
22924 "Proxy-Connection: keep-alive\r\n\r\n"),
22925
22926 // After calling trans->RestartWithAuth(), this is the request we should
22927 // be issuing -- the final header line contains the credentials.
22928 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
22929 "Host: www.example.org:443\r\n"
22930 "Proxy-Connection: keep-alive\r\n"
22931 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
22932
22933 MockWrite("GET / HTTP/1.1\r\n"
22934 "Host: www.example.org\r\n"
22935 "Connection: Upgrade\r\n"
22936 "Upgrade: websocket\r\n"
22937 "Origin: http://www.example.org\r\n"
22938 "Sec-WebSocket-Version: 13\r\n"
22939 "Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n"
22940 "Sec-WebSocket-Extensions: permessage-deflate; "
22941 "client_max_window_bits\r\n\r\n")};
22942
22943 // The proxy responds to the connect with a 407, using a persistent
22944 // connection.
22945 MockRead data_reads[] = {
22946 // No credentials.
22947 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"
22948 "Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"
22949 "Content-Length: 0\r\n"
22950 "Proxy-Connection: keep-alive\r\n\r\n"),
22951
22952 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
22953
22954 MockRead("HTTP/1.1 101 Switching Protocols\r\n"
22955 "Upgrade: websocket\r\n"
22956 "Connection: Upgrade\r\n"
22957 "Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=\r\n\r\n")};
22958
22959 StaticSocketDataProvider data(data_reads, data_writes);
22960 session_deps_.socket_factory->AddSocketDataProvider(&data);
22961 SSLSocketDataProvider ssl(ASYNC, OK);
22962 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
22963
22964 TestWebSocketHandshakeStreamCreateHelper websocket_stream_create_helper;
22965
22966 auto trans =
22967 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
22968 trans->SetWebSocketHandshakeStreamCreateHelper(
22969 &websocket_stream_create_helper);
22970
22971 {
22972 TestCompletionCallback callback;
22973
22974 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
22975 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
22976
22977 rv = callback.WaitForResult();
22978 EXPECT_THAT(rv, IsOk());
22979 }
22980
22981 const HttpResponseInfo* response = trans->GetResponseInfo();
22982 ASSERT_TRUE(response);
22983 ASSERT_TRUE(response->headers);
22984 EXPECT_EQ(407, response->headers->response_code());
22985
22986 {
22987 TestCompletionCallback callback;
22988
22989 int rv = trans->RestartWithAuth(AuthCredentials(kFoo, kBar),
22990 callback.callback());
22991 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
22992
22993 rv = callback.WaitForResult();
22994 EXPECT_THAT(rv, IsOk());
22995 }
22996
22997 response = trans->GetResponseInfo();
22998 ASSERT_TRUE(response);
22999 ASSERT_TRUE(response->headers);
23000
23001 EXPECT_EQ(101, response->headers->response_code());
23002
23003 trans.reset();
23004 session->CloseAllConnections(ERR_FAILED, "Very good reason");
23005 }
23006
23007 // Verify that proxy headers are not sent to the destination server when
23008 // establishing a tunnel for an insecure WebSocket connection.
23009 // This requires the authentication info to be injected into the auth cache
23010 // due to crbug.com/395064
23011 // TODO(ricea): Change to use a 407 response once issue 395064 is fixed.
TEST_P(HttpNetworkTransactionTest,ProxyHeadersNotSentOverWsTunnel)23012 TEST_P(HttpNetworkTransactionTest, ProxyHeadersNotSentOverWsTunnel) {
23013 HttpRequestInfo request;
23014 request.method = "GET";
23015 request.url = GURL("ws://www.example.org/");
23016 request.traffic_annotation =
23017 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
23018 AddWebSocketHeaders(&request.extra_headers);
23019
23020 // Configure against proxy server "myproxy:70".
23021 session_deps_.proxy_resolution_service =
23022 ConfiguredProxyResolutionService::CreateFixedFromPacResultForTest(
23023 "PROXY myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
23024
23025 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
23026
23027 MockWrite data_writes[] = {
23028 // Try to establish a tunnel for the WebSocket connection, with
23029 // credentials. Because WebSockets have a separate set of socket pools,
23030 // they cannot and will not use the same TCP/IP connection as the
23031 // preflight HTTP request.
23032 MockWrite("CONNECT www.example.org:80 HTTP/1.1\r\n"
23033 "Host: www.example.org:80\r\n"
23034 "Proxy-Connection: keep-alive\r\n"
23035 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
23036
23037 MockWrite("GET / HTTP/1.1\r\n"
23038 "Host: www.example.org\r\n"
23039 "Connection: Upgrade\r\n"
23040 "Upgrade: websocket\r\n"
23041 "Origin: http://www.example.org\r\n"
23042 "Sec-WebSocket-Version: 13\r\n"
23043 "Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n"
23044 "Sec-WebSocket-Extensions: permessage-deflate; "
23045 "client_max_window_bits\r\n\r\n")};
23046
23047 MockRead data_reads[] = {
23048 // HTTP CONNECT with credentials.
23049 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
23050
23051 // WebSocket connection established inside tunnel.
23052 MockRead("HTTP/1.1 101 Switching Protocols\r\n"
23053 "Upgrade: websocket\r\n"
23054 "Connection: Upgrade\r\n"
23055 "Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=\r\n\r\n")};
23056
23057 StaticSocketDataProvider data(data_reads, data_writes);
23058 session_deps_.socket_factory->AddSocketDataProvider(&data);
23059
23060 session->http_auth_cache()->Add(
23061 url::SchemeHostPort(GURL("http://myproxy:70/")), HttpAuth::AUTH_PROXY,
23062 "MyRealm1", HttpAuth::AUTH_SCHEME_BASIC, NetworkAnonymizationKey(),
23063 "Basic realm=MyRealm1", AuthCredentials(kFoo, kBar), "/");
23064
23065 TestWebSocketHandshakeStreamCreateHelper websocket_stream_create_helper;
23066
23067 auto trans =
23068 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
23069 trans->SetWebSocketHandshakeStreamCreateHelper(
23070 &websocket_stream_create_helper);
23071
23072 TestCompletionCallback callback;
23073
23074 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
23075 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
23076
23077 rv = callback.WaitForResult();
23078 EXPECT_THAT(rv, IsOk());
23079
23080 const HttpResponseInfo* response = trans->GetResponseInfo();
23081 ASSERT_TRUE(response);
23082 ASSERT_TRUE(response->headers);
23083
23084 EXPECT_EQ(101, response->headers->response_code());
23085
23086 trans.reset();
23087 session->CloseAllConnections(ERR_FAILED, "Very good reason");
23088 }
23089
23090 // WebSockets over QUIC is not supported, including over QUIC proxies.
TEST_P(HttpNetworkTransactionTest,WebSocketNotSentOverQuicProxy)23091 TEST_P(HttpNetworkTransactionTest, WebSocketNotSentOverQuicProxy) {
23092 for (bool secure : {true, false}) {
23093 SCOPED_TRACE(secure);
23094 session_deps_.proxy_resolution_service =
23095 ConfiguredProxyResolutionService::CreateFixedFromProxyChainsForTest(
23096 {ProxyChain::FromSchemeHostAndPort(ProxyServer::SCHEME_QUIC,
23097 "myproxy.org", 443)},
23098 TRAFFIC_ANNOTATION_FOR_TESTS);
23099 session_deps_.enable_quic = true;
23100
23101 HttpRequestInfo request;
23102 request.url =
23103 GURL(secure ? "ws://www.example.org/" : "wss://www.example.org/");
23104 AddWebSocketHeaders(&request.extra_headers);
23105 request.traffic_annotation =
23106 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
23107
23108 TestWebSocketHandshakeStreamCreateHelper
23109 websocket_handshake_stream_create_helper;
23110
23111 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
23112 HttpNetworkTransaction trans(LOW, session.get());
23113 trans.SetWebSocketHandshakeStreamCreateHelper(
23114 &websocket_handshake_stream_create_helper);
23115
23116 TestCompletionCallback callback;
23117 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
23118 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
23119
23120 rv = callback.WaitForResult();
23121 EXPECT_THAT(rv, IsError(ERR_NO_SUPPORTED_PROXIES));
23122 }
23123 }
23124
23125 #endif // BUILDFLAG(ENABLE_WEBSOCKETS)
23126
TEST_P(HttpNetworkTransactionTest,TotalNetworkBytesPost)23127 TEST_P(HttpNetworkTransactionTest, TotalNetworkBytesPost) {
23128 std::vector<std::unique_ptr<UploadElementReader>> element_readers;
23129 element_readers.push_back(
23130 std::make_unique<UploadBytesElementReader>("foo", 3));
23131 ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0);
23132
23133 HttpRequestInfo request;
23134 request.method = "POST";
23135 request.url = GURL("http://www.foo.com/");
23136 request.upload_data_stream = &upload_data_stream;
23137 request.traffic_annotation =
23138 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
23139
23140 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
23141 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
23142 MockWrite data_writes[] = {
23143 MockWrite("POST / HTTP/1.1\r\n"
23144 "Host: www.foo.com\r\n"
23145 "Connection: keep-alive\r\n"
23146 "Content-Length: 3\r\n\r\n"),
23147 MockWrite("foo"),
23148 };
23149
23150 MockRead data_reads[] = {
23151 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
23152 MockRead("hello world"),
23153 MockRead(SYNCHRONOUS, OK),
23154 };
23155 StaticSocketDataProvider data(data_reads, data_writes);
23156 session_deps_.socket_factory->AddSocketDataProvider(&data);
23157
23158 TestCompletionCallback callback;
23159
23160 EXPECT_EQ(ERR_IO_PENDING,
23161 trans.Start(&request, callback.callback(), NetLogWithSource()));
23162 EXPECT_THAT(callback.WaitForResult(), IsOk());
23163
23164 std::string response_data;
23165 EXPECT_THAT(ReadTransaction(&trans, &response_data), IsOk());
23166
23167 EXPECT_EQ(CountWriteBytes(data_writes), trans.GetTotalSentBytes());
23168 EXPECT_EQ(CountReadBytes(data_reads), trans.GetTotalReceivedBytes());
23169 }
23170
TEST_P(HttpNetworkTransactionTest,TotalNetworkBytesPost100Continue)23171 TEST_P(HttpNetworkTransactionTest, TotalNetworkBytesPost100Continue) {
23172 std::vector<std::unique_ptr<UploadElementReader>> element_readers;
23173 element_readers.push_back(
23174 std::make_unique<UploadBytesElementReader>("foo", 3));
23175 ElementsUploadDataStream upload_data_stream(std::move(element_readers), 0);
23176
23177 HttpRequestInfo request;
23178 request.method = "POST";
23179 request.url = GURL("http://www.foo.com/");
23180 request.upload_data_stream = &upload_data_stream;
23181 request.traffic_annotation =
23182 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
23183
23184 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
23185 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
23186 MockWrite data_writes[] = {
23187 MockWrite("POST / HTTP/1.1\r\n"
23188 "Host: www.foo.com\r\n"
23189 "Connection: keep-alive\r\n"
23190 "Content-Length: 3\r\n\r\n"),
23191 MockWrite("foo"),
23192 };
23193
23194 MockRead data_reads[] = {
23195 MockRead("HTTP/1.1 100 Continue\r\n\r\n"),
23196 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
23197 MockRead("hello world"),
23198 MockRead(SYNCHRONOUS, OK),
23199 };
23200 StaticSocketDataProvider data(data_reads, data_writes);
23201 session_deps_.socket_factory->AddSocketDataProvider(&data);
23202
23203 TestCompletionCallback callback;
23204
23205 EXPECT_EQ(ERR_IO_PENDING,
23206 trans.Start(&request, callback.callback(), NetLogWithSource()));
23207 EXPECT_THAT(callback.WaitForResult(), IsOk());
23208
23209 std::string response_data;
23210 EXPECT_THAT(ReadTransaction(&trans, &response_data), IsOk());
23211
23212 EXPECT_EQ(CountWriteBytes(data_writes), trans.GetTotalSentBytes());
23213 EXPECT_EQ(CountReadBytes(data_reads), trans.GetTotalReceivedBytes());
23214 }
23215
TEST_P(HttpNetworkTransactionTest,TotalNetworkBytesChunkedPost)23216 TEST_P(HttpNetworkTransactionTest, TotalNetworkBytesChunkedPost) {
23217 ChunkedUploadDataStream upload_data_stream(0);
23218
23219 HttpRequestInfo request;
23220 request.method = "POST";
23221 request.url = GURL("http://www.foo.com/");
23222 request.upload_data_stream = &upload_data_stream;
23223 request.traffic_annotation =
23224 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
23225
23226 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
23227 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
23228 // Send headers successfully, but get an error while sending the body.
23229 MockWrite data_writes[] = {
23230 MockWrite("POST / HTTP/1.1\r\n"
23231 "Host: www.foo.com\r\n"
23232 "Connection: keep-alive\r\n"
23233 "Transfer-Encoding: chunked\r\n\r\n"),
23234 MockWrite("1\r\nf\r\n"),
23235 MockWrite("2\r\noo\r\n"),
23236 MockWrite("0\r\n\r\n"),
23237 };
23238
23239 MockRead data_reads[] = {
23240 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
23241 MockRead("hello world"),
23242 MockRead(SYNCHRONOUS, OK),
23243 };
23244 StaticSocketDataProvider data(data_reads, data_writes);
23245 session_deps_.socket_factory->AddSocketDataProvider(&data);
23246
23247 TestCompletionCallback callback;
23248
23249 EXPECT_EQ(ERR_IO_PENDING,
23250 trans.Start(&request, callback.callback(), NetLogWithSource()));
23251
23252 base::RunLoop().RunUntilIdle();
23253 upload_data_stream.AppendData("f", 1, false);
23254
23255 base::RunLoop().RunUntilIdle();
23256 upload_data_stream.AppendData("oo", 2, true);
23257
23258 EXPECT_THAT(callback.WaitForResult(), IsOk());
23259
23260 std::string response_data;
23261 EXPECT_THAT(ReadTransaction(&trans, &response_data), IsOk());
23262
23263 EXPECT_EQ(CountWriteBytes(data_writes), trans.GetTotalSentBytes());
23264 EXPECT_EQ(CountReadBytes(data_reads), trans.GetTotalReceivedBytes());
23265 }
23266
CheckContentEncodingMatching(SpdySessionDependencies * session_deps,const std::string & accept_encoding,const std::string & content_encoding,const std::string & location,bool should_match)23267 void CheckContentEncodingMatching(SpdySessionDependencies* session_deps,
23268 const std::string& accept_encoding,
23269 const std::string& content_encoding,
23270 const std::string& location,
23271 bool should_match) {
23272 HttpRequestInfo request;
23273 request.method = "GET";
23274 request.url = GURL("http://www.foo.com/");
23275 request.extra_headers.SetHeader(HttpRequestHeaders::kAcceptEncoding,
23276 accept_encoding);
23277 request.traffic_annotation =
23278 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
23279
23280 std::unique_ptr<HttpNetworkSession> session(CreateSession(session_deps));
23281 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
23282 // Send headers successfully, but get an error while sending the body.
23283 MockWrite data_writes[] = {
23284 MockWrite("GET / HTTP/1.1\r\n"
23285 "Host: www.foo.com\r\n"
23286 "Connection: keep-alive\r\n"
23287 "Accept-Encoding: "),
23288 MockWrite(accept_encoding.data()),
23289 MockWrite("\r\n\r\n"),
23290 };
23291
23292 std::string response_code = "200 OK";
23293 std::string extra;
23294 if (!location.empty()) {
23295 response_code = "301 Redirect\r\nLocation: ";
23296 response_code.append(location);
23297 }
23298
23299 MockRead data_reads[] = {
23300 MockRead("HTTP/1.0 "),
23301 MockRead(response_code.data()),
23302 MockRead("\r\nContent-Encoding: "),
23303 MockRead(content_encoding.data()),
23304 MockRead("\r\n\r\n"),
23305 MockRead(SYNCHRONOUS, OK),
23306 };
23307 StaticSocketDataProvider data(data_reads, data_writes);
23308 session_deps->socket_factory->AddSocketDataProvider(&data);
23309
23310 TestCompletionCallback callback;
23311
23312 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
23313 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
23314
23315 rv = callback.WaitForResult();
23316 if (should_match) {
23317 EXPECT_THAT(rv, IsOk());
23318 } else {
23319 EXPECT_THAT(rv, IsError(ERR_CONTENT_DECODING_FAILED));
23320 }
23321 }
23322
TEST_P(HttpNetworkTransactionTest,MatchContentEncoding1)23323 TEST_P(HttpNetworkTransactionTest, MatchContentEncoding1) {
23324 CheckContentEncodingMatching(&session_deps_, "gzip,sdch", "br", "", false);
23325 }
23326
TEST_P(HttpNetworkTransactionTest,MatchContentEncoding2)23327 TEST_P(HttpNetworkTransactionTest, MatchContentEncoding2) {
23328 CheckContentEncodingMatching(&session_deps_, "identity;q=1, *;q=0", "", "",
23329 true);
23330 }
23331
TEST_P(HttpNetworkTransactionTest,MatchContentEncoding3)23332 TEST_P(HttpNetworkTransactionTest, MatchContentEncoding3) {
23333 CheckContentEncodingMatching(&session_deps_, "identity;q=1, *;q=0", "gzip",
23334 "", false);
23335 }
23336
TEST_P(HttpNetworkTransactionTest,MatchContentEncoding4)23337 TEST_P(HttpNetworkTransactionTest, MatchContentEncoding4) {
23338 CheckContentEncodingMatching(&session_deps_, "identity;q=1, *;q=0", "gzip",
23339 "www.foo.com/other", true);
23340 }
23341
TEST_P(HttpNetworkTransactionTest,ProxyResolutionFailsSync)23342 TEST_P(HttpNetworkTransactionTest, ProxyResolutionFailsSync) {
23343 ProxyConfig proxy_config;
23344 proxy_config.set_pac_url(GURL("http://fooproxyurl"));
23345 proxy_config.set_pac_mandatory(true);
23346 MockAsyncProxyResolver resolver;
23347 session_deps_.proxy_resolution_service =
23348 std::make_unique<ConfiguredProxyResolutionService>(
23349
23350 std::make_unique<ProxyConfigServiceFixed>(ProxyConfigWithAnnotation(
23351 proxy_config, TRAFFIC_ANNOTATION_FOR_TESTS)),
23352 std::make_unique<FailingProxyResolverFactory>(), nullptr,
23353 /*quick_check_enabled=*/true);
23354
23355 HttpRequestInfo request;
23356 request.method = "GET";
23357 request.url = GURL("http://www.example.org/");
23358 request.traffic_annotation =
23359 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
23360
23361 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
23362 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
23363
23364 TestCompletionCallback callback;
23365
23366 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
23367 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
23368 EXPECT_THAT(callback.WaitForResult(),
23369 IsError(ERR_MANDATORY_PROXY_CONFIGURATION_FAILED));
23370 }
23371
TEST_P(HttpNetworkTransactionTest,ProxyResolutionFailsAsync)23372 TEST_P(HttpNetworkTransactionTest, ProxyResolutionFailsAsync) {
23373 ProxyConfig proxy_config;
23374 proxy_config.set_pac_url(GURL("http://fooproxyurl"));
23375 proxy_config.set_pac_mandatory(true);
23376 auto proxy_resolver_factory =
23377 std::make_unique<MockAsyncProxyResolverFactory>(false);
23378 auto* proxy_resolver_factory_ptr = proxy_resolver_factory.get();
23379 MockAsyncProxyResolver resolver;
23380 session_deps_.proxy_resolution_service =
23381 std::make_unique<ConfiguredProxyResolutionService>(
23382
23383 std::make_unique<ProxyConfigServiceFixed>(ProxyConfigWithAnnotation(
23384 proxy_config, TRAFFIC_ANNOTATION_FOR_TESTS)),
23385 std::move(proxy_resolver_factory), nullptr,
23386 /*quick_check_enabled=*/true);
23387 HttpRequestInfo request;
23388 request.method = "GET";
23389 request.url = GURL("http://www.example.org/");
23390 request.traffic_annotation =
23391 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
23392
23393 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
23394 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
23395
23396 TestCompletionCallback callback;
23397 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
23398 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
23399
23400 proxy_resolver_factory_ptr->pending_requests()[0]->CompleteNowWithForwarder(
23401 ERR_FAILED, &resolver);
23402 EXPECT_THAT(callback.WaitForResult(),
23403 IsError(ERR_MANDATORY_PROXY_CONFIGURATION_FAILED));
23404 }
23405
TEST_P(HttpNetworkTransactionTest,NoSupportedProxies)23406 TEST_P(HttpNetworkTransactionTest, NoSupportedProxies) {
23407 session_deps_.proxy_resolution_service =
23408 ConfiguredProxyResolutionService::CreateFixedFromProxyChainsForTest(
23409 {ProxyChain::FromSchemeHostAndPort(ProxyServer::SCHEME_QUIC,
23410 "myproxy.org", 443)},
23411 TRAFFIC_ANNOTATION_FOR_TESTS);
23412 session_deps_.enable_quic = false;
23413 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
23414
23415 HttpRequestInfo request;
23416 request.method = "GET";
23417 request.url = GURL("http://www.example.org/");
23418 request.traffic_annotation =
23419 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
23420
23421 TestCompletionCallback callback;
23422 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
23423 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
23424 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
23425
23426 EXPECT_THAT(callback.WaitForResult(), IsError(ERR_NO_SUPPORTED_PROXIES));
23427 }
23428
23429 //-----------------------------------------------------------------------------
23430 // Reporting tests
23431
23432 #if BUILDFLAG(ENABLE_REPORTING)
23433 class HttpNetworkTransactionReportingTest
23434 : public HttpNetworkTransactionTestBase,
23435 public ::testing::WithParamInterface<bool> {
23436 protected:
HttpNetworkTransactionReportingTest()23437 HttpNetworkTransactionReportingTest() {
23438 std::vector<base::test::FeatureRef> required_features = {
23439 features::kPartitionNelAndReportingByNetworkIsolationKey};
23440 if (UseDocumentReporting()) {
23441 required_features.push_back(features::kDocumentReporting);
23442 }
23443 feature_list_.InitWithFeatures(required_features, {});
23444 }
23445
SetUp()23446 void SetUp() override {
23447 HttpNetworkTransactionTestBase::SetUp();
23448 auto test_reporting_context = std::make_unique<TestReportingContext>(
23449 &clock_, &tick_clock_, ReportingPolicy());
23450 test_reporting_context_ = test_reporting_context.get();
23451 session_deps_.reporting_service =
23452 ReportingService::CreateForTesting(std::move(test_reporting_context));
23453 }
23454
reporting_context() const23455 TestReportingContext* reporting_context() const {
23456 return test_reporting_context_;
23457 }
23458
TearDown()23459 void TearDown() override {
23460 clear_reporting_service();
23461 HttpNetworkTransactionTestBase::TearDown();
23462 }
clear_reporting_service()23463 void clear_reporting_service() {
23464 test_reporting_context_ = nullptr;
23465 session_deps_.reporting_service.reset();
23466 }
23467
23468 // Makes an HTTPS request that should install a valid Reporting policy
23469 // using Report-To header.
RequestPolicy(CertStatus cert_status=0)23470 void RequestPolicy(CertStatus cert_status = 0) {
23471 HttpRequestInfo request;
23472 request.method = "GET";
23473 request.url = GURL(url_);
23474 request.traffic_annotation =
23475 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
23476 request.network_isolation_key = kNetworkIsolationKey;
23477 request.network_anonymization_key = kNetworkAnonymizationKey;
23478 MockWrite data_writes[] = {
23479 MockWrite("GET / HTTP/1.1\r\n"
23480 "Host: www.example.org\r\n"
23481 "Connection: keep-alive\r\n\r\n"),
23482 };
23483
23484 MockRead reporting_header;
23485 reporting_header = MockRead(
23486 "Report-To: {\"group\": \"nel\", \"max_age\": 86400, "
23487 "\"endpoints\": [{\"url\": "
23488 "\"https://www.example.org/upload/\"}]}\r\n");
23489 MockRead data_reads[] = {
23490 MockRead("HTTP/1.0 200 OK\r\n"),
23491 std::move(reporting_header),
23492 MockRead("\r\n"),
23493 MockRead("hello world"),
23494 MockRead(SYNCHRONOUS, OK),
23495 };
23496
23497 StaticSocketDataProvider reads(data_reads, data_writes);
23498 session_deps_.socket_factory->AddSocketDataProvider(&reads);
23499
23500 SSLSocketDataProvider ssl(ASYNC, OK);
23501 if (request.url.SchemeIsCryptographic()) {
23502 ssl.ssl_info.cert =
23503 ImportCertFromFile(GetTestCertsDirectory(), "wildcard.pem");
23504 ASSERT_TRUE(ssl.ssl_info.cert);
23505 ssl.ssl_info.cert_status = cert_status;
23506 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
23507 }
23508
23509 TestCompletionCallback callback;
23510 auto session = CreateSession(&session_deps_);
23511 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
23512 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
23513 EXPECT_THAT(callback.GetResult(rv), IsOk());
23514 }
23515
23516 protected:
UseDocumentReporting() const23517 bool UseDocumentReporting() const { return GetParam(); }
23518 std::string url_ = "https://www.example.org/";
23519
23520 private:
23521 base::test::ScopedFeatureList feature_list_;
23522 raw_ptr<TestReportingContext> test_reporting_context_ = nullptr;
23523 };
23524
TEST_P(HttpNetworkTransactionReportingTest,DontProcessReportToHeaderNoService)23525 TEST_P(HttpNetworkTransactionReportingTest,
23526 DontProcessReportToHeaderNoService) {
23527 clear_reporting_service();
23528 RequestPolicy();
23529 // No crash.
23530 }
23531
TEST_P(HttpNetworkTransactionReportingTest,DontProcessReportToHeaderHttp)23532 TEST_P(HttpNetworkTransactionReportingTest, DontProcessReportToHeaderHttp) {
23533 url_ = "http://www.example.org/";
23534 RequestPolicy();
23535 EXPECT_EQ(0u, reporting_context()->cache()->GetEndpointCount());
23536 }
23537
TEST_P(HttpNetworkTransactionReportingTest,ProcessReportToHeaderHttps)23538 TEST_P(HttpNetworkTransactionReportingTest, ProcessReportToHeaderHttps) {
23539 RequestPolicy();
23540 ASSERT_EQ(1u, reporting_context()->cache()->GetEndpointCount());
23541 const ReportingEndpoint endpoint =
23542 reporting_context()->cache()->GetEndpointForTesting(
23543 ReportingEndpointGroupKey(
23544 kNetworkAnonymizationKey,
23545 url::Origin::Create(GURL("https://www.example.org/")), "nel"),
23546 GURL("https://www.example.org/upload/"));
23547 EXPECT_TRUE(endpoint);
23548 }
23549
TEST_P(HttpNetworkTransactionReportingTest,DontProcessReportToHeaderInvalidHttps)23550 TEST_P(HttpNetworkTransactionReportingTest,
23551 DontProcessReportToHeaderInvalidHttps) {
23552 CertStatus cert_status = CERT_STATUS_COMMON_NAME_INVALID;
23553 RequestPolicy(cert_status);
23554 EXPECT_EQ(0u, reporting_context()->cache()->GetEndpointCount());
23555 }
23556
23557 INSTANTIATE_TEST_SUITE_P(All,
23558 HttpNetworkTransactionReportingTest,
23559 ::testing::Bool());
23560
23561 #endif // BUILDFLAG(ENABLE_REPORTING)
23562
23563 //-----------------------------------------------------------------------------
23564 // Network Error Logging tests
23565
23566 #if BUILDFLAG(ENABLE_REPORTING)
23567 namespace {
23568
23569 const char kUserAgent[] = "Mozilla/1.0";
23570 const char kReferrer[] = "https://www.referrer.org/";
23571
23572 } // namespace
23573
23574 class HttpNetworkTransactionNetworkErrorLoggingTest
23575 : public HttpNetworkTransactionTest {
23576 protected:
SetUp()23577 void SetUp() override {
23578 HttpNetworkTransactionTestBase::SetUp();
23579 auto network_error_logging_service =
23580 std::make_unique<TestNetworkErrorLoggingService>();
23581 test_network_error_logging_service_ = network_error_logging_service.get();
23582 session_deps_.network_error_logging_service =
23583 std::move(network_error_logging_service);
23584
23585 extra_headers_.SetHeader("User-Agent", kUserAgent);
23586 extra_headers_.SetHeader("Referer", kReferrer);
23587
23588 request_.method = "GET";
23589 request_.url = GURL(url_);
23590 request_.network_isolation_key = kNetworkIsolationKey;
23591 request_.network_anonymization_key = kNetworkAnonymizationKey;
23592 request_.extra_headers = extra_headers_;
23593 request_.reporting_upload_depth = reporting_upload_depth_;
23594 request_.traffic_annotation =
23595 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
23596 }
23597
TearDown()23598 void TearDown() override {
23599 clear_network_error_logging_service();
23600 HttpNetworkTransactionTestBase::TearDown();
23601 }
23602
network_error_logging_service() const23603 TestNetworkErrorLoggingService* network_error_logging_service() const {
23604 return test_network_error_logging_service_;
23605 }
23606
clear_network_error_logging_service()23607 void clear_network_error_logging_service() {
23608 test_network_error_logging_service_ = nullptr;
23609 session_deps_.network_error_logging_service.reset();
23610 }
23611
23612 // Makes an HTTPS request that should install a valid NEL policy.
RequestPolicy(CertStatus cert_status=0)23613 void RequestPolicy(CertStatus cert_status = 0) {
23614 std::string extra_header_string = extra_headers_.ToString();
23615 MockWrite data_writes[] = {
23616 MockWrite("GET / HTTP/1.1\r\n"
23617 "Host: www.example.org\r\n"
23618 "Connection: keep-alive\r\n"),
23619 MockWrite(ASYNC, extra_header_string.data(),
23620 extra_header_string.size()),
23621 };
23622 MockRead data_reads[] = {
23623 MockRead("HTTP/1.0 200 OK\r\n"),
23624 MockRead("NEL: {\"report_to\": \"nel\", \"max_age\": 86400}\r\n"),
23625 MockRead("\r\n"),
23626 MockRead("hello world"),
23627 MockRead(SYNCHRONOUS, OK),
23628 };
23629
23630 StaticSocketDataProvider reads(data_reads, data_writes);
23631 session_deps_.socket_factory->AddSocketDataProvider(&reads);
23632
23633 SSLSocketDataProvider ssl(ASYNC, OK);
23634 if (request_.url.SchemeIsCryptographic()) {
23635 ssl.ssl_info.cert =
23636 ImportCertFromFile(GetTestCertsDirectory(), "wildcard.pem");
23637 ASSERT_TRUE(ssl.ssl_info.cert);
23638 ssl.ssl_info.cert_status = cert_status;
23639 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
23640 }
23641
23642 TestCompletionCallback callback;
23643 auto session = CreateSession(&session_deps_);
23644 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
23645 int rv = trans.Start(&request_, callback.callback(), NetLogWithSource());
23646 EXPECT_THAT(callback.GetResult(rv), IsOk());
23647
23648 std::string response_data;
23649 ASSERT_THAT(ReadTransaction(&trans, &response_data), IsOk());
23650 EXPECT_EQ("hello world", response_data);
23651 }
23652
CheckReport(size_t index,int status_code,int error_type,IPAddress server_ip=IPAddress::IPv4Localhost ())23653 void CheckReport(size_t index,
23654 int status_code,
23655 int error_type,
23656 IPAddress server_ip = IPAddress::IPv4Localhost()) {
23657 ASSERT_LT(index, network_error_logging_service()->errors().size());
23658
23659 const NetworkErrorLoggingService::RequestDetails& error =
23660 network_error_logging_service()->errors()[index];
23661 EXPECT_EQ(url_, error.uri);
23662 EXPECT_EQ(kNetworkAnonymizationKey, error.network_anonymization_key);
23663 EXPECT_EQ(kReferrer, error.referrer);
23664 EXPECT_EQ(kUserAgent, error.user_agent);
23665 EXPECT_EQ(server_ip, error.server_ip);
23666 EXPECT_EQ("http/1.1", error.protocol);
23667 EXPECT_EQ("GET", error.method);
23668 EXPECT_EQ(status_code, error.status_code);
23669 EXPECT_EQ(error_type, error.type);
23670 EXPECT_EQ(0, error.reporting_upload_depth);
23671 }
23672
23673 protected:
23674 std::string url_ = "https://www.example.org/";
23675 CertStatus cert_status_ = 0;
23676 HttpRequestInfo request_;
23677 HttpRequestHeaders extra_headers_;
23678 int reporting_upload_depth_ = 0;
23679
23680 private:
23681 raw_ptr<TestNetworkErrorLoggingService> test_network_error_logging_service_ =
23682 nullptr;
23683 };
23684
23685 INSTANTIATE_TEST_SUITE_P(All,
23686 HttpNetworkTransactionNetworkErrorLoggingTest,
23687 testing::Values(true, false));
23688
TEST_P(HttpNetworkTransactionNetworkErrorLoggingTest,DontProcessNelHeaderNoService)23689 TEST_P(HttpNetworkTransactionNetworkErrorLoggingTest,
23690 DontProcessNelHeaderNoService) {
23691 clear_network_error_logging_service();
23692 RequestPolicy();
23693 // No crash.
23694 }
23695
TEST_P(HttpNetworkTransactionNetworkErrorLoggingTest,DontProcessNelHeaderHttp)23696 TEST_P(HttpNetworkTransactionNetworkErrorLoggingTest,
23697 DontProcessNelHeaderHttp) {
23698 url_ = "http://www.example.org/";
23699 request_.url = GURL(url_);
23700 RequestPolicy();
23701 EXPECT_EQ(0u, network_error_logging_service()->headers().size());
23702 }
23703
23704 // Don't set NEL policies received on a proxied connection.
TEST_P(HttpNetworkTransactionNetworkErrorLoggingTest,DontProcessNelHeaderProxy)23705 TEST_P(HttpNetworkTransactionNetworkErrorLoggingTest,
23706 DontProcessNelHeaderProxy) {
23707 session_deps_.proxy_resolution_service =
23708 ConfiguredProxyResolutionService::CreateFixedFromPacResultForTest(
23709 "PROXY myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
23710 session_deps_.net_log = NetLog::Get();
23711 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
23712
23713 HttpRequestInfo request;
23714 request.method = "GET";
23715 request.url = GURL("https://www.example.org/");
23716 request.traffic_annotation =
23717 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
23718
23719 // Since we have proxy, should try to establish tunnel.
23720 MockWrite data_writes1[] = {
23721 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
23722 "Host: www.example.org:443\r\n"
23723 "Proxy-Connection: keep-alive\r\n\r\n"),
23724
23725 MockWrite("GET / HTTP/1.1\r\n"
23726 "Host: www.example.org\r\n"
23727 "Connection: keep-alive\r\n\r\n"),
23728 };
23729
23730 MockRead data_reads1[] = {
23731 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
23732
23733 MockRead("HTTP/1.1 200 OK\r\n"),
23734 MockRead("NEL: {\"report_to\": \"nel\", \"max_age\": 86400}\r\n"),
23735 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
23736 MockRead("Content-Length: 100\r\n\r\n"),
23737 MockRead(SYNCHRONOUS, OK),
23738 };
23739
23740 StaticSocketDataProvider data1(data_reads1, data_writes1);
23741 session_deps_.socket_factory->AddSocketDataProvider(&data1);
23742 SSLSocketDataProvider ssl(ASYNC, OK);
23743 ssl.ssl_info.cert =
23744 ImportCertFromFile(GetTestCertsDirectory(), "wildcard.pem");
23745 ASSERT_TRUE(ssl.ssl_info.cert);
23746 ssl.ssl_info.cert_status = 0;
23747 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
23748
23749 TestCompletionCallback callback1;
23750 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
23751
23752 int rv = trans.Start(&request, callback1.callback(),
23753 NetLogWithSource::Make(NetLogSourceType::NONE));
23754 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
23755
23756 rv = callback1.WaitForResult();
23757 EXPECT_THAT(rv, IsOk());
23758
23759 const HttpResponseInfo* response = trans.GetResponseInfo();
23760 ASSERT_TRUE(response);
23761 EXPECT_EQ(200, response->headers->response_code());
23762 EXPECT_TRUE(response->was_fetched_via_proxy);
23763
23764 // No NEL header was set.
23765 EXPECT_EQ(0u, network_error_logging_service()->headers().size());
23766 }
23767
TEST_P(HttpNetworkTransactionNetworkErrorLoggingTest,ProcessNelHeaderHttps)23768 TEST_P(HttpNetworkTransactionNetworkErrorLoggingTest, ProcessNelHeaderHttps) {
23769 RequestPolicy();
23770 ASSERT_EQ(1u, network_error_logging_service()->headers().size());
23771 const auto& header = network_error_logging_service()->headers()[0];
23772 EXPECT_EQ(kNetworkAnonymizationKey, header.network_anonymization_key);
23773 EXPECT_EQ(url::Origin::Create(GURL("https://www.example.org/")),
23774 header.origin);
23775 EXPECT_EQ(IPAddress::IPv4Localhost(), header.received_ip_address);
23776 EXPECT_EQ("{\"report_to\": \"nel\", \"max_age\": 86400}", header.value);
23777 }
23778
TEST_P(HttpNetworkTransactionNetworkErrorLoggingTest,DontProcessNelHeaderInvalidHttps)23779 TEST_P(HttpNetworkTransactionNetworkErrorLoggingTest,
23780 DontProcessNelHeaderInvalidHttps) {
23781 CertStatus cert_status = CERT_STATUS_COMMON_NAME_INVALID;
23782 RequestPolicy(cert_status);
23783 EXPECT_EQ(0u, network_error_logging_service()->headers().size());
23784 }
23785
TEST_P(HttpNetworkTransactionNetworkErrorLoggingTest,CreateReportSuccess)23786 TEST_P(HttpNetworkTransactionNetworkErrorLoggingTest, CreateReportSuccess) {
23787 RequestPolicy();
23788 ASSERT_EQ(1u, network_error_logging_service()->errors().size());
23789 CheckReport(0 /* index */, 200 /* status_code */, OK);
23790 }
23791
TEST_P(HttpNetworkTransactionNetworkErrorLoggingTest,CreateReportDNSErrorAfterStartSync)23792 TEST_P(HttpNetworkTransactionNetworkErrorLoggingTest,
23793 CreateReportDNSErrorAfterStartSync) {
23794 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
23795 auto trans =
23796 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
23797
23798 session_deps_.host_resolver->set_synchronous_mode(true);
23799 session_deps_.host_resolver->rules()->AddRule(GURL(url_).host(),
23800 ERR_NAME_NOT_RESOLVED);
23801 TestCompletionCallback callback;
23802
23803 int rv = trans->Start(&request_, callback.callback(), NetLogWithSource());
23804 EXPECT_THAT(callback.GetResult(rv), IsError(ERR_NAME_NOT_RESOLVED));
23805
23806 trans.reset();
23807
23808 ASSERT_EQ(1u, network_error_logging_service()->errors().size());
23809 CheckReport(0 /* index */, 0 /* status_code */, ERR_NAME_NOT_RESOLVED,
23810 IPAddress() /* server_ip */);
23811 }
23812
TEST_P(HttpNetworkTransactionNetworkErrorLoggingTest,CreateReportDNSErrorAfterStartAsync)23813 TEST_P(HttpNetworkTransactionNetworkErrorLoggingTest,
23814 CreateReportDNSErrorAfterStartAsync) {
23815 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
23816 auto trans =
23817 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
23818
23819 session_deps_.host_resolver->set_synchronous_mode(false);
23820 session_deps_.host_resolver->rules()->AddRule(GURL(url_).host(),
23821 ERR_NAME_NOT_RESOLVED);
23822 TestCompletionCallback callback;
23823
23824 int rv = trans->Start(&request_, callback.callback(), NetLogWithSource());
23825 EXPECT_THAT(callback.GetResult(rv), IsError(ERR_NAME_NOT_RESOLVED));
23826
23827 trans.reset();
23828
23829 ASSERT_EQ(1u, network_error_logging_service()->errors().size());
23830 CheckReport(0 /* index */, 0 /* status_code */, ERR_NAME_NOT_RESOLVED,
23831 IPAddress() /* server_ip */);
23832 }
23833
TEST_P(HttpNetworkTransactionNetworkErrorLoggingTest,CreateReportErrorAfterStart)23834 TEST_P(HttpNetworkTransactionNetworkErrorLoggingTest,
23835 CreateReportErrorAfterStart) {
23836 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
23837 auto trans =
23838 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
23839
23840 MockConnect mock_connect(SYNCHRONOUS, ERR_CONNECTION_REFUSED);
23841 StaticSocketDataProvider data;
23842 data.set_connect_data(mock_connect);
23843 session_deps_.socket_factory->AddSocketDataProvider(&data);
23844
23845 TestCompletionCallback callback;
23846
23847 int rv = trans->Start(&request_, callback.callback(), NetLogWithSource());
23848 EXPECT_THAT(callback.GetResult(rv), IsError(ERR_CONNECTION_REFUSED));
23849
23850 trans.reset();
23851
23852 ASSERT_EQ(1u, network_error_logging_service()->errors().size());
23853 CheckReport(0 /* index */, 0 /* status_code */, ERR_CONNECTION_REFUSED,
23854 IPAddress::IPv4Localhost() /* server_ip */);
23855 }
23856
23857 // Same as above except the error is ASYNC
TEST_P(HttpNetworkTransactionNetworkErrorLoggingTest,CreateReportErrorAfterStartAsync)23858 TEST_P(HttpNetworkTransactionNetworkErrorLoggingTest,
23859 CreateReportErrorAfterStartAsync) {
23860 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
23861 auto trans =
23862 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
23863
23864 MockConnect mock_connect(ASYNC, ERR_CONNECTION_REFUSED);
23865 StaticSocketDataProvider data;
23866 data.set_connect_data(mock_connect);
23867 session_deps_.socket_factory->AddSocketDataProvider(&data);
23868
23869 TestCompletionCallback callback;
23870
23871 int rv = trans->Start(&request_, callback.callback(), NetLogWithSource());
23872 EXPECT_THAT(callback.GetResult(rv), IsError(ERR_CONNECTION_REFUSED));
23873
23874 trans.reset();
23875
23876 ASSERT_EQ(1u, network_error_logging_service()->errors().size());
23877 CheckReport(0 /* index */, 0 /* status_code */, ERR_CONNECTION_REFUSED,
23878 IPAddress::IPv4Localhost() /* server_ip */);
23879 }
23880
TEST_P(HttpNetworkTransactionNetworkErrorLoggingTest,CreateReportReadBodyError)23881 TEST_P(HttpNetworkTransactionNetworkErrorLoggingTest,
23882 CreateReportReadBodyError) {
23883 std::string extra_header_string = extra_headers_.ToString();
23884 MockWrite data_writes[] = {
23885 MockWrite("GET / HTTP/1.1\r\n"
23886 "Host: www.example.org\r\n"
23887 "Connection: keep-alive\r\n"),
23888 MockWrite(ASYNC, extra_header_string.data(), extra_header_string.size()),
23889 };
23890 MockRead data_reads[] = {
23891 MockRead("HTTP/1.0 200 OK\r\n"),
23892 MockRead("Content-Length: 100\r\n\r\n"), // wrong content length
23893 MockRead("hello world"),
23894 MockRead(SYNCHRONOUS, OK),
23895 };
23896
23897 StaticSocketDataProvider reads(data_reads, data_writes);
23898 session_deps_.socket_factory->AddSocketDataProvider(&reads);
23899
23900 SSLSocketDataProvider ssl(ASYNC, OK);
23901 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
23902
23903 // Log start time
23904 base::TimeTicks start_time = base::TimeTicks::Now();
23905
23906 TestCompletionCallback callback;
23907 auto session = CreateSession(&session_deps_);
23908 auto trans =
23909 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
23910 int rv = trans->Start(&request_, callback.callback(), NetLogWithSource());
23911 EXPECT_THAT(callback.GetResult(rv), IsOk());
23912
23913 const HttpResponseInfo* response = trans->GetResponseInfo();
23914 ASSERT_TRUE(response);
23915
23916 EXPECT_TRUE(response->headers);
23917 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
23918
23919 std::string response_data;
23920 rv = ReadTransaction(trans.get(), &response_data);
23921 EXPECT_THAT(rv, IsError(ERR_CONTENT_LENGTH_MISMATCH));
23922
23923 trans.reset();
23924
23925 ASSERT_EQ(1u, network_error_logging_service()->errors().size());
23926
23927 CheckReport(0 /* index */, 200 /* status_code */,
23928 ERR_CONTENT_LENGTH_MISMATCH);
23929 const NetworkErrorLoggingService::RequestDetails& error =
23930 network_error_logging_service()->errors()[0];
23931 EXPECT_LE(error.elapsed_time, base::TimeTicks::Now() - start_time);
23932 }
23933
23934 // Same as above except the final read is ASYNC.
TEST_P(HttpNetworkTransactionNetworkErrorLoggingTest,CreateReportReadBodyErrorAsync)23935 TEST_P(HttpNetworkTransactionNetworkErrorLoggingTest,
23936 CreateReportReadBodyErrorAsync) {
23937 std::string extra_header_string = extra_headers_.ToString();
23938 MockWrite data_writes[] = {
23939 MockWrite("GET / HTTP/1.1\r\n"
23940 "Host: www.example.org\r\n"
23941 "Connection: keep-alive\r\n"),
23942 MockWrite(ASYNC, extra_header_string.data(), extra_header_string.size()),
23943 };
23944 MockRead data_reads[] = {
23945 MockRead("HTTP/1.0 200 OK\r\n"),
23946 MockRead("Content-Length: 100\r\n\r\n"), // wrong content length
23947 MockRead("hello world"),
23948 MockRead(ASYNC, OK),
23949 };
23950
23951 StaticSocketDataProvider reads(data_reads, data_writes);
23952 session_deps_.socket_factory->AddSocketDataProvider(&reads);
23953
23954 SSLSocketDataProvider ssl(ASYNC, OK);
23955 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
23956
23957 // Log start time
23958 base::TimeTicks start_time = base::TimeTicks::Now();
23959
23960 TestCompletionCallback callback;
23961 auto session = CreateSession(&session_deps_);
23962 auto trans =
23963 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
23964 int rv = trans->Start(&request_, callback.callback(), NetLogWithSource());
23965 EXPECT_THAT(callback.GetResult(rv), IsOk());
23966
23967 const HttpResponseInfo* response = trans->GetResponseInfo();
23968 ASSERT_TRUE(response);
23969
23970 EXPECT_TRUE(response->headers);
23971 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
23972
23973 std::string response_data;
23974 rv = ReadTransaction(trans.get(), &response_data);
23975 EXPECT_THAT(rv, IsError(ERR_CONTENT_LENGTH_MISMATCH));
23976
23977 trans.reset();
23978
23979 ASSERT_EQ(1u, network_error_logging_service()->errors().size());
23980
23981 CheckReport(0 /* index */, 200 /* status_code */,
23982 ERR_CONTENT_LENGTH_MISMATCH);
23983 const NetworkErrorLoggingService::RequestDetails& error =
23984 network_error_logging_service()->errors()[0];
23985 EXPECT_LE(error.elapsed_time, base::TimeTicks::Now() - start_time);
23986 }
23987
TEST_P(HttpNetworkTransactionNetworkErrorLoggingTest,CreateReportRestartWithAuth)23988 TEST_P(HttpNetworkTransactionNetworkErrorLoggingTest,
23989 CreateReportRestartWithAuth) {
23990 std::string extra_header_string = extra_headers_.ToString();
23991 static const base::TimeDelta kSleepDuration = base::Milliseconds(10);
23992
23993 MockWrite data_writes1[] = {
23994 MockWrite("GET / HTTP/1.1\r\n"
23995 "Host: www.example.org\r\n"
23996 "Connection: keep-alive\r\n"),
23997 MockWrite(ASYNC, extra_header_string.data(), extra_header_string.size()),
23998 };
23999
24000 MockRead data_reads1[] = {
24001 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
24002 // Give a couple authenticate options (only the middle one is actually
24003 // supported).
24004 MockRead("WWW-Authenticate: Basic invalid\r\n"), // Malformed.
24005 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
24006 MockRead("WWW-Authenticate: UNSUPPORTED realm=\"FOO\"\r\n"),
24007 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
24008 // Large content-length -- won't matter, as connection will be reset.
24009 MockRead("Content-Length: 10000\r\n\r\n"),
24010 MockRead(SYNCHRONOUS, ERR_FAILED),
24011 };
24012
24013 // After calling trans->RestartWithAuth(), this is the request we should
24014 // be issuing -- the final header line contains the credentials.
24015 MockWrite data_writes2[] = {
24016 MockWrite("GET / HTTP/1.1\r\n"
24017 "Host: www.example.org\r\n"
24018 "Connection: keep-alive\r\n"
24019 "Authorization: Basic Zm9vOmJhcg==\r\n"),
24020 MockWrite(ASYNC, extra_header_string.data(), extra_header_string.size()),
24021 };
24022
24023 // Lastly, the server responds with the actual content.
24024 MockRead data_reads2[] = {
24025 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
24026 MockRead("hello world"),
24027 MockRead(SYNCHRONOUS, OK),
24028 };
24029
24030 StaticSocketDataProvider data1(data_reads1, data_writes1);
24031 StaticSocketDataProvider data2(data_reads2, data_writes2);
24032 session_deps_.socket_factory->AddSocketDataProvider(&data1);
24033 session_deps_.socket_factory->AddSocketDataProvider(&data2);
24034
24035 SSLSocketDataProvider ssl1(ASYNC, OK);
24036 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl1);
24037 SSLSocketDataProvider ssl2(ASYNC, OK);
24038 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
24039
24040 base::TimeTicks start_time = base::TimeTicks::Now();
24041 base::TimeTicks restart_time;
24042
24043 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
24044 auto trans =
24045 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
24046
24047 TestCompletionCallback callback1;
24048
24049 int rv = trans->Start(&request_, callback1.callback(), NetLogWithSource());
24050 EXPECT_THAT(callback1.GetResult(rv), IsOk());
24051
24052 ASSERT_EQ(1u, network_error_logging_service()->errors().size());
24053
24054 TestCompletionCallback callback2;
24055
24056 // Wait 10 ms then restart with auth
24057 FastForwardBy(kSleepDuration);
24058 restart_time = base::TimeTicks::Now();
24059 rv =
24060 trans->RestartWithAuth(AuthCredentials(kFoo, kBar), callback2.callback());
24061 EXPECT_THAT(callback2.GetResult(rv), IsOk());
24062
24063 std::string response_data;
24064 ASSERT_THAT(ReadTransaction(trans.get(), &response_data), IsOk());
24065 EXPECT_EQ("hello world", response_data);
24066
24067 trans.reset();
24068
24069 // One 401 report for the auth challenge, then a 200 report for the successful
24070 // retry. Note that we don't report the error draining the body, as the first
24071 // request already generated a report for the auth challenge.
24072 ASSERT_EQ(2u, network_error_logging_service()->errors().size());
24073
24074 // Check error report contents
24075 CheckReport(0 /* index */, 401 /* status_code */, OK);
24076 CheckReport(1 /* index */, 200 /* status_code */, OK);
24077
24078 const NetworkErrorLoggingService::RequestDetails& error1 =
24079 network_error_logging_service()->errors()[0];
24080 const NetworkErrorLoggingService::RequestDetails& error2 =
24081 network_error_logging_service()->errors()[1];
24082
24083 // Sanity-check elapsed time values
24084 EXPECT_EQ(error1.elapsed_time, restart_time - start_time - kSleepDuration);
24085 // Check that the start time is refreshed when restarting with auth.
24086 EXPECT_EQ(error2.elapsed_time, base::TimeTicks::Now() - restart_time);
24087 }
24088
24089 // Same as above, except draining the body before restarting fails
24090 // asynchronously.
TEST_P(HttpNetworkTransactionNetworkErrorLoggingTest,CreateReportRestartWithAuthAsync)24091 TEST_P(HttpNetworkTransactionNetworkErrorLoggingTest,
24092 CreateReportRestartWithAuthAsync) {
24093 std::string extra_header_string = extra_headers_.ToString();
24094 static const base::TimeDelta kSleepDuration = base::Milliseconds(10);
24095
24096 MockWrite data_writes1[] = {
24097 MockWrite("GET / HTTP/1.1\r\n"
24098 "Host: www.example.org\r\n"
24099 "Connection: keep-alive\r\n"),
24100 MockWrite(ASYNC, extra_header_string.data(), extra_header_string.size()),
24101 };
24102
24103 MockRead data_reads1[] = {
24104 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
24105 // Give a couple authenticate options (only the middle one is actually
24106 // supported).
24107 MockRead("WWW-Authenticate: Basic invalid\r\n"), // Malformed.
24108 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
24109 MockRead("WWW-Authenticate: UNSUPPORTED realm=\"FOO\"\r\n"),
24110 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
24111 // Large content-length -- won't matter, as connection will be reset.
24112 MockRead("Content-Length: 10000\r\n\r\n"),
24113 MockRead(ASYNC, ERR_FAILED),
24114 };
24115
24116 // After calling trans->RestartWithAuth(), this is the request we should
24117 // be issuing -- the final header line contains the credentials.
24118 MockWrite data_writes2[] = {
24119 MockWrite("GET / HTTP/1.1\r\n"
24120 "Host: www.example.org\r\n"
24121 "Connection: keep-alive\r\n"
24122 "Authorization: Basic Zm9vOmJhcg==\r\n"),
24123 MockWrite(ASYNC, extra_header_string.data(), extra_header_string.size()),
24124 };
24125
24126 // Lastly, the server responds with the actual content.
24127 MockRead data_reads2[] = {
24128 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
24129 MockRead("hello world"),
24130 MockRead(SYNCHRONOUS, OK),
24131 };
24132
24133 StaticSocketDataProvider data1(data_reads1, data_writes1);
24134 StaticSocketDataProvider data2(data_reads2, data_writes2);
24135 session_deps_.socket_factory->AddSocketDataProvider(&data1);
24136 session_deps_.socket_factory->AddSocketDataProvider(&data2);
24137
24138 SSLSocketDataProvider ssl1(ASYNC, OK);
24139 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl1);
24140 SSLSocketDataProvider ssl2(ASYNC, OK);
24141 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
24142
24143 base::TimeTicks start_time = base::TimeTicks::Now();
24144 base::TimeTicks restart_time;
24145
24146 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
24147 auto trans =
24148 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
24149
24150 TestCompletionCallback callback1;
24151
24152 int rv = trans->Start(&request_, callback1.callback(), NetLogWithSource());
24153 EXPECT_THAT(callback1.GetResult(rv), IsOk());
24154
24155 ASSERT_EQ(1u, network_error_logging_service()->errors().size());
24156
24157 TestCompletionCallback callback2;
24158
24159 // Wait 10 ms then restart with auth
24160 FastForwardBy(kSleepDuration);
24161 restart_time = base::TimeTicks::Now();
24162 rv =
24163 trans->RestartWithAuth(AuthCredentials(kFoo, kBar), callback2.callback());
24164 EXPECT_THAT(callback2.GetResult(rv), IsOk());
24165
24166 std::string response_data;
24167 ASSERT_THAT(ReadTransaction(trans.get(), &response_data), IsOk());
24168 EXPECT_EQ("hello world", response_data);
24169
24170 trans.reset();
24171
24172 // One 401 report for the auth challenge, then a 200 report for the successful
24173 // retry. Note that we don't report the error draining the body, as the first
24174 // request already generated a report for the auth challenge.
24175 ASSERT_EQ(2u, network_error_logging_service()->errors().size());
24176
24177 // Check error report contents
24178 CheckReport(0 /* index */, 401 /* status_code */, OK);
24179 CheckReport(1 /* index */, 200 /* status_code */, OK);
24180
24181 const NetworkErrorLoggingService::RequestDetails& error1 =
24182 network_error_logging_service()->errors()[0];
24183 const NetworkErrorLoggingService::RequestDetails& error2 =
24184 network_error_logging_service()->errors()[1];
24185
24186 // Sanity-check elapsed time values
24187 EXPECT_EQ(error1.elapsed_time, restart_time - start_time - kSleepDuration);
24188 // Check that the start time is refreshed when restarting with auth.
24189 EXPECT_EQ(error2.elapsed_time, base::TimeTicks::Now() - restart_time);
24190 }
24191
TEST_P(HttpNetworkTransactionNetworkErrorLoggingTest,CreateReportRetryKeepAliveConnectionReset)24192 TEST_P(HttpNetworkTransactionNetworkErrorLoggingTest,
24193 CreateReportRetryKeepAliveConnectionReset) {
24194 std::string extra_header_string = extra_headers_.ToString();
24195 MockWrite data_writes1[] = {
24196 MockWrite("GET / HTTP/1.1\r\n"
24197 "Host: www.example.org\r\n"
24198 "Connection: keep-alive\r\n"),
24199 MockWrite(ASYNC, extra_header_string.data(), extra_header_string.size()),
24200 MockWrite("GET / HTTP/1.1\r\n"
24201 "Host: www.example.org\r\n"
24202 "Connection: keep-alive\r\n"),
24203 MockWrite(ASYNC, extra_header_string.data(), extra_header_string.size()),
24204 };
24205
24206 MockRead data_reads1[] = {
24207 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
24208 MockRead("hello"),
24209 // Connection is reset
24210 MockRead(ASYNC, ERR_CONNECTION_RESET),
24211 };
24212
24213 // Successful retry
24214 MockRead data_reads2[] = {
24215 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
24216 MockRead("world"),
24217 MockRead(ASYNC, OK),
24218 };
24219
24220 StaticSocketDataProvider data1(data_reads1, data_writes1);
24221 StaticSocketDataProvider data2(data_reads2, base::span<MockWrite>());
24222 session_deps_.socket_factory->AddSocketDataProvider(&data1);
24223 session_deps_.socket_factory->AddSocketDataProvider(&data2);
24224
24225 SSLSocketDataProvider ssl1(ASYNC, OK);
24226 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl1);
24227 SSLSocketDataProvider ssl2(ASYNC, OK);
24228 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
24229
24230 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
24231 auto trans1 =
24232 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
24233
24234 TestCompletionCallback callback1;
24235
24236 int rv = trans1->Start(&request_, callback1.callback(), NetLogWithSource());
24237 EXPECT_THAT(callback1.GetResult(rv), IsOk());
24238
24239 std::string response_data;
24240 ASSERT_THAT(ReadTransaction(trans1.get(), &response_data), IsOk());
24241 EXPECT_EQ("hello", response_data);
24242
24243 ASSERT_EQ(1u, network_error_logging_service()->errors().size());
24244
24245 auto trans2 =
24246 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
24247
24248 TestCompletionCallback callback2;
24249
24250 rv = trans2->Start(&request_, callback2.callback(), NetLogWithSource());
24251 EXPECT_THAT(callback2.GetResult(rv), IsOk());
24252
24253 ASSERT_THAT(ReadTransaction(trans2.get(), &response_data), IsOk());
24254 EXPECT_EQ("world", response_data);
24255
24256 trans1.reset();
24257 trans2.reset();
24258
24259 // One OK report from first request, then a ERR_CONNECTION_RESET report from
24260 // the second request, then an OK report from the successful retry.
24261 ASSERT_EQ(3u, network_error_logging_service()->errors().size());
24262
24263 // Check error report contents
24264 CheckReport(0 /* index */, 200 /* status_code */, OK);
24265 CheckReport(1 /* index */, 0 /* status_code */, ERR_CONNECTION_RESET);
24266 CheckReport(2 /* index */, 200 /* status_code */, OK);
24267 }
24268
TEST_P(HttpNetworkTransactionNetworkErrorLoggingTest,CreateReportRetryKeepAlive408)24269 TEST_P(HttpNetworkTransactionNetworkErrorLoggingTest,
24270 CreateReportRetryKeepAlive408) {
24271 std::string extra_header_string = extra_headers_.ToString();
24272 MockWrite data_writes1[] = {
24273 MockWrite("GET / HTTP/1.1\r\n"
24274 "Host: www.example.org\r\n"
24275 "Connection: keep-alive\r\n"),
24276 MockWrite(ASYNC, extra_header_string.data(), extra_header_string.size()),
24277 MockWrite("GET / HTTP/1.1\r\n"
24278 "Host: www.example.org\r\n"
24279 "Connection: keep-alive\r\n"),
24280 MockWrite(ASYNC, extra_header_string.data(), extra_header_string.size()),
24281 };
24282
24283 MockRead data_reads1[] = {
24284 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
24285 MockRead("hello"),
24286 // 408 Request Timeout
24287 MockRead(SYNCHRONOUS,
24288 "HTTP/1.1 408 Request Timeout\r\n"
24289 "Connection: Keep-Alive\r\n"
24290 "Content-Length: 6\r\n\r\n"
24291 "Pickle"),
24292 };
24293
24294 // Successful retry
24295 MockRead data_reads2[] = {
24296 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
24297 MockRead("world"),
24298 MockRead(ASYNC, OK),
24299 };
24300
24301 StaticSocketDataProvider data1(data_reads1, data_writes1);
24302 StaticSocketDataProvider data2(data_reads2, base::span<MockWrite>());
24303 session_deps_.socket_factory->AddSocketDataProvider(&data1);
24304 session_deps_.socket_factory->AddSocketDataProvider(&data2);
24305
24306 SSLSocketDataProvider ssl1(ASYNC, OK);
24307 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl1);
24308 SSLSocketDataProvider ssl2(ASYNC, OK);
24309 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
24310
24311 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
24312 auto trans1 =
24313 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
24314
24315 TestCompletionCallback callback1;
24316
24317 int rv = trans1->Start(&request_, callback1.callback(), NetLogWithSource());
24318 EXPECT_THAT(callback1.GetResult(rv), IsOk());
24319
24320 std::string response_data;
24321 ASSERT_THAT(ReadTransaction(trans1.get(), &response_data), IsOk());
24322 EXPECT_EQ("hello", response_data);
24323
24324 ASSERT_EQ(1u, network_error_logging_service()->errors().size());
24325
24326 auto trans2 =
24327 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
24328
24329 TestCompletionCallback callback2;
24330
24331 rv = trans2->Start(&request_, callback2.callback(), NetLogWithSource());
24332 EXPECT_THAT(callback2.GetResult(rv), IsOk());
24333
24334 ASSERT_THAT(ReadTransaction(trans2.get(), &response_data), IsOk());
24335 EXPECT_EQ("world", response_data);
24336
24337 trans1.reset();
24338 trans2.reset();
24339
24340 // One 200 report from first request, then a 408 report from
24341 // the second request, then a 200 report from the successful retry.
24342 ASSERT_EQ(3u, network_error_logging_service()->errors().size());
24343
24344 // Check error report contents
24345 CheckReport(0 /* index */, 200 /* status_code */, OK);
24346 CheckReport(1 /* index */, 408 /* status_code */, OK);
24347 CheckReport(2 /* index */, 200 /* status_code */, OK);
24348 }
24349
TEST_P(HttpNetworkTransactionNetworkErrorLoggingTest,CreateReportRetry421WithoutConnectionPooling)24350 TEST_P(HttpNetworkTransactionNetworkErrorLoggingTest,
24351 CreateReportRetry421WithoutConnectionPooling) {
24352 // Two hosts resolve to the same IP address.
24353 const std::string ip_addr = "1.2.3.4";
24354 IPAddress ip;
24355 ASSERT_TRUE(ip.AssignFromIPLiteral(ip_addr));
24356 IPEndPoint peer_addr = IPEndPoint(ip, 443);
24357
24358 session_deps_.host_resolver = std::make_unique<MockCachingHostResolver>();
24359 session_deps_.host_resolver->rules()->AddRule("www.example.org", ip_addr);
24360 session_deps_.host_resolver->rules()->AddRule("mail.example.org", ip_addr);
24361
24362 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
24363
24364 // Two requests on the first connection.
24365 spdy::SpdySerializedFrame req1(
24366 spdy_util_.ConstructSpdyGet("https://www.example.org", 1, LOWEST));
24367 spdy_util_.UpdateWithStreamDestruction(1);
24368 spdy::SpdySerializedFrame req2(
24369 spdy_util_.ConstructSpdyGet("https://mail.example.org", 3, LOWEST));
24370 spdy::SpdySerializedFrame rst(
24371 spdy_util_.ConstructSpdyRstStream(3, spdy::ERROR_CODE_CANCEL));
24372 MockWrite writes1[] = {
24373 CreateMockWrite(req1, 0),
24374 CreateMockWrite(req2, 3),
24375 CreateMockWrite(rst, 6),
24376 };
24377
24378 // The first one succeeds, the second gets error 421 Misdirected Request.
24379 spdy::SpdySerializedFrame resp1(
24380 spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
24381 spdy::SpdySerializedFrame body1(spdy_util_.ConstructSpdyDataFrame(1, true));
24382 spdy::Http2HeaderBlock response_headers;
24383 response_headers[spdy::kHttp2StatusHeader] = "421";
24384 spdy::SpdySerializedFrame resp2(
24385 spdy_util_.ConstructSpdyReply(3, std::move(response_headers)));
24386 MockRead reads1[] = {CreateMockRead(resp1, 1), CreateMockRead(body1, 2),
24387 CreateMockRead(resp2, 4), MockRead(ASYNC, 0, 5)};
24388
24389 MockConnect connect1(ASYNC, OK, peer_addr);
24390 SequencedSocketData data1(connect1, reads1, writes1);
24391 session_deps_.socket_factory->AddSocketDataProvider(&data1);
24392
24393 AddSSLSocketData();
24394
24395 // Retry the second request on a second connection.
24396 SpdyTestUtil spdy_util2(/*use_priority_header=*/true);
24397 spdy::SpdySerializedFrame req3(
24398 spdy_util2.ConstructSpdyGet("https://mail.example.org", 1, LOWEST));
24399 MockWrite writes2[] = {
24400 CreateMockWrite(req3, 0),
24401 };
24402
24403 spdy::SpdySerializedFrame resp3(
24404 spdy_util2.ConstructSpdyGetReply(nullptr, 0, 1));
24405 spdy::SpdySerializedFrame body3(spdy_util2.ConstructSpdyDataFrame(1, true));
24406 MockRead reads2[] = {CreateMockRead(resp3, 1), CreateMockRead(body3, 2),
24407 MockRead(ASYNC, 0, 3)};
24408
24409 MockConnect connect2(ASYNC, OK, peer_addr);
24410 SequencedSocketData data2(connect2, reads2, writes2);
24411 session_deps_.socket_factory->AddSocketDataProvider(&data2);
24412
24413 AddSSLSocketData();
24414
24415 // Preload mail.example.org into HostCache.
24416 int rv = session_deps_.host_resolver->LoadIntoCache(
24417 HostPortPair("mail.example.org", 443), NetworkAnonymizationKey(),
24418 std::nullopt);
24419 EXPECT_THAT(rv, IsOk());
24420
24421 HttpRequestInfo request1;
24422 request1.method = "GET";
24423 request1.url = GURL("https://www.example.org/");
24424 request1.load_flags = 0;
24425 request1.traffic_annotation =
24426 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
24427 auto trans1 =
24428 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
24429
24430 TestCompletionCallback callback;
24431 rv = trans1->Start(&request1, callback.callback(), NetLogWithSource());
24432 EXPECT_THAT(callback.GetResult(rv), IsOk());
24433
24434 const HttpResponseInfo* response = trans1->GetResponseInfo();
24435 ASSERT_TRUE(response);
24436 ASSERT_TRUE(response->headers);
24437 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
24438 EXPECT_TRUE(response->was_fetched_via_spdy);
24439 EXPECT_TRUE(response->was_alpn_negotiated);
24440 std::string response_data;
24441 ASSERT_THAT(ReadTransaction(trans1.get(), &response_data), IsOk());
24442 EXPECT_EQ("hello!", response_data);
24443
24444 trans1.reset();
24445
24446 ASSERT_EQ(1u, network_error_logging_service()->errors().size());
24447
24448 HttpRequestInfo request2;
24449 request2.method = "GET";
24450 request2.url = GURL("https://mail.example.org/");
24451 request2.load_flags = 0;
24452 request2.traffic_annotation =
24453 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
24454 auto trans2 =
24455 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
24456
24457 rv = trans2->Start(&request2, callback.callback(),
24458 NetLogWithSource::Make(NetLogSourceType::NONE));
24459 EXPECT_THAT(callback.GetResult(rv), IsOk());
24460
24461 response = trans2->GetResponseInfo();
24462 ASSERT_TRUE(response);
24463 ASSERT_TRUE(response->headers);
24464 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
24465 EXPECT_TRUE(response->was_fetched_via_spdy);
24466 EXPECT_TRUE(response->was_alpn_negotiated);
24467 ASSERT_THAT(ReadTransaction(trans2.get(), &response_data), IsOk());
24468 EXPECT_EQ("hello!", response_data);
24469
24470 trans2.reset();
24471
24472 // One 200 report from the first request, then a 421 report from the
24473 // second request, then a 200 report from the successful retry.
24474 ASSERT_EQ(3u, network_error_logging_service()->errors().size());
24475
24476 // Check error report contents
24477 const NetworkErrorLoggingService::RequestDetails& error1 =
24478 network_error_logging_service()->errors()[0];
24479 EXPECT_EQ(GURL("https://www.example.org/"), error1.uri);
24480 EXPECT_TRUE(error1.referrer.is_empty());
24481 EXPECT_EQ("", error1.user_agent);
24482 EXPECT_EQ(ip, error1.server_ip);
24483 EXPECT_EQ("h2", error1.protocol);
24484 EXPECT_EQ("GET", error1.method);
24485 EXPECT_EQ(200, error1.status_code);
24486 EXPECT_EQ(OK, error1.type);
24487 EXPECT_EQ(0, error1.reporting_upload_depth);
24488
24489 const NetworkErrorLoggingService::RequestDetails& error2 =
24490 network_error_logging_service()->errors()[1];
24491 EXPECT_EQ(GURL("https://mail.example.org/"), error2.uri);
24492 EXPECT_TRUE(error2.referrer.is_empty());
24493 EXPECT_EQ("", error2.user_agent);
24494 EXPECT_EQ(ip, error2.server_ip);
24495 EXPECT_EQ("h2", error2.protocol);
24496 EXPECT_EQ("GET", error2.method);
24497 EXPECT_EQ(421, error2.status_code);
24498 EXPECT_EQ(OK, error2.type);
24499 EXPECT_EQ(0, error2.reporting_upload_depth);
24500
24501 const NetworkErrorLoggingService::RequestDetails& error3 =
24502 network_error_logging_service()->errors()[2];
24503 EXPECT_EQ(GURL("https://mail.example.org/"), error3.uri);
24504 EXPECT_TRUE(error3.referrer.is_empty());
24505 EXPECT_EQ("", error3.user_agent);
24506 EXPECT_EQ(ip, error3.server_ip);
24507 EXPECT_EQ("h2", error3.protocol);
24508 EXPECT_EQ("GET", error3.method);
24509 EXPECT_EQ(200, error3.status_code);
24510 EXPECT_EQ(OK, error3.type);
24511 EXPECT_EQ(0, error3.reporting_upload_depth);
24512 }
24513
TEST_P(HttpNetworkTransactionNetworkErrorLoggingTest,CreateReportCancelAfterStart)24514 TEST_P(HttpNetworkTransactionNetworkErrorLoggingTest,
24515 CreateReportCancelAfterStart) {
24516 StaticSocketDataProvider data;
24517 data.set_connect_data(MockConnect(SYNCHRONOUS, ERR_IO_PENDING));
24518 session_deps_.socket_factory->AddSocketDataProvider(&data);
24519
24520 TestCompletionCallback callback;
24521 auto session = CreateSession(&session_deps_);
24522 auto trans =
24523 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
24524 int rv = trans->Start(&request_, callback.callback(), NetLogWithSource());
24525 EXPECT_EQ(rv, ERR_IO_PENDING);
24526
24527 // Cancel after start.
24528 trans.reset();
24529
24530 ASSERT_EQ(1u, network_error_logging_service()->errors().size());
24531 CheckReport(0 /* index */, 0 /* status_code */, ERR_ABORTED,
24532 IPAddress() /* server_ip */);
24533 }
24534
TEST_P(HttpNetworkTransactionNetworkErrorLoggingTest,CreateReportCancelBeforeReadingBody)24535 TEST_P(HttpNetworkTransactionNetworkErrorLoggingTest,
24536 CreateReportCancelBeforeReadingBody) {
24537 std::string extra_header_string = extra_headers_.ToString();
24538 MockWrite data_writes[] = {
24539 MockWrite("GET / HTTP/1.1\r\n"
24540 "Host: www.example.org\r\n"
24541 "Connection: keep-alive\r\n"),
24542 MockWrite(ASYNC, extra_header_string.data(), extra_header_string.size()),
24543 };
24544 MockRead data_reads[] = {
24545 MockRead("HTTP/1.0 200 OK\r\n"),
24546 MockRead("Content-Length: 100\r\n\r\n"), // Body is never read.
24547 };
24548
24549 StaticSocketDataProvider data(data_reads, data_writes);
24550 session_deps_.socket_factory->AddSocketDataProvider(&data);
24551
24552 SSLSocketDataProvider ssl(ASYNC, OK);
24553 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
24554
24555 TestCompletionCallback callback;
24556 auto session = CreateSession(&session_deps_);
24557 auto trans =
24558 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
24559 int rv = trans->Start(&request_, callback.callback(), NetLogWithSource());
24560 EXPECT_THAT(callback.GetResult(rv), IsOk());
24561
24562 const HttpResponseInfo* response = trans->GetResponseInfo();
24563 ASSERT_TRUE(response);
24564
24565 EXPECT_TRUE(response->headers);
24566 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
24567
24568 // Cancel before reading the body.
24569 trans.reset();
24570
24571 ASSERT_EQ(1u, network_error_logging_service()->errors().size());
24572 CheckReport(0 /* index */, 200 /* status_code */, ERR_ABORTED);
24573 }
24574
TEST_P(HttpNetworkTransactionNetworkErrorLoggingTest,DontCreateReportHttp)24575 TEST_P(HttpNetworkTransactionNetworkErrorLoggingTest, DontCreateReportHttp) {
24576 RequestPolicy();
24577 EXPECT_EQ(1u, network_error_logging_service()->headers().size());
24578 EXPECT_EQ(1u, network_error_logging_service()->errors().size());
24579
24580 // Make HTTP request
24581 std::string extra_header_string = extra_headers_.ToString();
24582 MockRead data_reads[] = {
24583 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
24584 MockRead("hello world"),
24585 MockRead(SYNCHRONOUS, OK),
24586 };
24587 MockWrite data_writes[] = {
24588 MockWrite("GET / HTTP/1.1\r\n"
24589 "Host: www.example.org\r\n"
24590 "Connection: keep-alive\r\n"),
24591 MockWrite(ASYNC, extra_header_string.data(), extra_header_string.size()),
24592 };
24593
24594 StaticSocketDataProvider data(data_reads, data_writes);
24595 session_deps_.socket_factory->AddSocketDataProvider(&data);
24596
24597 // Insecure url
24598 url_ = "http://www.example.org/";
24599 request_.url = GURL(url_);
24600
24601 TestCompletionCallback callback;
24602 auto session = CreateSession(&session_deps_);
24603 auto trans =
24604 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
24605 int rv = trans->Start(&request_, callback.callback(), NetLogWithSource());
24606 EXPECT_THAT(callback.GetResult(rv), IsOk());
24607
24608 std::string response_data;
24609 ASSERT_THAT(ReadTransaction(trans.get(), &response_data), IsOk());
24610 EXPECT_EQ("hello world", response_data);
24611
24612 // Insecure request does not generate a report
24613 EXPECT_EQ(1u, network_error_logging_service()->errors().size());
24614 }
24615
TEST_P(HttpNetworkTransactionNetworkErrorLoggingTest,DontCreateReportHttpError)24616 TEST_P(HttpNetworkTransactionNetworkErrorLoggingTest,
24617 DontCreateReportHttpError) {
24618 RequestPolicy();
24619 EXPECT_EQ(1u, network_error_logging_service()->headers().size());
24620 EXPECT_EQ(1u, network_error_logging_service()->errors().size());
24621
24622 // Make HTTP request that fails
24623 MockRead data_reads[] = {
24624 MockRead("hello world"),
24625 MockRead(SYNCHRONOUS, OK),
24626 };
24627
24628 StaticSocketDataProvider data(data_reads, base::span<MockWrite>());
24629 session_deps_.socket_factory->AddSocketDataProvider(&data);
24630
24631 url_ = "http://www.originwithoutpolicy.com:2000/";
24632 request_.url = GURL(url_);
24633
24634 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
24635
24636 auto trans =
24637 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
24638 TestCompletionCallback callback;
24639 int rv = trans->Start(&request_, callback.callback(), NetLogWithSource());
24640 EXPECT_THAT(callback.GetResult(rv), IsError(ERR_INVALID_HTTP_RESPONSE));
24641
24642 // Insecure request does not generate a report, regardless of existence of a
24643 // policy for the origin.
24644 EXPECT_EQ(1u, network_error_logging_service()->errors().size());
24645 }
24646
24647 // Don't report on proxy auth challenges, don't report if connecting through a
24648 // proxy.
TEST_P(HttpNetworkTransactionNetworkErrorLoggingTest,DontCreateReportProxy)24649 TEST_P(HttpNetworkTransactionNetworkErrorLoggingTest, DontCreateReportProxy) {
24650 HttpRequestInfo request;
24651 request.method = "GET";
24652 request.url = GURL("https://www.example.org/");
24653 request.traffic_annotation =
24654 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
24655
24656 // Configure against proxy server "myproxy:70".
24657 session_deps_.proxy_resolution_service =
24658 ConfiguredProxyResolutionService::CreateFixedFromPacResultForTest(
24659 "PROXY myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
24660 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
24661
24662 // Since we have proxy, should try to establish tunnel.
24663 MockWrite data_writes1[] = {
24664 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
24665 "Host: www.example.org:443\r\n"
24666 "Proxy-Connection: keep-alive\r\n\r\n"),
24667 };
24668
24669 // The proxy responds to the connect with a 407, using a non-persistent
24670 // connection.
24671 MockRead data_reads1[] = {
24672 // No credentials.
24673 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
24674 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
24675 MockRead("Proxy-Connection: close\r\n\r\n"),
24676 };
24677
24678 MockWrite data_writes2[] = {
24679 // After calling trans->RestartWithAuth(), this is the request we should
24680 // be issuing -- the final header line contains the credentials.
24681 MockWrite("CONNECT www.example.org:443 HTTP/1.1\r\n"
24682 "Host: www.example.org:443\r\n"
24683 "Proxy-Connection: keep-alive\r\n"
24684 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
24685
24686 MockWrite("GET / HTTP/1.1\r\n"
24687 "Host: www.example.org\r\n"
24688 "Connection: keep-alive\r\n\r\n"),
24689 };
24690
24691 MockRead data_reads2[] = {
24692 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
24693
24694 MockRead("HTTP/1.1 200 OK\r\n"),
24695 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
24696 MockRead("Content-Length: 5\r\n\r\n"),
24697 MockRead(SYNCHRONOUS, "hello"),
24698 };
24699
24700 StaticSocketDataProvider data1(data_reads1, data_writes1);
24701 session_deps_.socket_factory->AddSocketDataProvider(&data1);
24702 StaticSocketDataProvider data2(data_reads2, data_writes2);
24703 session_deps_.socket_factory->AddSocketDataProvider(&data2);
24704 SSLSocketDataProvider ssl(ASYNC, OK);
24705 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
24706
24707 TestCompletionCallback callback1;
24708
24709 auto trans =
24710 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
24711
24712 int rv = trans->Start(&request, callback1.callback(), NetLogWithSource());
24713 EXPECT_THAT(callback1.GetResult(rv), IsOk());
24714
24715 const HttpResponseInfo* response = trans->GetResponseInfo();
24716 EXPECT_EQ(407, response->headers->response_code());
24717
24718 std::string response_data;
24719 rv = ReadTransaction(trans.get(), &response_data);
24720 EXPECT_THAT(rv, IsError(ERR_TUNNEL_CONNECTION_FAILED));
24721
24722 // No NEL report is generated for the 407.
24723 EXPECT_EQ(0u, network_error_logging_service()->errors().size());
24724
24725 TestCompletionCallback callback2;
24726
24727 rv =
24728 trans->RestartWithAuth(AuthCredentials(kFoo, kBar), callback2.callback());
24729 EXPECT_THAT(callback2.GetResult(rv), IsOk());
24730
24731 response = trans->GetResponseInfo();
24732 EXPECT_EQ(200, response->headers->response_code());
24733
24734 ASSERT_THAT(ReadTransaction(trans.get(), &response_data), IsOk());
24735 EXPECT_EQ("hello", response_data);
24736
24737 trans.reset();
24738
24739 // No NEL report is generated because we are behind a proxy.
24740 EXPECT_EQ(0u, network_error_logging_service()->errors().size());
24741 }
24742
TEST_P(HttpNetworkTransactionNetworkErrorLoggingTest,ReportContainsUploadDepth)24743 TEST_P(HttpNetworkTransactionNetworkErrorLoggingTest,
24744 ReportContainsUploadDepth) {
24745 reporting_upload_depth_ = 7;
24746 request_.reporting_upload_depth = reporting_upload_depth_;
24747 RequestPolicy();
24748 ASSERT_EQ(1u, network_error_logging_service()->errors().size());
24749 const NetworkErrorLoggingService::RequestDetails& error =
24750 network_error_logging_service()->errors()[0];
24751 EXPECT_EQ(7, error.reporting_upload_depth);
24752 }
24753
TEST_P(HttpNetworkTransactionNetworkErrorLoggingTest,ReportElapsedTime)24754 TEST_P(HttpNetworkTransactionNetworkErrorLoggingTest, ReportElapsedTime) {
24755 std::string extra_header_string = extra_headers_.ToString();
24756 static const base::TimeDelta kSleepDuration = base::Milliseconds(10);
24757
24758 std::vector<MockWrite> data_writes = {
24759 MockWrite(ASYNC, 0,
24760 "GET / HTTP/1.1\r\n"
24761 "Host: www.example.org\r\n"
24762 "Connection: keep-alive\r\n"),
24763 MockWrite(ASYNC, 1, extra_header_string.data()),
24764 };
24765
24766 std::vector<MockRead> data_reads = {
24767 // Write one byte of the status line, followed by a pause.
24768 MockRead(ASYNC, 2, "H"),
24769 MockRead(ASYNC, ERR_IO_PENDING, 3),
24770 MockRead(ASYNC, 4, "TTP/1.1 200 OK\r\n\r\n"),
24771 MockRead(ASYNC, 5, "hello world"),
24772 MockRead(SYNCHRONOUS, OK, 6),
24773 };
24774
24775 SequencedSocketData data(data_reads, data_writes);
24776 session_deps_.socket_factory->AddSocketDataProvider(&data);
24777
24778 SSLSocketDataProvider ssl(ASYNC, OK);
24779 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
24780
24781 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
24782
24783 auto trans =
24784 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
24785
24786 TestCompletionCallback callback;
24787
24788 int rv = trans->Start(&request_, callback.callback(), NetLogWithSource());
24789 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
24790
24791 data.RunUntilPaused();
24792 ASSERT_TRUE(data.IsPaused());
24793 FastForwardBy(kSleepDuration);
24794 data.Resume();
24795
24796 EXPECT_THAT(callback.GetResult(rv), IsOk());
24797
24798 std::string response_data;
24799 ASSERT_THAT(ReadTransaction(trans.get(), &response_data), IsOk());
24800 EXPECT_EQ("hello world", response_data);
24801
24802 trans.reset();
24803
24804 ASSERT_EQ(1u, network_error_logging_service()->errors().size());
24805
24806 CheckReport(0 /* index */, 200 /* status_code */, OK);
24807
24808 const NetworkErrorLoggingService::RequestDetails& error =
24809 network_error_logging_service()->errors()[0];
24810
24811 // Sanity-check elapsed time in error report
24812 EXPECT_EQ(kSleepDuration, error.elapsed_time);
24813 }
24814
24815 #endif // BUILDFLAG(ENABLE_REPORTING)
24816
TEST_P(HttpNetworkTransactionTest,AlwaysFailRequestToCache)24817 TEST_P(HttpNetworkTransactionTest, AlwaysFailRequestToCache) {
24818 HttpRequestInfo request;
24819 request.method = "GET";
24820 request.url = GURL("http://example.org/");
24821
24822 request.load_flags = LOAD_ONLY_FROM_CACHE;
24823
24824 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
24825 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
24826 TestCompletionCallback callback1;
24827 int rv = trans.Start(&request, callback1.callback(), NetLogWithSource());
24828
24829 EXPECT_THAT(rv, IsError(ERR_CACHE_MISS));
24830 }
24831
TEST_P(HttpNetworkTransactionTest,ZeroRTTDoesntConfirm)24832 TEST_P(HttpNetworkTransactionTest, ZeroRTTDoesntConfirm) {
24833 static const base::TimeDelta kDelay = base::Milliseconds(10);
24834 HttpRequestInfo request;
24835 request.method = "GET";
24836 request.url = GURL("https://www.example.org/");
24837 request.traffic_annotation =
24838 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
24839
24840 MockWrite data_writes[] = {
24841 MockWrite("GET / HTTP/1.1\r\n"
24842 "Host: www.example.org\r\n"
24843 "Connection: keep-alive\r\n\r\n"),
24844 };
24845
24846 MockRead data_reads[] = {
24847 MockRead("HTTP/1.1 200 OK\r\n"),
24848 MockRead("Content-Length: 1\r\n\r\n"),
24849 MockRead(SYNCHRONOUS, "1"),
24850 };
24851
24852 StaticSocketDataProvider data(data_reads, data_writes);
24853 session_deps_.socket_factory->AddSocketDataProvider(&data);
24854 SSLSocketDataProvider ssl(SYNCHRONOUS, OK);
24855 ssl.connect_callback = FastForwardByCallback(kDelay);
24856 ssl.confirm = MockConfirm(SYNCHRONOUS, OK);
24857 ssl.confirm_callback = FastForwardByCallback(kDelay);
24858 session_deps_.enable_early_data = true;
24859 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
24860
24861 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
24862
24863 TestCompletionCallback callback;
24864 auto trans =
24865 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
24866
24867 base::TimeTicks start_time = base::TimeTicks::Now();
24868 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
24869 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
24870
24871 rv = callback.WaitForResult();
24872 EXPECT_THAT(rv, IsOk());
24873
24874 const HttpResponseInfo* response = trans->GetResponseInfo();
24875 ASSERT_TRUE(response);
24876 ASSERT_TRUE(response->headers);
24877 EXPECT_EQ(200, response->headers->response_code());
24878 EXPECT_EQ(1, response->headers->GetContentLength());
24879
24880 // Check that ConfirmHandshake wasn't called.
24881 ASSERT_FALSE(ssl.ConfirmDataConsumed());
24882 ASSERT_TRUE(ssl.WriteBeforeConfirm());
24883
24884 // The handshake time should include the time it took to run Connect(), but
24885 // not ConfirmHandshake().
24886 LoadTimingInfo load_timing_info;
24887 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
24888 EXPECT_EQ(load_timing_info.connect_timing.connect_start, start_time);
24889 EXPECT_EQ(load_timing_info.connect_timing.ssl_start, start_time);
24890 EXPECT_EQ(load_timing_info.connect_timing.ssl_end, start_time + kDelay);
24891 EXPECT_EQ(load_timing_info.connect_timing.connect_end, start_time + kDelay);
24892
24893 trans.reset();
24894
24895 session->CloseAllConnections(ERR_FAILED, "Very good reason");
24896 }
24897
TEST_P(HttpNetworkTransactionTest,ZeroRTTSyncConfirmSyncWrite)24898 TEST_P(HttpNetworkTransactionTest, ZeroRTTSyncConfirmSyncWrite) {
24899 static const base::TimeDelta kDelay = base::Milliseconds(10);
24900 HttpRequestInfo request;
24901 request.method = "POST";
24902 request.url = GURL("https://www.example.org/");
24903 request.traffic_annotation =
24904 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
24905
24906 MockWrite data_writes[] = {
24907 MockWrite(SYNCHRONOUS,
24908 "POST / HTTP/1.1\r\n"
24909 "Host: www.example.org\r\n"
24910 "Connection: keep-alive\r\n"
24911 "Content-Length: 0\r\n\r\n"),
24912 };
24913
24914 MockRead data_reads[] = {
24915 MockRead("HTTP/1.1 200 OK\r\n"),
24916 MockRead("Content-Length: 1\r\n\r\n"),
24917 MockRead(SYNCHRONOUS, "1"),
24918 };
24919
24920 StaticSocketDataProvider data(data_reads, data_writes);
24921 session_deps_.socket_factory->AddSocketDataProvider(&data);
24922 SSLSocketDataProvider ssl(SYNCHRONOUS, OK);
24923 ssl.connect_callback = FastForwardByCallback(kDelay);
24924 ssl.confirm = MockConfirm(SYNCHRONOUS, OK);
24925 ssl.confirm_callback = FastForwardByCallback(kDelay);
24926 session_deps_.enable_early_data = true;
24927 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
24928
24929 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
24930
24931 TestCompletionCallback callback;
24932 auto trans =
24933 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
24934
24935 base::TimeTicks start_time = base::TimeTicks::Now();
24936 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
24937 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
24938
24939 rv = callback.WaitForResult();
24940 EXPECT_THAT(rv, IsOk());
24941
24942 const HttpResponseInfo* response = trans->GetResponseInfo();
24943 ASSERT_TRUE(response);
24944 ASSERT_TRUE(response->headers);
24945 EXPECT_EQ(200, response->headers->response_code());
24946 EXPECT_EQ(1, response->headers->GetContentLength());
24947
24948 // Check that the Write didn't get called before ConfirmHandshake completed.
24949 ASSERT_FALSE(ssl.WriteBeforeConfirm());
24950
24951 // The handshake time should include the time it took to run Connect(), but
24952 // not ConfirmHandshake(). If ConfirmHandshake() returns synchronously, we
24953 // assume the connection did not negotiate 0-RTT or the handshake was already
24954 // confirmed.
24955 LoadTimingInfo load_timing_info;
24956 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
24957 EXPECT_EQ(load_timing_info.connect_timing.connect_start, start_time);
24958 EXPECT_EQ(load_timing_info.connect_timing.ssl_start, start_time);
24959 EXPECT_EQ(load_timing_info.connect_timing.ssl_end, start_time + kDelay);
24960 EXPECT_EQ(load_timing_info.connect_timing.connect_end, start_time + kDelay);
24961
24962 trans.reset();
24963
24964 session->CloseAllConnections(ERR_FAILED, "Very good reason");
24965 }
24966
TEST_P(HttpNetworkTransactionTest,ZeroRTTSyncConfirmAsyncWrite)24967 TEST_P(HttpNetworkTransactionTest, ZeroRTTSyncConfirmAsyncWrite) {
24968 HttpRequestInfo request;
24969 request.method = "POST";
24970 request.url = GURL("https://www.example.org/");
24971 request.traffic_annotation =
24972 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
24973
24974 MockWrite data_writes[] = {
24975 MockWrite(ASYNC,
24976 "POST / HTTP/1.1\r\n"
24977 "Host: www.example.org\r\n"
24978 "Connection: keep-alive\r\n"
24979 "Content-Length: 0\r\n\r\n"),
24980 };
24981
24982 MockRead data_reads[] = {
24983 MockRead("HTTP/1.1 200 OK\r\n"),
24984 MockRead("Content-Length: 1\r\n\r\n"),
24985 MockRead(SYNCHRONOUS, "1"),
24986 };
24987
24988 StaticSocketDataProvider data(data_reads, data_writes);
24989 session_deps_.socket_factory->AddSocketDataProvider(&data);
24990 SSLSocketDataProvider ssl(SYNCHRONOUS, OK);
24991 ssl.confirm = MockConfirm(SYNCHRONOUS, OK);
24992 session_deps_.enable_early_data = true;
24993 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
24994
24995 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
24996
24997 TestCompletionCallback callback;
24998 auto trans =
24999 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
25000
25001 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
25002 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
25003
25004 rv = callback.WaitForResult();
25005 EXPECT_THAT(rv, IsOk());
25006
25007 const HttpResponseInfo* response = trans->GetResponseInfo();
25008 ASSERT_TRUE(response);
25009 ASSERT_TRUE(response->headers);
25010 EXPECT_EQ(200, response->headers->response_code());
25011 EXPECT_EQ(1, response->headers->GetContentLength());
25012
25013 // Check that the Write didn't get called before ConfirmHandshake completed.
25014 ASSERT_FALSE(ssl.WriteBeforeConfirm());
25015
25016 trans.reset();
25017
25018 session->CloseAllConnections(ERR_FAILED, "Very good reason");
25019 }
25020
TEST_P(HttpNetworkTransactionTest,ZeroRTTAsyncConfirmSyncWrite)25021 TEST_P(HttpNetworkTransactionTest, ZeroRTTAsyncConfirmSyncWrite) {
25022 static const base::TimeDelta kDelay = base::Milliseconds(10);
25023 HttpRequestInfo request;
25024 request.method = "POST";
25025 request.url = GURL("https://www.example.org/");
25026 request.traffic_annotation =
25027 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
25028
25029 MockWrite data_writes[] = {
25030 MockWrite(SYNCHRONOUS,
25031 "POST / HTTP/1.1\r\n"
25032 "Host: www.example.org\r\n"
25033 "Connection: keep-alive\r\n"
25034 "Content-Length: 0\r\n\r\n"),
25035 };
25036
25037 MockRead data_reads[] = {
25038 MockRead("HTTP/1.1 200 OK\r\n"),
25039 MockRead("Content-Length: 1\r\n\r\n"),
25040 MockRead(SYNCHRONOUS, "1"),
25041 };
25042
25043 StaticSocketDataProvider data(data_reads, data_writes);
25044 session_deps_.socket_factory->AddSocketDataProvider(&data);
25045 SSLSocketDataProvider ssl(SYNCHRONOUS, OK);
25046 ssl.connect_callback = FastForwardByCallback(kDelay);
25047 ssl.confirm = MockConfirm(ASYNC, OK);
25048 ssl.confirm_callback = FastForwardByCallback(kDelay);
25049 session_deps_.enable_early_data = true;
25050 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
25051
25052 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
25053
25054 TestCompletionCallback callback;
25055 auto trans =
25056 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
25057
25058 base::TimeTicks start_time = base::TimeTicks::Now();
25059 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
25060 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
25061
25062 rv = callback.WaitForResult();
25063 EXPECT_THAT(rv, IsOk());
25064
25065 const HttpResponseInfo* response = trans->GetResponseInfo();
25066 ASSERT_TRUE(response);
25067 ASSERT_TRUE(response->headers);
25068 EXPECT_EQ(200, response->headers->response_code());
25069 EXPECT_EQ(1, response->headers->GetContentLength());
25070
25071 // Check that the Write didn't get called before ConfirmHandshake completed.
25072 ASSERT_FALSE(ssl.WriteBeforeConfirm());
25073
25074 // The handshake time should include the time it took to run Connect() and
25075 // ConfirmHandshake().
25076 LoadTimingInfo load_timing_info;
25077 EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
25078 EXPECT_EQ(load_timing_info.connect_timing.connect_start, start_time);
25079 EXPECT_EQ(load_timing_info.connect_timing.ssl_start, start_time);
25080 EXPECT_EQ(load_timing_info.connect_timing.ssl_end, start_time + 2 * kDelay);
25081 EXPECT_EQ(load_timing_info.connect_timing.connect_end,
25082 start_time + 2 * kDelay);
25083
25084 trans.reset();
25085
25086 session->CloseAllConnections(ERR_FAILED, "Very good reason");
25087 }
25088
TEST_P(HttpNetworkTransactionTest,ZeroRTTAsyncConfirmAsyncWrite)25089 TEST_P(HttpNetworkTransactionTest, ZeroRTTAsyncConfirmAsyncWrite) {
25090 HttpRequestInfo request;
25091 request.method = "POST";
25092 request.url = GURL("https://www.example.org/");
25093 request.traffic_annotation =
25094 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
25095
25096 MockWrite data_writes[] = {
25097 MockWrite(ASYNC,
25098 "POST / HTTP/1.1\r\n"
25099 "Host: www.example.org\r\n"
25100 "Connection: keep-alive\r\n"
25101 "Content-Length: 0\r\n\r\n"),
25102 };
25103
25104 MockRead data_reads[] = {
25105 MockRead("HTTP/1.1 200 OK\r\n"),
25106 MockRead("Content-Length: 1\r\n\r\n"),
25107 MockRead(SYNCHRONOUS, "1"),
25108 };
25109
25110 StaticSocketDataProvider data(data_reads, data_writes);
25111 session_deps_.socket_factory->AddSocketDataProvider(&data);
25112 SSLSocketDataProvider ssl(SYNCHRONOUS, OK);
25113 ssl.confirm = MockConfirm(ASYNC, OK);
25114 session_deps_.enable_early_data = true;
25115 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
25116
25117 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
25118
25119 TestCompletionCallback callback;
25120 auto trans =
25121 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
25122
25123 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
25124 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
25125
25126 rv = callback.WaitForResult();
25127 EXPECT_THAT(rv, IsOk());
25128
25129 const HttpResponseInfo* response = trans->GetResponseInfo();
25130 ASSERT_TRUE(response);
25131 ASSERT_TRUE(response->headers);
25132 EXPECT_EQ(200, response->headers->response_code());
25133 EXPECT_EQ(1, response->headers->GetContentLength());
25134
25135 // Check that the Write didn't get called before ConfirmHandshake completed.
25136 ASSERT_FALSE(ssl.WriteBeforeConfirm());
25137
25138 trans.reset();
25139
25140 session->CloseAllConnections(ERR_FAILED, "Very good reason");
25141 }
25142
25143 // 0-RTT rejects are handled at HttpNetworkTransaction.
TEST_P(HttpNetworkTransactionTest,ZeroRTTReject)25144 TEST_P(HttpNetworkTransactionTest, ZeroRTTReject) {
25145 enum class RejectType {
25146 kRead,
25147 kWrite,
25148 kConfirm,
25149 };
25150
25151 for (RejectType type :
25152 {RejectType::kRead, RejectType::kWrite, RejectType::kConfirm}) {
25153 SCOPED_TRACE(static_cast<int>(type));
25154 for (Error reject_error :
25155 {ERR_EARLY_DATA_REJECTED, ERR_WRONG_VERSION_ON_EARLY_DATA}) {
25156 SCOPED_TRACE(reject_error);
25157 session_deps_.socket_factory =
25158 std::make_unique<MockClientSocketFactory>();
25159
25160 HttpRequestInfo request;
25161 request.method = type == RejectType::kConfirm ? "POST" : "GET";
25162 request.url = GURL("https://www.example.org/");
25163 request.traffic_annotation =
25164 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
25165
25166 // The first request fails.
25167 std::vector<MockWrite> data1_writes;
25168 std::vector<MockRead> data1_reads;
25169 SSLSocketDataProvider ssl1(SYNCHRONOUS, OK);
25170 switch (type) {
25171 case RejectType::kRead:
25172 data1_writes.emplace_back(
25173 "GET / HTTP/1.1\r\n"
25174 "Host: www.example.org\r\n"
25175 "Connection: keep-alive\r\n\r\n");
25176 data1_reads.emplace_back(ASYNC, reject_error);
25177 // Cause ConfirmHandshake to hang (it should not be called).
25178 ssl1.confirm = MockConfirm(SYNCHRONOUS, ERR_IO_PENDING);
25179 break;
25180 case RejectType::kWrite:
25181 data1_writes.emplace_back(ASYNC, reject_error);
25182 // Cause ConfirmHandshake to hang (it should not be called).
25183 ssl1.confirm = MockConfirm(SYNCHRONOUS, ERR_IO_PENDING);
25184 break;
25185 case RejectType::kConfirm:
25186 // The request never gets far enough to read or write.
25187 ssl1.confirm = MockConfirm(ASYNC, reject_error);
25188 break;
25189 }
25190
25191 StaticSocketDataProvider data1(data1_reads, data1_writes);
25192 session_deps_.socket_factory->AddSocketDataProvider(&data1);
25193 session_deps_.enable_early_data = true;
25194 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl1);
25195
25196 // The retry succeeds.
25197 //
25198 // TODO(https://crbug.com/950705): If |reject_error| is
25199 // ERR_EARLY_DATA_REJECTED, the retry should happen over the same socket.
25200 MockWrite data2_writes[] = {
25201 request.method == "POST"
25202 ? MockWrite("POST / HTTP/1.1\r\n"
25203 "Host: www.example.org\r\n"
25204 "Connection: keep-alive\r\n"
25205 "Content-Length: 0\r\n\r\n")
25206 : MockWrite("GET / HTTP/1.1\r\n"
25207 "Host: www.example.org\r\n"
25208 "Connection: keep-alive\r\n\r\n"),
25209 };
25210
25211 MockRead data2_reads[] = {
25212 MockRead("HTTP/1.1 200 OK\r\n"),
25213 MockRead("Content-Length: 1\r\n\r\n"),
25214 MockRead(SYNCHRONOUS, "1"),
25215 };
25216
25217 StaticSocketDataProvider data2(data2_reads, data2_writes);
25218 session_deps_.socket_factory->AddSocketDataProvider(&data2);
25219 SSLSocketDataProvider ssl2(SYNCHRONOUS, OK);
25220 ssl2.confirm = MockConfirm(ASYNC, OK);
25221 session_deps_.enable_early_data = true;
25222 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
25223
25224 std::unique_ptr<HttpNetworkSession> session(
25225 CreateSession(&session_deps_));
25226
25227 TestCompletionCallback callback;
25228 auto trans = std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY,
25229 session.get());
25230
25231 EXPECT_THAT(callback.GetResult(trans->Start(&request, callback.callback(),
25232 NetLogWithSource())),
25233 IsOk());
25234
25235 const HttpResponseInfo* response = trans->GetResponseInfo();
25236 ASSERT_TRUE(response);
25237 ASSERT_TRUE(response->headers);
25238 EXPECT_EQ(200, response->headers->response_code());
25239 EXPECT_EQ(1, response->headers->GetContentLength());
25240 }
25241 }
25242 }
25243
TEST_P(HttpNetworkTransactionTest,ZeroRTTConfirmErrorSync)25244 TEST_P(HttpNetworkTransactionTest, ZeroRTTConfirmErrorSync) {
25245 HttpRequestInfo request;
25246 request.method = "POST";
25247 request.url = GURL("https://www.example.org/");
25248 request.traffic_annotation =
25249 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
25250
25251 MockWrite data_writes[] = {
25252 MockWrite("POST / HTTP/1.1\r\n"
25253 "Host: www.example.org\r\n"
25254 "Connection: keep-alive\r\n"
25255 "Content-Length: 0\r\n\r\n"),
25256 };
25257
25258 MockRead data_reads[] = {
25259 MockRead("HTTP/1.1 200 OK\r\n"),
25260 MockRead("Content-Length: 1\r\n\r\n"),
25261 MockRead(SYNCHRONOUS, "1"),
25262 };
25263
25264 StaticSocketDataProvider data(data_reads, data_writes);
25265 session_deps_.socket_factory->AddSocketDataProvider(&data);
25266 SSLSocketDataProvider ssl(SYNCHRONOUS, OK);
25267 ssl.confirm = MockConfirm(SYNCHRONOUS, ERR_SSL_PROTOCOL_ERROR);
25268 session_deps_.enable_early_data = true;
25269 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
25270
25271 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
25272
25273 TestCompletionCallback callback;
25274 auto trans =
25275 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
25276
25277 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
25278 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
25279
25280 rv = callback.WaitForResult();
25281 EXPECT_THAT(rv, IsError(ERR_SSL_PROTOCOL_ERROR));
25282
25283 // Check that the Write didn't get called before ConfirmHandshake completed.
25284 ASSERT_FALSE(ssl.WriteBeforeConfirm());
25285
25286 trans.reset();
25287
25288 session->CloseAllConnections(ERR_FAILED, "Very good reason");
25289 }
25290
TEST_P(HttpNetworkTransactionTest,ZeroRTTConfirmErrorAsync)25291 TEST_P(HttpNetworkTransactionTest, ZeroRTTConfirmErrorAsync) {
25292 HttpRequestInfo request;
25293 request.method = "POST";
25294 request.url = GURL("https://www.example.org/");
25295 request.traffic_annotation =
25296 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
25297
25298 MockWrite data_writes[] = {
25299 MockWrite("POST / HTTP/1.1\r\n"
25300 "Host: www.example.org\r\n"
25301 "Connection: keep-alive\r\n"
25302 "Content-Length: 0\r\n\r\n"),
25303 };
25304
25305 MockRead data_reads[] = {
25306 MockRead("HTTP/1.1 200 OK\r\n"),
25307 MockRead("Content-Length: 1\r\n\r\n"),
25308 MockRead(SYNCHRONOUS, "1"),
25309 };
25310
25311 StaticSocketDataProvider data(data_reads, data_writes);
25312 session_deps_.socket_factory->AddSocketDataProvider(&data);
25313 SSLSocketDataProvider ssl(SYNCHRONOUS, OK);
25314 ssl.confirm = MockConfirm(ASYNC, ERR_SSL_PROTOCOL_ERROR);
25315 session_deps_.enable_early_data = true;
25316 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
25317
25318 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
25319
25320 TestCompletionCallback callback;
25321 auto trans =
25322 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
25323
25324 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
25325 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
25326
25327 rv = callback.WaitForResult();
25328 EXPECT_THAT(rv, IsError(ERR_SSL_PROTOCOL_ERROR));
25329
25330 // Check that the Write didn't get called before ConfirmHandshake completed.
25331 ASSERT_FALSE(ssl.WriteBeforeConfirm());
25332
25333 trans.reset();
25334
25335 session->CloseAllConnections(ERR_FAILED, "Very good reason");
25336 }
25337
25338 // Test the proxy and origin server each requesting both TLS client certificates
25339 // and HTTP auth. This is a regression test for https://crbug.com/946406.
TEST_P(HttpNetworkTransactionTest,AuthEverything)25340 TEST_P(HttpNetworkTransactionTest, AuthEverything) {
25341 // Note these hosts must match the CheckBasic*Auth() functions.
25342 session_deps_.proxy_resolution_service =
25343 ConfiguredProxyResolutionService::CreateFixedForTest(
25344 "https://myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
25345
25346 auto cert_request_info_proxy = base::MakeRefCounted<SSLCertRequestInfo>();
25347 cert_request_info_proxy->host_and_port = HostPortPair("myproxy", 70);
25348
25349 std::unique_ptr<FakeClientCertIdentity> identity_proxy =
25350 FakeClientCertIdentity::CreateFromCertAndKeyFiles(
25351 GetTestCertsDirectory(), "client_1.pem", "client_1.pk8");
25352 ASSERT_TRUE(identity_proxy);
25353
25354 auto cert_request_info_origin = base::MakeRefCounted<SSLCertRequestInfo>();
25355 cert_request_info_origin->host_and_port =
25356 HostPortPair("www.example.org", 443);
25357
25358 std::unique_ptr<FakeClientCertIdentity> identity_origin =
25359 FakeClientCertIdentity::CreateFromCertAndKeyFiles(
25360 GetTestCertsDirectory(), "client_2.pem", "client_2.pk8");
25361 ASSERT_TRUE(identity_origin);
25362
25363 HttpRequestInfo request;
25364 request.method = "GET";
25365 request.url = GURL("https://www.example.org/");
25366 request.traffic_annotation =
25367 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
25368
25369 // First, the client connects to the proxy, which requests a client
25370 // certificate.
25371 SSLSocketDataProvider ssl_proxy1(ASYNC, ERR_SSL_CLIENT_AUTH_CERT_NEEDED);
25372 ssl_proxy1.cert_request_info = cert_request_info_proxy;
25373 ssl_proxy1.expected_send_client_cert = false;
25374 StaticSocketDataProvider data1;
25375 session_deps_.socket_factory->AddSocketDataProvider(&data1);
25376 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_proxy1);
25377
25378 // The client responds with a certificate on a new connection. The handshake
25379 // succeeds.
25380 SSLSocketDataProvider ssl_proxy2(ASYNC, OK);
25381 ssl_proxy2.expected_send_client_cert = true;
25382 ssl_proxy2.expected_client_cert = identity_proxy->certificate();
25383 // The client attempts an HTTP CONNECT, but the proxy requests basic auth.
25384 std::vector<MockWrite> mock_writes2;
25385 std::vector<MockRead> mock_reads2;
25386 mock_writes2.emplace_back(
25387 "CONNECT www.example.org:443 HTTP/1.1\r\n"
25388 "Host: www.example.org:443\r\n"
25389 "Proxy-Connection: keep-alive\r\n\r\n");
25390 mock_reads2.emplace_back(
25391 "HTTP/1.1 407 Proxy Authentication Required\r\n"
25392 "Content-Length: 0\r\n"
25393 "Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n\r\n");
25394 // The client retries with credentials.
25395 mock_writes2.emplace_back(
25396 "CONNECT www.example.org:443 HTTP/1.1\r\n"
25397 "Host: www.example.org:443\r\n"
25398 "Proxy-Connection: keep-alive\r\n"
25399 // Authenticate as proxyuser:proxypass.
25400 "Proxy-Authorization: Basic cHJveHl1c2VyOnByb3h5cGFzcw==\r\n\r\n");
25401 mock_reads2.emplace_back("HTTP/1.1 200 Connection Established\r\n\r\n");
25402 // The origin requests client certificates.
25403 SSLSocketDataProvider ssl_origin2(ASYNC, ERR_SSL_CLIENT_AUTH_CERT_NEEDED);
25404 ssl_origin2.cert_request_info = cert_request_info_origin;
25405 StaticSocketDataProvider data2(mock_reads2, mock_writes2);
25406 session_deps_.socket_factory->AddSocketDataProvider(&data2);
25407 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_proxy2);
25408 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_origin2);
25409
25410 // The client responds to the origin client certificate request on a new
25411 // connection.
25412 SSLSocketDataProvider ssl_proxy3(ASYNC, OK);
25413 ssl_proxy3.expected_send_client_cert = true;
25414 ssl_proxy3.expected_client_cert = identity_proxy->certificate();
25415 std::vector<MockWrite> mock_writes3;
25416 std::vector<MockRead> mock_reads3;
25417 mock_writes3.emplace_back(
25418 "CONNECT www.example.org:443 HTTP/1.1\r\n"
25419 "Host: www.example.org:443\r\n"
25420 "Proxy-Connection: keep-alive\r\n"
25421 // Authenticate as proxyuser:proxypass.
25422 "Proxy-Authorization: Basic cHJveHl1c2VyOnByb3h5cGFzcw==\r\n\r\n");
25423 mock_reads3.emplace_back("HTTP/1.1 200 Connection Established\r\n\r\n");
25424 SSLSocketDataProvider ssl_origin3(ASYNC, OK);
25425 ssl_origin3.expected_send_client_cert = true;
25426 ssl_origin3.expected_client_cert = identity_origin->certificate();
25427 // The client sends the origin HTTP request, which results in another HTTP
25428 // auth request.
25429 mock_writes3.emplace_back(
25430 "GET / HTTP/1.1\r\n"
25431 "Host: www.example.org\r\n"
25432 "Connection: keep-alive\r\n\r\n");
25433 mock_reads3.emplace_back(
25434 "HTTP/1.1 401 Unauthorized\r\n"
25435 "WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"
25436 "Content-Length: 0\r\n\r\n");
25437 // The client retries with credentials, and the request finally succeeds.
25438 mock_writes3.emplace_back(
25439 "GET / HTTP/1.1\r\n"
25440 "Host: www.example.org\r\n"
25441 "Connection: keep-alive\r\n"
25442 // Authenticate as user:pass.
25443 "Authorization: Basic dXNlcjpwYXNz\r\n\r\n");
25444 mock_reads3.emplace_back(
25445 "HTTP/1.1 200 OK\r\n"
25446 "Content-Length: 0\r\n\r\n");
25447 // The client makes another request. This should reuse the socket with all
25448 // credentials cached.
25449 mock_writes3.emplace_back(
25450 "GET / HTTP/1.1\r\n"
25451 "Host: www.example.org\r\n"
25452 "Connection: keep-alive\r\n"
25453 // Authenticate as user:pass.
25454 "Authorization: Basic dXNlcjpwYXNz\r\n\r\n");
25455 mock_reads3.emplace_back(
25456 "HTTP/1.1 200 OK\r\n"
25457 "Content-Length: 0\r\n\r\n");
25458 StaticSocketDataProvider data3(mock_reads3, mock_writes3);
25459 session_deps_.socket_factory->AddSocketDataProvider(&data3);
25460 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_proxy3);
25461 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_origin3);
25462
25463 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
25464
25465 // Start the request.
25466 TestCompletionCallback callback;
25467 auto trans =
25468 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
25469 int rv = callback.GetResult(
25470 trans->Start(&request, callback.callback(), NetLogWithSource()));
25471
25472 // Handle the proxy client certificate challenge.
25473 ASSERT_THAT(rv, IsError(ERR_SSL_CLIENT_AUTH_CERT_NEEDED));
25474 SSLCertRequestInfo* cert_request_info =
25475 trans->GetResponseInfo()->cert_request_info.get();
25476 ASSERT_TRUE(cert_request_info);
25477 EXPECT_TRUE(cert_request_info->is_proxy);
25478 EXPECT_EQ(cert_request_info->host_and_port,
25479 cert_request_info_proxy->host_and_port);
25480 rv = callback.GetResult(trans->RestartWithCertificate(
25481 identity_proxy->certificate(), identity_proxy->ssl_private_key(),
25482 callback.callback()));
25483
25484 // Handle the proxy HTTP auth challenge.
25485 ASSERT_THAT(rv, IsOk());
25486 EXPECT_EQ(407, trans->GetResponseInfo()->headers->response_code());
25487 EXPECT_TRUE(
25488 CheckBasicSecureProxyAuth(trans->GetResponseInfo()->auth_challenge));
25489 rv = callback.GetResult(trans->RestartWithAuth(
25490 AuthCredentials(u"proxyuser", u"proxypass"), callback.callback()));
25491
25492 // Handle the origin client certificate challenge.
25493 ASSERT_THAT(rv, IsError(ERR_SSL_CLIENT_AUTH_CERT_NEEDED));
25494 cert_request_info = trans->GetResponseInfo()->cert_request_info.get();
25495 ASSERT_TRUE(cert_request_info);
25496 EXPECT_FALSE(cert_request_info->is_proxy);
25497 EXPECT_EQ(cert_request_info->host_and_port,
25498 cert_request_info_origin->host_and_port);
25499 rv = callback.GetResult(trans->RestartWithCertificate(
25500 identity_origin->certificate(), identity_origin->ssl_private_key(),
25501 callback.callback()));
25502
25503 // Handle the origin HTTP auth challenge.
25504 ASSERT_THAT(rv, IsOk());
25505 EXPECT_EQ(401, trans->GetResponseInfo()->headers->response_code());
25506 EXPECT_TRUE(
25507 CheckBasicSecureServerAuth(trans->GetResponseInfo()->auth_challenge));
25508 rv = callback.GetResult(trans->RestartWithAuth(
25509 AuthCredentials(u"user", u"pass"), callback.callback()));
25510
25511 // The request completes.
25512 ASSERT_THAT(rv, IsOk());
25513 EXPECT_EQ(200, trans->GetResponseInfo()->headers->response_code());
25514
25515 // Make a second request. This time all credentials are cached.
25516 trans =
25517 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
25518 ASSERT_THAT(callback.GetResult(trans->Start(&request, callback.callback(),
25519 NetLogWithSource())),
25520 IsOk());
25521 EXPECT_EQ(200, trans->GetResponseInfo()->headers->response_code());
25522 }
25523
25524 // Test the proxy and origin server each requesting both TLS client certificates
25525 // and HTTP auth and each HTTP auth closing the connection. This is a regression
25526 // test for https://crbug.com/946406.
TEST_P(HttpNetworkTransactionTest,AuthEverythingWithConnectClose)25527 TEST_P(HttpNetworkTransactionTest, AuthEverythingWithConnectClose) {
25528 // Note these hosts must match the CheckBasic*Auth() functions.
25529 session_deps_.proxy_resolution_service =
25530 ConfiguredProxyResolutionService::CreateFixedForTest(
25531 "https://myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
25532
25533 auto cert_request_info_proxy = base::MakeRefCounted<SSLCertRequestInfo>();
25534 cert_request_info_proxy->host_and_port = HostPortPair("myproxy", 70);
25535
25536 std::unique_ptr<FakeClientCertIdentity> identity_proxy =
25537 FakeClientCertIdentity::CreateFromCertAndKeyFiles(
25538 GetTestCertsDirectory(), "client_1.pem", "client_1.pk8");
25539 ASSERT_TRUE(identity_proxy);
25540
25541 auto cert_request_info_origin = base::MakeRefCounted<SSLCertRequestInfo>();
25542 cert_request_info_origin->host_and_port =
25543 HostPortPair("www.example.org", 443);
25544
25545 std::unique_ptr<FakeClientCertIdentity> identity_origin =
25546 FakeClientCertIdentity::CreateFromCertAndKeyFiles(
25547 GetTestCertsDirectory(), "client_2.pem", "client_2.pk8");
25548 ASSERT_TRUE(identity_origin);
25549
25550 HttpRequestInfo request;
25551 request.method = "GET";
25552 request.url = GURL("https://www.example.org/");
25553 request.traffic_annotation =
25554 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
25555
25556 // First, the client connects to the proxy, which requests a client
25557 // certificate.
25558 SSLSocketDataProvider ssl_proxy1(ASYNC, ERR_SSL_CLIENT_AUTH_CERT_NEEDED);
25559 ssl_proxy1.cert_request_info = cert_request_info_proxy;
25560 ssl_proxy1.expected_send_client_cert = false;
25561 StaticSocketDataProvider data1;
25562 session_deps_.socket_factory->AddSocketDataProvider(&data1);
25563 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_proxy1);
25564
25565 // The client responds with a certificate on a new connection. The handshake
25566 // succeeds.
25567 SSLSocketDataProvider ssl_proxy2(ASYNC, OK);
25568 ssl_proxy2.expected_send_client_cert = true;
25569 ssl_proxy2.expected_client_cert = identity_proxy->certificate();
25570 // The client attempts an HTTP CONNECT, but the proxy requests basic auth.
25571 std::vector<MockWrite> mock_writes2;
25572 std::vector<MockRead> mock_reads2;
25573 mock_writes2.emplace_back(
25574 "CONNECT www.example.org:443 HTTP/1.1\r\n"
25575 "Host: www.example.org:443\r\n"
25576 "Proxy-Connection: keep-alive\r\n\r\n");
25577 mock_reads2.emplace_back(
25578 "HTTP/1.1 407 Proxy Authentication Required\r\n"
25579 "Content-Length: 0\r\n"
25580 "Proxy-Connection: close\r\n"
25581 "Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n\r\n");
25582 StaticSocketDataProvider data2(mock_reads2, mock_writes2);
25583 session_deps_.socket_factory->AddSocketDataProvider(&data2);
25584 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_proxy2);
25585
25586 // The client retries with credentials on a new connection.
25587 SSLSocketDataProvider ssl_proxy3(ASYNC, OK);
25588 ssl_proxy3.expected_send_client_cert = true;
25589 ssl_proxy3.expected_client_cert = identity_proxy->certificate();
25590 std::vector<MockWrite> mock_writes3;
25591 std::vector<MockRead> mock_reads3;
25592 mock_writes3.emplace_back(
25593 "CONNECT www.example.org:443 HTTP/1.1\r\n"
25594 "Host: www.example.org:443\r\n"
25595 "Proxy-Connection: keep-alive\r\n"
25596 // Authenticate as proxyuser:proxypass.
25597 "Proxy-Authorization: Basic cHJveHl1c2VyOnByb3h5cGFzcw==\r\n\r\n");
25598 mock_reads3.emplace_back("HTTP/1.1 200 Connection Established\r\n\r\n");
25599 // The origin requests client certificates.
25600 SSLSocketDataProvider ssl_origin3(ASYNC, ERR_SSL_CLIENT_AUTH_CERT_NEEDED);
25601 ssl_origin3.cert_request_info = cert_request_info_origin;
25602 StaticSocketDataProvider data3(mock_reads3, mock_writes3);
25603 session_deps_.socket_factory->AddSocketDataProvider(&data3);
25604 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_proxy3);
25605 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_origin3);
25606
25607 // The client responds to the origin client certificate request on a new
25608 // connection.
25609 SSLSocketDataProvider ssl_proxy4(ASYNC, OK);
25610 ssl_proxy4.expected_send_client_cert = true;
25611 ssl_proxy4.expected_client_cert = identity_proxy->certificate();
25612 std::vector<MockWrite> mock_writes4;
25613 std::vector<MockRead> mock_reads4;
25614 mock_writes4.emplace_back(
25615 "CONNECT www.example.org:443 HTTP/1.1\r\n"
25616 "Host: www.example.org:443\r\n"
25617 "Proxy-Connection: keep-alive\r\n"
25618 // Authenticate as proxyuser:proxypass.
25619 "Proxy-Authorization: Basic cHJveHl1c2VyOnByb3h5cGFzcw==\r\n\r\n");
25620 mock_reads4.emplace_back("HTTP/1.1 200 Connection Established\r\n\r\n");
25621 SSLSocketDataProvider ssl_origin4(ASYNC, OK);
25622 ssl_origin4.expected_send_client_cert = true;
25623 ssl_origin4.expected_client_cert = identity_origin->certificate();
25624 // The client sends the origin HTTP request, which results in another HTTP
25625 // auth request and closed connection.
25626 mock_writes4.emplace_back(
25627 "GET / HTTP/1.1\r\n"
25628 "Host: www.example.org\r\n"
25629 "Connection: keep-alive\r\n\r\n");
25630 mock_reads4.emplace_back(
25631 "HTTP/1.1 401 Unauthorized\r\n"
25632 "WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"
25633 "Connection: close\r\n"
25634 "Content-Length: 0\r\n\r\n");
25635 StaticSocketDataProvider data4(mock_reads4, mock_writes4);
25636 session_deps_.socket_factory->AddSocketDataProvider(&data4);
25637 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_proxy4);
25638 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_origin4);
25639
25640 // The client retries with credentials on a new connection, and the request
25641 // finally succeeds.
25642 SSLSocketDataProvider ssl_proxy5(ASYNC, OK);
25643 ssl_proxy5.expected_send_client_cert = true;
25644 ssl_proxy5.expected_client_cert = identity_proxy->certificate();
25645 std::vector<MockWrite> mock_writes5;
25646 std::vector<MockRead> mock_reads5;
25647 mock_writes5.emplace_back(
25648 "CONNECT www.example.org:443 HTTP/1.1\r\n"
25649 "Host: www.example.org:443\r\n"
25650 "Proxy-Connection: keep-alive\r\n"
25651 // Authenticate as proxyuser:proxypass.
25652 "Proxy-Authorization: Basic cHJveHl1c2VyOnByb3h5cGFzcw==\r\n\r\n");
25653 mock_reads5.emplace_back("HTTP/1.1 200 Connection Established\r\n\r\n");
25654 SSLSocketDataProvider ssl_origin5(ASYNC, OK);
25655 ssl_origin5.expected_send_client_cert = true;
25656 ssl_origin5.expected_client_cert = identity_origin->certificate();
25657 mock_writes5.emplace_back(
25658 "GET / HTTP/1.1\r\n"
25659 "Host: www.example.org\r\n"
25660 "Connection: keep-alive\r\n"
25661 // Authenticate as user:pass.
25662 "Authorization: Basic dXNlcjpwYXNz\r\n\r\n");
25663 mock_reads5.emplace_back(
25664 "HTTP/1.1 200 OK\r\n"
25665 "Connection: close\r\n"
25666 "Content-Length: 0\r\n\r\n");
25667 StaticSocketDataProvider data5(mock_reads5, mock_writes5);
25668 session_deps_.socket_factory->AddSocketDataProvider(&data5);
25669 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_proxy5);
25670 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_origin5);
25671
25672 // The client makes a second request. This needs yet another connection, but
25673 // all credentials are cached.
25674 SSLSocketDataProvider ssl_proxy6(ASYNC, OK);
25675 ssl_proxy6.expected_send_client_cert = true;
25676 ssl_proxy6.expected_client_cert = identity_proxy->certificate();
25677 std::vector<MockWrite> mock_writes6;
25678 std::vector<MockRead> mock_reads6;
25679 mock_writes6.emplace_back(
25680 "CONNECT www.example.org:443 HTTP/1.1\r\n"
25681 "Host: www.example.org:443\r\n"
25682 "Proxy-Connection: keep-alive\r\n"
25683 // Authenticate as proxyuser:proxypass.
25684 "Proxy-Authorization: Basic cHJveHl1c2VyOnByb3h5cGFzcw==\r\n\r\n");
25685 mock_reads6.emplace_back("HTTP/1.1 200 Connection Established\r\n\r\n");
25686 SSLSocketDataProvider ssl_origin6(ASYNC, OK);
25687 ssl_origin6.expected_send_client_cert = true;
25688 ssl_origin6.expected_client_cert = identity_origin->certificate();
25689 mock_writes6.emplace_back(
25690 "GET / HTTP/1.1\r\n"
25691 "Host: www.example.org\r\n"
25692 "Connection: keep-alive\r\n"
25693 // Authenticate as user:pass.
25694 "Authorization: Basic dXNlcjpwYXNz\r\n\r\n");
25695 mock_reads6.emplace_back(
25696 "HTTP/1.1 200 OK\r\n"
25697 "Connection: close\r\n"
25698 "Content-Length: 0\r\n\r\n");
25699 StaticSocketDataProvider data6(mock_reads6, mock_writes6);
25700 session_deps_.socket_factory->AddSocketDataProvider(&data6);
25701 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_proxy6);
25702 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_origin6);
25703
25704 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
25705
25706 // Start the request.
25707 TestCompletionCallback callback;
25708 auto trans =
25709 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
25710 int rv = callback.GetResult(
25711 trans->Start(&request, callback.callback(), NetLogWithSource()));
25712
25713 // Handle the proxy client certificate challenge.
25714 ASSERT_THAT(rv, IsError(ERR_SSL_CLIENT_AUTH_CERT_NEEDED));
25715 SSLCertRequestInfo* cert_request_info =
25716 trans->GetResponseInfo()->cert_request_info.get();
25717 ASSERT_TRUE(cert_request_info);
25718 EXPECT_TRUE(cert_request_info->is_proxy);
25719 EXPECT_EQ(cert_request_info->host_and_port,
25720 cert_request_info_proxy->host_and_port);
25721 rv = callback.GetResult(trans->RestartWithCertificate(
25722 identity_proxy->certificate(), identity_proxy->ssl_private_key(),
25723 callback.callback()));
25724
25725 // Handle the proxy HTTP auth challenge.
25726 ASSERT_THAT(rv, IsOk());
25727 EXPECT_EQ(407, trans->GetResponseInfo()->headers->response_code());
25728 EXPECT_TRUE(
25729 CheckBasicSecureProxyAuth(trans->GetResponseInfo()->auth_challenge));
25730 rv = callback.GetResult(trans->RestartWithAuth(
25731 AuthCredentials(u"proxyuser", u"proxypass"), callback.callback()));
25732
25733 // Handle the origin client certificate challenge.
25734 ASSERT_THAT(rv, IsError(ERR_SSL_CLIENT_AUTH_CERT_NEEDED));
25735 cert_request_info = trans->GetResponseInfo()->cert_request_info.get();
25736 ASSERT_TRUE(cert_request_info);
25737 EXPECT_FALSE(cert_request_info->is_proxy);
25738 EXPECT_EQ(cert_request_info->host_and_port,
25739 cert_request_info_origin->host_and_port);
25740 rv = callback.GetResult(trans->RestartWithCertificate(
25741 identity_origin->certificate(), identity_origin->ssl_private_key(),
25742 callback.callback()));
25743
25744 // Handle the origin HTTP auth challenge.
25745 ASSERT_THAT(rv, IsOk());
25746 EXPECT_EQ(401, trans->GetResponseInfo()->headers->response_code());
25747 EXPECT_TRUE(
25748 CheckBasicSecureServerAuth(trans->GetResponseInfo()->auth_challenge));
25749 rv = callback.GetResult(trans->RestartWithAuth(
25750 AuthCredentials(u"user", u"pass"), callback.callback()));
25751
25752 // The request completes.
25753 ASSERT_THAT(rv, IsOk());
25754 EXPECT_EQ(200, trans->GetResponseInfo()->headers->response_code());
25755
25756 // Make a second request. This time all credentials are cached.
25757 trans =
25758 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
25759 ASSERT_THAT(callback.GetResult(trans->Start(&request, callback.callback(),
25760 NetLogWithSource())),
25761 IsOk());
25762 EXPECT_EQ(200, trans->GetResponseInfo()->headers->response_code());
25763 }
25764
25765 // Test the proxy requesting HTTP auth and the server requesting TLS client
25766 // certificates. This is a regression test for https://crbug.com/946406.
TEST_P(HttpNetworkTransactionTest,ProxyHTTPAndServerTLSAuth)25767 TEST_P(HttpNetworkTransactionTest, ProxyHTTPAndServerTLSAuth) {
25768 // Note these hosts must match the CheckBasic*Auth() functions.
25769 session_deps_.proxy_resolution_service =
25770 ConfiguredProxyResolutionService::CreateFixedForTest(
25771 "https://myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
25772
25773 auto cert_request_info_origin = base::MakeRefCounted<SSLCertRequestInfo>();
25774 cert_request_info_origin->host_and_port =
25775 HostPortPair("www.example.org", 443);
25776
25777 std::unique_ptr<FakeClientCertIdentity> identity_origin =
25778 FakeClientCertIdentity::CreateFromCertAndKeyFiles(
25779 GetTestCertsDirectory(), "client_2.pem", "client_2.pk8");
25780 ASSERT_TRUE(identity_origin);
25781
25782 HttpRequestInfo request;
25783 request.method = "GET";
25784 request.url = GURL("https://www.example.org/");
25785 request.traffic_annotation =
25786 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
25787
25788 // The client connects to the proxy. The handshake succeeds.
25789 SSLSocketDataProvider ssl_proxy1(ASYNC, OK);
25790 // The client attempts an HTTP CONNECT, but the proxy requests basic auth.
25791 std::vector<MockWrite> mock_writes1;
25792 std::vector<MockRead> mock_reads1;
25793 mock_writes1.emplace_back(
25794 "CONNECT www.example.org:443 HTTP/1.1\r\n"
25795 "Host: www.example.org:443\r\n"
25796 "Proxy-Connection: keep-alive\r\n\r\n");
25797 mock_reads1.emplace_back(
25798 "HTTP/1.1 407 Proxy Authentication Required\r\n"
25799 "Content-Length: 0\r\n"
25800 "Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n\r\n");
25801 // The client retries with credentials, and the request finally succeeds.
25802 mock_writes1.emplace_back(
25803 "CONNECT www.example.org:443 HTTP/1.1\r\n"
25804 "Host: www.example.org:443\r\n"
25805 "Proxy-Connection: keep-alive\r\n"
25806 // Authenticate as proxyuser:proxypass.
25807 "Proxy-Authorization: Basic cHJveHl1c2VyOnByb3h5cGFzcw==\r\n\r\n");
25808 mock_reads1.emplace_back("HTTP/1.1 200 Connection Established\r\n\r\n");
25809 // The origin requests client certificates.
25810 SSLSocketDataProvider ssl_origin1(ASYNC, ERR_SSL_CLIENT_AUTH_CERT_NEEDED);
25811 ssl_origin1.cert_request_info = cert_request_info_origin;
25812 StaticSocketDataProvider data1(mock_reads1, mock_writes1);
25813 session_deps_.socket_factory->AddSocketDataProvider(&data1);
25814 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_proxy1);
25815 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_origin1);
25816
25817 // The client responds to the origin client certificate request on a new
25818 // connection.
25819 SSLSocketDataProvider ssl_proxy2(ASYNC, OK);
25820 std::vector<MockWrite> mock_writes2;
25821 std::vector<MockRead> mock_reads2;
25822 mock_writes2.emplace_back(
25823 "CONNECT www.example.org:443 HTTP/1.1\r\n"
25824 "Host: www.example.org:443\r\n"
25825 "Proxy-Connection: keep-alive\r\n"
25826 // Authenticate as proxyuser:proxypass.
25827 "Proxy-Authorization: Basic cHJveHl1c2VyOnByb3h5cGFzcw==\r\n\r\n");
25828 mock_reads2.emplace_back("HTTP/1.1 200 Connection Established\r\n\r\n");
25829 SSLSocketDataProvider ssl_origin2(ASYNC, OK);
25830 ssl_origin2.expected_send_client_cert = true;
25831 ssl_origin2.expected_client_cert = identity_origin->certificate();
25832 // The client sends the origin HTTP request, which succeeds.
25833 mock_writes2.emplace_back(
25834 "GET / HTTP/1.1\r\n"
25835 "Host: www.example.org\r\n"
25836 "Connection: keep-alive\r\n\r\n");
25837 mock_reads2.emplace_back(
25838 "HTTP/1.1 200 OK\r\n"
25839 "Content-Length: 0\r\n\r\n");
25840 StaticSocketDataProvider data2(mock_reads2, mock_writes2);
25841 session_deps_.socket_factory->AddSocketDataProvider(&data2);
25842 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_proxy2);
25843 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_origin2);
25844
25845 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
25846
25847 // Start the request.
25848 TestCompletionCallback callback;
25849 auto trans =
25850 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
25851 int rv = callback.GetResult(
25852 trans->Start(&request, callback.callback(), NetLogWithSource()));
25853
25854 // Handle the proxy HTTP auth challenge.
25855 ASSERT_THAT(rv, IsOk());
25856 EXPECT_EQ(407, trans->GetResponseInfo()->headers->response_code());
25857 EXPECT_TRUE(
25858 CheckBasicSecureProxyAuth(trans->GetResponseInfo()->auth_challenge));
25859 rv = callback.GetResult(trans->RestartWithAuth(
25860 AuthCredentials(u"proxyuser", u"proxypass"), callback.callback()));
25861
25862 // Handle the origin client certificate challenge.
25863 ASSERT_THAT(rv, IsError(ERR_SSL_CLIENT_AUTH_CERT_NEEDED));
25864 SSLCertRequestInfo* cert_request_info =
25865 trans->GetResponseInfo()->cert_request_info.get();
25866 ASSERT_TRUE(cert_request_info);
25867 EXPECT_FALSE(cert_request_info->is_proxy);
25868 EXPECT_EQ(cert_request_info->host_and_port,
25869 cert_request_info_origin->host_and_port);
25870 rv = callback.GetResult(trans->RestartWithCertificate(
25871 identity_origin->certificate(), identity_origin->ssl_private_key(),
25872 callback.callback()));
25873
25874 // The request completes.
25875 ASSERT_THAT(rv, IsOk());
25876 EXPECT_EQ(200, trans->GetResponseInfo()->headers->response_code());
25877 }
25878
25879 // Test that socket reuse works with client certificates.
TEST_P(HttpNetworkTransactionTest,ClientCertSocketReuse)25880 TEST_P(HttpNetworkTransactionTest, ClientCertSocketReuse) {
25881 auto cert_request_info = base::MakeRefCounted<SSLCertRequestInfo>();
25882 cert_request_info->host_and_port = HostPortPair("www.example.org", 443);
25883
25884 std::unique_ptr<FakeClientCertIdentity> identity =
25885 FakeClientCertIdentity::CreateFromCertAndKeyFiles(
25886 GetTestCertsDirectory(), "client_1.pem", "client_1.pk8");
25887 ASSERT_TRUE(identity);
25888
25889 HttpRequestInfo request1;
25890 request1.method = "GET";
25891 request1.url = GURL("https://www.example.org/a");
25892 request1.traffic_annotation =
25893 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
25894
25895 HttpRequestInfo request2;
25896 request2.method = "GET";
25897 request2.url = GURL("https://www.example.org/b");
25898 request2.traffic_annotation =
25899 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
25900
25901 // The first connection results in a client certificate request.
25902 StaticSocketDataProvider data1;
25903 session_deps_.socket_factory->AddSocketDataProvider(&data1);
25904 SSLSocketDataProvider ssl1(ASYNC, ERR_SSL_CLIENT_AUTH_CERT_NEEDED);
25905 ssl1.cert_request_info = cert_request_info;
25906 ssl1.expected_send_client_cert = false;
25907 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl1);
25908
25909 // The second connection succeeds and is usable for both requests.
25910 MockWrite mock_writes[] = {
25911 MockWrite("GET /a HTTP/1.1\r\n"
25912 "Host: www.example.org\r\n"
25913 "Connection: keep-alive\r\n\r\n"),
25914 MockWrite("GET /b HTTP/1.1\r\n"
25915 "Host: www.example.org\r\n"
25916 "Connection: keep-alive\r\n\r\n"),
25917 };
25918 MockRead mock_reads[] = {
25919 MockRead("HTTP/1.1 200 OK\r\n"
25920 "Content-Length: 0\r\n\r\n"),
25921 MockRead("HTTP/1.1 200 OK\r\n"
25922 "Content-Length: 0\r\n\r\n"),
25923 };
25924 StaticSocketDataProvider data2(mock_reads, mock_writes);
25925 session_deps_.socket_factory->AddSocketDataProvider(&data2);
25926 SSLSocketDataProvider ssl2(ASYNC, OK);
25927 ssl2.expected_send_client_cert = true;
25928 ssl2.expected_client_cert = identity->certificate();
25929 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
25930
25931 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
25932
25933 // Start the first request. It succeeds after providing client certificates.
25934 TestCompletionCallback callback;
25935 auto trans =
25936 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
25937 ASSERT_THAT(callback.GetResult(trans->Start(&request1, callback.callback(),
25938 NetLogWithSource())),
25939 IsError(ERR_SSL_CLIENT_AUTH_CERT_NEEDED));
25940
25941 SSLCertRequestInfo* info = trans->GetResponseInfo()->cert_request_info.get();
25942 ASSERT_TRUE(info);
25943 EXPECT_FALSE(info->is_proxy);
25944 EXPECT_EQ(info->host_and_port, cert_request_info->host_and_port);
25945
25946 ASSERT_THAT(callback.GetResult(trans->RestartWithCertificate(
25947 identity->certificate(), identity->ssl_private_key(),
25948 callback.callback())),
25949 IsOk());
25950 EXPECT_EQ(200, trans->GetResponseInfo()->headers->response_code());
25951
25952 // Make the second request. It completes without requesting client
25953 // certificates.
25954 trans =
25955 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
25956 ASSERT_THAT(callback.GetResult(trans->Start(&request2, callback.callback(),
25957 NetLogWithSource())),
25958 IsOk());
25959 EXPECT_EQ(200, trans->GetResponseInfo()->headers->response_code());
25960 }
25961
25962 // Test for kPartitionConnectionsByNetworkIsolationKey. Runs 3 requests in
25963 // sequence with two different NetworkAnonymizationKeys, the first and last have
25964 // the same key, the second a different one. Checks that the requests are
25965 // partitioned across sockets as expected.
TEST_P(HttpNetworkTransactionTest,NetworkIsolation)25966 TEST_P(HttpNetworkTransactionTest, NetworkIsolation) {
25967 const SchemefulSite kSite1(GURL("http://origin1/"));
25968 const SchemefulSite kSite2(GURL("http://origin2/"));
25969 const auto network_anonymization_key1 =
25970 net::NetworkAnonymizationKey::CreateSameSite(kSite1);
25971 const auto network_anonymization_key2 =
25972 net::NetworkAnonymizationKey::CreateSameSite(kSite2);
25973 NetworkIsolationKey network_isolation_key1(kSite1, kSite1);
25974 NetworkIsolationKey network_isolation_key2(kSite2, kSite2);
25975
25976 for (bool partition_connections : {false, true}) {
25977 SCOPED_TRACE(partition_connections);
25978
25979 base::test::ScopedFeatureList feature_list;
25980 if (partition_connections) {
25981 feature_list.InitAndEnableFeature(
25982 features::kPartitionConnectionsByNetworkIsolationKey);
25983 } else {
25984 feature_list.InitAndDisableFeature(
25985 features::kPartitionConnectionsByNetworkIsolationKey);
25986 }
25987
25988 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
25989
25990 // Reads and writes for the unpartitioned case, where only one socket is
25991 // used.
25992
25993 const MockWrite kUnpartitionedWrites[] = {
25994 MockWrite("GET /1 HTTP/1.1\r\n"
25995 "Host: foo.test\r\n"
25996 "Connection: keep-alive\r\n\r\n"),
25997 MockWrite("GET /2 HTTP/1.1\r\n"
25998 "Host: foo.test\r\n"
25999 "Connection: keep-alive\r\n\r\n"),
26000 MockWrite("GET /3 HTTP/1.1\r\n"
26001 "Host: foo.test\r\n"
26002 "Connection: keep-alive\r\n\r\n"),
26003 };
26004
26005 const MockRead kUnpartitionedReads[] = {
26006 MockRead("HTTP/1.1 200 OK\r\n"
26007 "Connection: keep-alive\r\n"
26008 "Content-Length: 1\r\n\r\n"
26009 "1"),
26010 MockRead("HTTP/1.1 200 OK\r\n"
26011 "Connection: keep-alive\r\n"
26012 "Content-Length: 1\r\n\r\n"
26013 "2"),
26014 MockRead("HTTP/1.1 200 OK\r\n"
26015 "Connection: keep-alive\r\n"
26016 "Content-Length: 1\r\n\r\n"
26017 "3"),
26018 };
26019
26020 StaticSocketDataProvider unpartitioned_data(kUnpartitionedReads,
26021 kUnpartitionedWrites);
26022
26023 // Reads and writes for the partitioned case, where two sockets are used.
26024
26025 const MockWrite kPartitionedWrites1[] = {
26026 MockWrite("GET /1 HTTP/1.1\r\n"
26027 "Host: foo.test\r\n"
26028 "Connection: keep-alive\r\n\r\n"),
26029 MockWrite("GET /3 HTTP/1.1\r\n"
26030 "Host: foo.test\r\n"
26031 "Connection: keep-alive\r\n\r\n"),
26032 };
26033
26034 const MockRead kPartitionedReads1[] = {
26035 MockRead("HTTP/1.1 200 OK\r\n"
26036 "Connection: keep-alive\r\n"
26037 "Content-Length: 1\r\n\r\n"
26038 "1"),
26039 MockRead("HTTP/1.1 200 OK\r\n"
26040 "Connection: keep-alive\r\n"
26041 "Content-Length: 1\r\n\r\n"
26042 "3"),
26043 };
26044
26045 const MockWrite kPartitionedWrites2[] = {
26046 MockWrite("GET /2 HTTP/1.1\r\n"
26047 "Host: foo.test\r\n"
26048 "Connection: keep-alive\r\n\r\n"),
26049 };
26050
26051 const MockRead kPartitionedReads2[] = {
26052 MockRead("HTTP/1.1 200 OK\r\n"
26053 "Connection: keep-alive\r\n"
26054 "Content-Length: 1\r\n\r\n"
26055 "2"),
26056 };
26057
26058 StaticSocketDataProvider partitioned_data1(kPartitionedReads1,
26059 kPartitionedWrites1);
26060 StaticSocketDataProvider partitioned_data2(kPartitionedReads2,
26061 kPartitionedWrites2);
26062
26063 if (partition_connections) {
26064 session_deps_.socket_factory->AddSocketDataProvider(&partitioned_data1);
26065 session_deps_.socket_factory->AddSocketDataProvider(&partitioned_data2);
26066 } else {
26067 session_deps_.socket_factory->AddSocketDataProvider(&unpartitioned_data);
26068 }
26069
26070 TestCompletionCallback callback;
26071 HttpRequestInfo request1;
26072 request1.method = "GET";
26073 request1.url = GURL("http://foo.test/1");
26074 request1.traffic_annotation =
26075 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
26076 request1.network_isolation_key = network_isolation_key1;
26077 request1.network_anonymization_key = network_anonymization_key1;
26078 auto trans1 = std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY,
26079 session.get());
26080 int rv = trans1->Start(&request1, callback.callback(), NetLogWithSource());
26081 EXPECT_THAT(callback.GetResult(rv), IsOk());
26082 std::string response_data1;
26083 EXPECT_THAT(ReadTransaction(trans1.get(), &response_data1), IsOk());
26084 EXPECT_EQ("1", response_data1);
26085 trans1.reset();
26086
26087 HttpRequestInfo request2;
26088 request2.method = "GET";
26089 request2.url = GURL("http://foo.test/2");
26090 request2.traffic_annotation =
26091 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
26092 request2.network_isolation_key = network_isolation_key2;
26093 request2.network_anonymization_key = network_anonymization_key2;
26094 auto trans2 = std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY,
26095 session.get());
26096 rv = trans2->Start(&request2, callback.callback(), NetLogWithSource());
26097 EXPECT_THAT(callback.GetResult(rv), IsOk());
26098 std::string response_data2;
26099 EXPECT_THAT(ReadTransaction(trans2.get(), &response_data2), IsOk());
26100 EXPECT_EQ("2", response_data2);
26101 trans2.reset();
26102
26103 HttpRequestInfo request3;
26104 request3.method = "GET";
26105 request3.url = GURL("http://foo.test/3");
26106 request3.traffic_annotation =
26107 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
26108 request3.network_isolation_key = network_isolation_key1;
26109 request3.network_anonymization_key = network_anonymization_key1;
26110 auto trans3 = std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY,
26111 session.get());
26112 rv = trans3->Start(&request3, callback.callback(), NetLogWithSource());
26113 EXPECT_THAT(callback.GetResult(rv), IsOk());
26114 std::string response_data3;
26115 EXPECT_THAT(ReadTransaction(trans3.get(), &response_data3), IsOk());
26116 EXPECT_EQ("3", response_data3);
26117 trans3.reset();
26118 }
26119 }
26120
TEST_P(HttpNetworkTransactionTest,NetworkIsolationH2)26121 TEST_P(HttpNetworkTransactionTest, NetworkIsolationH2) {
26122 const SchemefulSite kSite1(GURL("http://origin1/"));
26123 const SchemefulSite kSite2(GURL("http://origin2/"));
26124 const auto network_anonymization_key1 =
26125 net::NetworkAnonymizationKey::CreateSameSite(kSite1);
26126 const auto network_anonymization_key2 =
26127 net::NetworkAnonymizationKey::CreateSameSite(kSite2);
26128 NetworkIsolationKey network_isolation_key1(kSite1, kSite1);
26129 NetworkIsolationKey network_isolation_key2(kSite2, kSite2);
26130
26131 // Whether to use an H2 proxy. When false, uses HTTPS H2 requests without a
26132 // proxy, when true, uses HTTP requests over an H2 proxy. It's unnecessary to
26133 // test tunneled HTTPS over an H2 proxy, since that path sets up H2 sessions
26134 // the same way as the HTTP over H2 proxy case.
26135 for (bool use_proxy : {false, true}) {
26136 SCOPED_TRACE(use_proxy);
26137 if (use_proxy) {
26138 session_deps_.proxy_resolution_service =
26139 ConfiguredProxyResolutionService::CreateFixedFromPacResultForTest(
26140 "HTTPS proxy:443", TRAFFIC_ANNOTATION_FOR_TESTS);
26141 } else {
26142 session_deps_.proxy_resolution_service =
26143 ConfiguredProxyResolutionService::CreateDirect();
26144 }
26145 const char* url1 = nullptr;
26146 const char* url2 = nullptr;
26147 const char* url3 = nullptr;
26148 if (use_proxy) {
26149 url1 = "http://foo.test/1";
26150 url2 = "http://foo.test/2";
26151 url3 = "http://foo.test/3";
26152 } else {
26153 url1 = "https://foo.test/1";
26154 url2 = "https://foo.test/2";
26155 url3 = "https://foo.test/3";
26156 }
26157
26158 for (bool partition_connections : {false, true}) {
26159 SCOPED_TRACE(partition_connections);
26160
26161 base::test::ScopedFeatureList feature_list;
26162 if (partition_connections) {
26163 feature_list.InitAndEnableFeature(
26164 features::kPartitionConnectionsByNetworkIsolationKey);
26165 } else {
26166 feature_list.InitAndDisableFeature(
26167 features::kPartitionConnectionsByNetworkIsolationKey);
26168 }
26169
26170 std::unique_ptr<HttpNetworkSession> session(
26171 CreateSession(&session_deps_));
26172
26173 // Reads and writes for the unpartitioned case, where only one socket is
26174 // used.
26175
26176 SpdyTestUtil spdy_util(/*use_priority_header=*/true);
26177 spdy::SpdySerializedFrame unpartitioned_req1(
26178 spdy_util.ConstructSpdyGet(url1, 1, LOWEST));
26179 spdy::SpdySerializedFrame unpartitioned_response1(
26180 spdy_util.ConstructSpdyGetReply(nullptr, 0, 1));
26181 spdy::SpdySerializedFrame unpartitioned_body1(
26182 spdy_util.ConstructSpdyDataFrame(1, "1", true));
26183 spdy_util.UpdateWithStreamDestruction(1);
26184
26185 spdy::SpdySerializedFrame unpartitioned_req2(
26186 spdy_util.ConstructSpdyGet(url2, 3, LOWEST));
26187 spdy::SpdySerializedFrame unpartitioned_response2(
26188 spdy_util.ConstructSpdyGetReply(nullptr, 0, 3));
26189 spdy::SpdySerializedFrame unpartitioned_body2(
26190 spdy_util.ConstructSpdyDataFrame(3, "2", true));
26191 spdy_util.UpdateWithStreamDestruction(3);
26192
26193 spdy::SpdySerializedFrame unpartitioned_req3(
26194 spdy_util.ConstructSpdyGet(url3, 5, LOWEST));
26195 spdy::SpdySerializedFrame unpartitioned_response3(
26196 spdy_util.ConstructSpdyGetReply(nullptr, 0, 5));
26197 spdy::SpdySerializedFrame unpartitioned_body3(
26198 spdy_util.ConstructSpdyDataFrame(5, "3", true));
26199
26200 const MockWrite kUnpartitionedWrites[] = {
26201 CreateMockWrite(unpartitioned_req1, 0),
26202 CreateMockWrite(unpartitioned_req2, 3),
26203 CreateMockWrite(unpartitioned_req3, 6),
26204 };
26205
26206 const MockRead kUnpartitionedReads[] = {
26207 CreateMockRead(unpartitioned_response1, 1),
26208 CreateMockRead(unpartitioned_body1, 2),
26209 CreateMockRead(unpartitioned_response2, 4),
26210 CreateMockRead(unpartitioned_body2, 5),
26211 CreateMockRead(unpartitioned_response3, 7),
26212 CreateMockRead(unpartitioned_body3, 8),
26213 MockRead(SYNCHRONOUS, ERR_IO_PENDING, 9),
26214 };
26215
26216 SequencedSocketData unpartitioned_data(kUnpartitionedReads,
26217 kUnpartitionedWrites);
26218
26219 // Reads and writes for the partitioned case, where two sockets are used.
26220
26221 SpdyTestUtil spdy_util2(/*use_priority_header=*/true);
26222 spdy::SpdySerializedFrame partitioned_req1(
26223 spdy_util2.ConstructSpdyGet(url1, 1, LOWEST));
26224 spdy::SpdySerializedFrame partitioned_response1(
26225 spdy_util2.ConstructSpdyGetReply(nullptr, 0, 1));
26226 spdy::SpdySerializedFrame partitioned_body1(
26227 spdy_util2.ConstructSpdyDataFrame(1, "1", true));
26228 spdy_util2.UpdateWithStreamDestruction(1);
26229
26230 spdy::SpdySerializedFrame partitioned_req3(
26231 spdy_util2.ConstructSpdyGet(url3, 3, LOWEST));
26232 spdy::SpdySerializedFrame partitioned_response3(
26233 spdy_util2.ConstructSpdyGetReply(nullptr, 0, 3));
26234 spdy::SpdySerializedFrame partitioned_body3(
26235 spdy_util2.ConstructSpdyDataFrame(3, "3", true));
26236
26237 const MockWrite kPartitionedWrites1[] = {
26238 CreateMockWrite(partitioned_req1, 0),
26239 CreateMockWrite(partitioned_req3, 3),
26240 };
26241
26242 const MockRead kPartitionedReads1[] = {
26243 CreateMockRead(partitioned_response1, 1),
26244 CreateMockRead(partitioned_body1, 2),
26245 CreateMockRead(partitioned_response3, 4),
26246 CreateMockRead(partitioned_body3, 5),
26247 MockRead(SYNCHRONOUS, ERR_IO_PENDING, 6),
26248 };
26249
26250 SpdyTestUtil spdy_util3(/*use_priority_header=*/true);
26251 spdy::SpdySerializedFrame partitioned_req2(
26252 spdy_util3.ConstructSpdyGet(url2, 1, LOWEST));
26253 spdy::SpdySerializedFrame partitioned_response2(
26254 spdy_util3.ConstructSpdyGetReply(nullptr, 0, 1));
26255 spdy::SpdySerializedFrame partitioned_body2(
26256 spdy_util3.ConstructSpdyDataFrame(1, "2", true));
26257
26258 const MockWrite kPartitionedWrites2[] = {
26259 CreateMockWrite(partitioned_req2, 0),
26260 };
26261
26262 const MockRead kPartitionedReads2[] = {
26263 CreateMockRead(partitioned_response2, 1),
26264 CreateMockRead(partitioned_body2, 2),
26265 MockRead(SYNCHRONOUS, ERR_IO_PENDING, 3),
26266 };
26267
26268 SequencedSocketData partitioned_data1(kPartitionedReads1,
26269 kPartitionedWrites1);
26270 SequencedSocketData partitioned_data2(kPartitionedReads2,
26271 kPartitionedWrites2);
26272
26273 // No need to segment SSLDataProviders by whether or not partitioning is
26274 // enabled.
26275 SSLSocketDataProvider ssl_data1(ASYNC, OK);
26276 ssl_data1.next_proto = kProtoHTTP2;
26277 SSLSocketDataProvider ssl_data2(ASYNC, OK);
26278 ssl_data2.next_proto = kProtoHTTP2;
26279
26280 if (partition_connections) {
26281 session_deps_.socket_factory->AddSocketDataProvider(&partitioned_data1);
26282 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data1);
26283 session_deps_.socket_factory->AddSocketDataProvider(&partitioned_data2);
26284 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data2);
26285 } else {
26286 session_deps_.socket_factory->AddSocketDataProvider(
26287 &unpartitioned_data);
26288 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data1);
26289 }
26290
26291 TestCompletionCallback callback;
26292 HttpRequestInfo request1;
26293 request1.method = "GET";
26294 request1.url = GURL(url1);
26295 request1.traffic_annotation =
26296 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
26297 request1.network_isolation_key = network_isolation_key1;
26298 request1.network_anonymization_key = network_anonymization_key1;
26299
26300 auto trans1 =
26301 std::make_unique<HttpNetworkTransaction>(LOWEST, session.get());
26302 int rv =
26303 trans1->Start(&request1, callback.callback(), NetLogWithSource());
26304 EXPECT_THAT(callback.GetResult(rv), IsOk());
26305 std::string response_data1;
26306 EXPECT_THAT(ReadTransaction(trans1.get(), &response_data1), IsOk());
26307 EXPECT_EQ("1", response_data1);
26308 trans1.reset();
26309
26310 HttpRequestInfo request2;
26311 request2.method = "GET";
26312 request2.url = GURL(url2);
26313 request2.traffic_annotation =
26314 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
26315 request2.network_isolation_key = network_isolation_key2;
26316 request2.network_anonymization_key = network_anonymization_key2;
26317 auto trans2 =
26318 std::make_unique<HttpNetworkTransaction>(LOWEST, session.get());
26319 rv = trans2->Start(&request2, callback.callback(), NetLogWithSource());
26320 EXPECT_THAT(callback.GetResult(rv), IsOk());
26321 std::string response_data2;
26322 EXPECT_THAT(ReadTransaction(trans2.get(), &response_data2), IsOk());
26323 EXPECT_EQ("2", response_data2);
26324 trans2.reset();
26325
26326 HttpRequestInfo request3;
26327 request3.method = "GET";
26328 request3.url = GURL(url3);
26329 request3.traffic_annotation =
26330 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
26331 request3.network_isolation_key = network_isolation_key1;
26332 request3.network_anonymization_key = network_anonymization_key1;
26333
26334 auto trans3 =
26335 std::make_unique<HttpNetworkTransaction>(LOWEST, session.get());
26336 rv = trans3->Start(&request3, callback.callback(), NetLogWithSource());
26337 EXPECT_THAT(callback.GetResult(rv), IsOk());
26338 std::string response_data3;
26339 EXPECT_THAT(ReadTransaction(trans3.get(), &response_data3), IsOk());
26340 EXPECT_EQ("3", response_data3);
26341 trans3.reset();
26342 }
26343 }
26344 }
26345
26346 // Preconnect two sockets with different NetworkAnonymizationKeys when
26347 // features::kPartitionConnectionsByNetworkIsolationKey is enabled. Then
26348 // issue a request and make sure the correct socket is used. Loops three times,
26349 // expecting to use the first preconnect, second preconnect, and neither.
TEST_P(HttpNetworkTransactionTest,NetworkIsolationPreconnect)26350 TEST_P(HttpNetworkTransactionTest, NetworkIsolationPreconnect) {
26351 base::test::ScopedFeatureList feature_list;
26352 feature_list.InitAndEnableFeature(
26353 features::kPartitionConnectionsByNetworkIsolationKey);
26354
26355 enum class TestCase {
26356 kUseFirstPreconnect,
26357 kUseSecondPreconnect,
26358 kDontUsePreconnect,
26359 };
26360
26361 const SchemefulSite kSite1(GURL("http://origin1/"));
26362 const SchemefulSite kSite2(GURL("http://origin2/"));
26363 const SchemefulSite kSite3(GURL("http://origin3/"));
26364 auto preconnect1_anonymization_key =
26365 NetworkAnonymizationKey::CreateSameSite(kSite1);
26366 auto preconnect2_anonymization_key =
26367 NetworkAnonymizationKey::CreateSameSite(kSite2);
26368 auto not_preconnected_anonymization_key =
26369 NetworkAnonymizationKey::CreateSameSite(kSite3);
26370 NetworkIsolationKey preconnect1_isolation_key(kSite1, kSite1);
26371 NetworkIsolationKey preconnect2_isolation_key(kSite2, kSite2);
26372 NetworkIsolationKey not_preconnected_isolation_key(kSite3, kSite3);
26373 // Test that only preconnects with
26374 for (TestCase test_case :
26375 {TestCase::kUseFirstPreconnect, TestCase::kUseSecondPreconnect,
26376 TestCase::kDontUsePreconnect}) {
26377 SpdySessionDependencies session_deps;
26378 // Make DNS lookups completely synchronously, so preconnects complete
26379 // immediately.
26380 session_deps.host_resolver->set_synchronous_mode(true);
26381
26382 const MockWrite kMockWrites[] = {
26383 MockWrite(ASYNC, 0,
26384 "GET / HTTP/1.1\r\n"
26385 "Host: www.foo.com\r\n"
26386 "Connection: keep-alive\r\n\r\n"),
26387 };
26388
26389 const MockRead kMockReads[] = {
26390 MockRead(ASYNC, 1,
26391 "HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"
26392 "hello"),
26393 };
26394
26395 // Used for the socket that will actually be used, which may or may not be
26396 // one of the preconnects
26397 SequencedSocketData used_socket_data(MockConnect(SYNCHRONOUS, OK),
26398 kMockReads, kMockWrites);
26399
26400 // Used for the preconnects that won't actually be used.
26401 SequencedSocketData preconnect1_data(MockConnect(SYNCHRONOUS, OK),
26402 base::span<const MockRead>(),
26403 base::span<const MockWrite>());
26404 SequencedSocketData preconnect2_data(MockConnect(SYNCHRONOUS, OK),
26405 base::span<const MockRead>(),
26406 base::span<const MockWrite>());
26407
26408 NetworkAnonymizationKey network_anonymization_key_for_request;
26409 NetworkIsolationKey network_isolation_key_for_request;
26410
26411 switch (test_case) {
26412 case TestCase::kUseFirstPreconnect:
26413 session_deps.socket_factory->AddSocketDataProvider(&used_socket_data);
26414 session_deps.socket_factory->AddSocketDataProvider(&preconnect2_data);
26415 network_isolation_key_for_request = preconnect1_isolation_key;
26416 network_anonymization_key_for_request = preconnect1_anonymization_key;
26417 break;
26418 case TestCase::kUseSecondPreconnect:
26419 session_deps.socket_factory->AddSocketDataProvider(&preconnect1_data);
26420 session_deps.socket_factory->AddSocketDataProvider(&used_socket_data);
26421 network_isolation_key_for_request = preconnect2_isolation_key;
26422 network_anonymization_key_for_request = preconnect2_anonymization_key;
26423 break;
26424 case TestCase::kDontUsePreconnect:
26425 session_deps.socket_factory->AddSocketDataProvider(&preconnect1_data);
26426 session_deps.socket_factory->AddSocketDataProvider(&preconnect2_data);
26427 session_deps.socket_factory->AddSocketDataProvider(&used_socket_data);
26428 network_isolation_key_for_request = not_preconnected_isolation_key;
26429 network_anonymization_key_for_request =
26430 not_preconnected_anonymization_key;
26431 break;
26432 }
26433
26434 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps));
26435
26436 // Preconnect sockets.
26437 HttpRequestInfo request;
26438 request.method = "GET";
26439 request.url = GURL("http://www.foo.com/");
26440 request.traffic_annotation =
26441 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
26442
26443 request.network_isolation_key = preconnect1_isolation_key;
26444 request.network_anonymization_key = preconnect1_anonymization_key;
26445 session->http_stream_factory()->PreconnectStreams(1, request);
26446
26447 request.network_isolation_key = preconnect2_isolation_key;
26448 request.network_anonymization_key = preconnect2_anonymization_key;
26449 session->http_stream_factory()->PreconnectStreams(1, request);
26450
26451 request.network_isolation_key = network_isolation_key_for_request;
26452 request.network_anonymization_key = network_anonymization_key_for_request;
26453
26454 EXPECT_EQ(2, GetIdleSocketCountInTransportSocketPool(session.get()));
26455
26456 // Make the request.
26457 TestCompletionCallback callback;
26458
26459 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
26460
26461 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
26462 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
26463
26464 rv = callback.WaitForResult();
26465 EXPECT_THAT(rv, IsOk());
26466
26467 const HttpResponseInfo* response = trans.GetResponseInfo();
26468 ASSERT_TRUE(response);
26469 ASSERT_TRUE(response->headers);
26470 EXPECT_EQ(200, response->headers->response_code());
26471
26472 std::string response_data;
26473 rv = ReadTransaction(&trans, &response_data);
26474 EXPECT_THAT(rv, IsOk());
26475 EXPECT_EQ("hello", response_data);
26476
26477 if (test_case != TestCase::kDontUsePreconnect) {
26478 EXPECT_EQ(2, GetIdleSocketCountInTransportSocketPool(session.get()));
26479 } else {
26480 EXPECT_EQ(3, GetIdleSocketCountInTransportSocketPool(session.get()));
26481 }
26482 }
26483 }
26484
26485 // Test that the NetworkAnonymizationKey is passed down to SSLConfig so the
26486 // session cache is isolated.
TEST_P(HttpNetworkTransactionTest,NetworkIsolationSSL)26487 TEST_P(HttpNetworkTransactionTest, NetworkIsolationSSL) {
26488 base::test::ScopedFeatureList feature_list;
26489 feature_list.InitWithFeatures(
26490 {features::kPartitionConnectionsByNetworkIsolationKey,
26491 features::kPartitionSSLSessionsByNetworkIsolationKey},
26492 {});
26493
26494 const SchemefulSite kSite1(GURL("http://origin1/"));
26495 const SchemefulSite kSite2(GURL("http://origin2/"));
26496 const auto kNetworkAnonymizationKey1 =
26497 NetworkAnonymizationKey::CreateSameSite(kSite1);
26498 const net::NetworkIsolationKey kNetworkIsolationKey1(kSite1, kSite1);
26499 const auto kNetworkAnonymizationKey2 =
26500 NetworkAnonymizationKey::CreateSameSite(kSite2);
26501 const net::NetworkIsolationKey kNetworkIsolationKey2(kSite2, kSite2);
26502 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
26503
26504 // The server always sends Connection: close, so each request goes over a
26505 // distinct socket.
26506
26507 const MockWrite kWrites1[] = {
26508 MockWrite("GET /1 HTTP/1.1\r\n"
26509 "Host: foo.test\r\n"
26510 "Connection: keep-alive\r\n\r\n")};
26511
26512 const MockRead kReads1[] = {
26513 MockRead("HTTP/1.1 200 OK\r\n"
26514 "Connection: close\r\n"
26515 "Content-Length: 1\r\n\r\n"
26516 "1")};
26517
26518 const MockWrite kWrites2[] = {
26519 MockWrite("GET /2 HTTP/1.1\r\n"
26520 "Host: foo.test\r\n"
26521 "Connection: keep-alive\r\n\r\n")};
26522
26523 const MockRead kReads2[] = {
26524 MockRead("HTTP/1.1 200 OK\r\n"
26525 "Connection: close\r\n"
26526 "Content-Length: 1\r\n\r\n"
26527 "2")};
26528
26529 const MockWrite kWrites3[] = {
26530 MockWrite("GET /3 HTTP/1.1\r\n"
26531 "Host: foo.test\r\n"
26532 "Connection: keep-alive\r\n\r\n")};
26533
26534 const MockRead kReads3[] = {
26535 MockRead("HTTP/1.1 200 OK\r\n"
26536 "Connection: close\r\n"
26537 "Content-Length: 1\r\n\r\n"
26538 "3")};
26539
26540 StaticSocketDataProvider data1(kReads1, kWrites1);
26541 StaticSocketDataProvider data2(kReads2, kWrites2);
26542 StaticSocketDataProvider data3(kReads3, kWrites3);
26543 session_deps_.socket_factory->AddSocketDataProvider(&data1);
26544 session_deps_.socket_factory->AddSocketDataProvider(&data2);
26545 session_deps_.socket_factory->AddSocketDataProvider(&data3);
26546
26547 SSLSocketDataProvider ssl_data1(ASYNC, OK);
26548 ssl_data1.expected_host_and_port = HostPortPair("foo.test", 443);
26549 ssl_data1.expected_network_anonymization_key = kNetworkAnonymizationKey1;
26550 SSLSocketDataProvider ssl_data2(ASYNC, OK);
26551 ssl_data2.expected_host_and_port = HostPortPair("foo.test", 443);
26552 ssl_data2.expected_network_anonymization_key = kNetworkAnonymizationKey2;
26553 SSLSocketDataProvider ssl_data3(ASYNC, OK);
26554 ssl_data3.expected_host_and_port = HostPortPair("foo.test", 443);
26555 ssl_data3.expected_network_anonymization_key = kNetworkAnonymizationKey1;
26556 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data1);
26557 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data2);
26558 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data3);
26559
26560 TestCompletionCallback callback;
26561 HttpRequestInfo request1;
26562 request1.method = "GET";
26563 request1.url = GURL("https://foo.test/1");
26564 request1.traffic_annotation =
26565 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
26566 request1.network_isolation_key = kNetworkIsolationKey1;
26567 request1.network_anonymization_key = kNetworkAnonymizationKey1;
26568
26569 auto trans1 =
26570 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
26571 int rv = trans1->Start(&request1, callback.callback(), NetLogWithSource());
26572 EXPECT_THAT(callback.GetResult(rv), IsOk());
26573 std::string response_data1;
26574 EXPECT_THAT(ReadTransaction(trans1.get(), &response_data1), IsOk());
26575 EXPECT_EQ("1", response_data1);
26576 trans1.reset();
26577
26578 HttpRequestInfo request2;
26579 request2.method = "GET";
26580 request2.url = GURL("https://foo.test/2");
26581 request2.traffic_annotation =
26582 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
26583 request2.network_isolation_key = kNetworkIsolationKey2;
26584 request2.network_anonymization_key = kNetworkAnonymizationKey2;
26585 auto trans2 =
26586 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
26587 rv = trans2->Start(&request2, callback.callback(), NetLogWithSource());
26588 EXPECT_THAT(callback.GetResult(rv), IsOk());
26589 std::string response_data2;
26590 EXPECT_THAT(ReadTransaction(trans2.get(), &response_data2), IsOk());
26591 EXPECT_EQ("2", response_data2);
26592 trans2.reset();
26593
26594 HttpRequestInfo request3;
26595 request3.method = "GET";
26596 request3.url = GURL("https://foo.test/3");
26597 request3.traffic_annotation =
26598 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
26599 request3.network_isolation_key = kNetworkIsolationKey1;
26600 request3.network_anonymization_key = kNetworkAnonymizationKey1;
26601 auto trans3 =
26602 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
26603 rv = trans3->Start(&request3, callback.callback(), NetLogWithSource());
26604 EXPECT_THAT(callback.GetResult(rv), IsOk());
26605 std::string response_data3;
26606 EXPECT_THAT(ReadTransaction(trans3.get(), &response_data3), IsOk());
26607 EXPECT_EQ("3", response_data3);
26608 trans3.reset();
26609 }
26610
26611 // Test that the NetworkAnonymizationKey is passed down to SSLConfig so the
26612 // session cache is isolated, for both origins and proxies.
TEST_P(HttpNetworkTransactionTest,NetworkIsolationSSLProxy)26613 TEST_P(HttpNetworkTransactionTest, NetworkIsolationSSLProxy) {
26614 base::test::ScopedFeatureList feature_list;
26615 feature_list.InitWithFeatures(
26616 {features::kPartitionConnectionsByNetworkIsolationKey,
26617 features::kPartitionSSLSessionsByNetworkIsolationKey},
26618 {});
26619
26620 session_deps_.proxy_resolution_service =
26621 ConfiguredProxyResolutionService::CreateFixedForTest(
26622 "https://myproxy:70", TRAFFIC_ANNOTATION_FOR_TESTS);
26623
26624 const SchemefulSite kSite1(GURL("http://origin1/"));
26625 const SchemefulSite kSite2(GURL("http://origin2/"));
26626 const auto kNetworkAnonymizationKey1 =
26627 NetworkAnonymizationKey::CreateSameSite(kSite1);
26628 const auto kNetworkAnonymizationKey2 =
26629 NetworkAnonymizationKey::CreateSameSite(kSite2);
26630 const net::NetworkIsolationKey kNetworkIsolationKey1(kSite1, kSite1);
26631 const net::NetworkIsolationKey kNetworkIsolationKey2(kSite2, kSite2);
26632 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
26633
26634 // Make both a tunneled and non-tunneled request.
26635 HttpRequestInfo request1;
26636 request1.method = "GET";
26637 request1.url = GURL("https://foo.test/1");
26638 request1.traffic_annotation =
26639 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
26640 request1.network_isolation_key = kNetworkIsolationKey1;
26641 request1.network_anonymization_key = kNetworkAnonymizationKey1;
26642
26643 HttpRequestInfo request2;
26644 request2.method = "GET";
26645 request2.url = GURL("http://foo.test/2");
26646 request2.traffic_annotation =
26647 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
26648 request2.network_isolation_key = kNetworkIsolationKey2;
26649 request2.network_anonymization_key = kNetworkAnonymizationKey2;
26650
26651 const MockWrite kWrites1[] = {
26652 MockWrite("CONNECT foo.test:443 HTTP/1.1\r\n"
26653 "Host: foo.test:443\r\n"
26654 "Proxy-Connection: keep-alive\r\n\r\n"),
26655 MockWrite("GET /1 HTTP/1.1\r\n"
26656 "Host: foo.test\r\n"
26657 "Connection: keep-alive\r\n\r\n")};
26658
26659 const MockRead kReads1[] = {
26660 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
26661 MockRead("HTTP/1.1 200 OK\r\n"
26662 "Connection: close\r\n"
26663 "Content-Length: 1\r\n\r\n"
26664 "1")};
26665
26666 const MockWrite kWrites2[] = {
26667 MockWrite("GET http://foo.test/2 HTTP/1.1\r\n"
26668 "Host: foo.test\r\n"
26669 "Proxy-Connection: keep-alive\r\n\r\n")};
26670
26671 const MockRead kReads2[] = {
26672 MockRead("HTTP/1.1 200 OK\r\n"
26673 "Connection: close\r\n"
26674 "Content-Length: 1\r\n\r\n"
26675 "2")};
26676
26677 StaticSocketDataProvider data1(kReads1, kWrites1);
26678 StaticSocketDataProvider data2(kReads2, kWrites2);
26679 session_deps_.socket_factory->AddSocketDataProvider(&data1);
26680 session_deps_.socket_factory->AddSocketDataProvider(&data2);
26681 session_deps_.socket_factory->AddSocketDataProvider(&data2);
26682
26683 SSLSocketDataProvider ssl_proxy1(ASYNC, OK);
26684 ssl_proxy1.expected_host_and_port = HostPortPair("myproxy", 70);
26685 ssl_proxy1.expected_network_anonymization_key = kNetworkAnonymizationKey1;
26686 SSLSocketDataProvider ssl_origin1(ASYNC, OK);
26687 ssl_origin1.expected_host_and_port = HostPortPair("foo.test", 443);
26688 ssl_origin1.expected_network_anonymization_key = kNetworkAnonymizationKey1;
26689 SSLSocketDataProvider ssl_proxy2(ASYNC, OK);
26690 ssl_proxy2.expected_host_and_port = HostPortPair("myproxy", 70);
26691 ssl_proxy2.expected_network_anonymization_key = kNetworkAnonymizationKey2;
26692 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_proxy1);
26693 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_origin1);
26694 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_proxy2);
26695
26696 TestCompletionCallback callback;
26697 auto trans1 =
26698 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
26699 int rv = trans1->Start(&request1, callback.callback(), NetLogWithSource());
26700 EXPECT_THAT(callback.GetResult(rv), IsOk());
26701 std::string response_data1;
26702 EXPECT_THAT(ReadTransaction(trans1.get(), &response_data1), IsOk());
26703 EXPECT_EQ("1", response_data1);
26704 trans1.reset();
26705
26706 auto trans2 =
26707 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
26708 rv = trans2->Start(&request2, callback.callback(), NetLogWithSource());
26709 EXPECT_THAT(callback.GetResult(rv), IsOk());
26710 std::string response_data2;
26711 EXPECT_THAT(ReadTransaction(trans2.get(), &response_data2), IsOk());
26712 EXPECT_EQ("2", response_data2);
26713 trans2.reset();
26714 }
26715
26716 // Test that SSLConfig changes from SSLConfigService are picked up even when
26717 // there are live sockets.
TEST_P(HttpNetworkTransactionTest,SSLConfigChanged)26718 TEST_P(HttpNetworkTransactionTest, SSLConfigChanged) {
26719 SSLContextConfig ssl_context_config;
26720 ssl_context_config.version_max = SSL_PROTOCOL_VERSION_TLS1_3;
26721 auto ssl_config_service =
26722 std::make_unique<TestSSLConfigService>(ssl_context_config);
26723 TestSSLConfigService* ssl_config_service_raw = ssl_config_service.get();
26724
26725 session_deps_.ssl_config_service = std::move(ssl_config_service);
26726
26727 // Make three requests. Between the second and third, the SSL config will
26728 // change.
26729 HttpRequestInfo request1;
26730 request1.method = "GET";
26731 request1.url = GURL("https://foo.test/1");
26732 request1.traffic_annotation =
26733 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
26734
26735 HttpRequestInfo request2;
26736 request2.method = "GET";
26737 request2.url = GURL("https://foo.test/2");
26738 request2.traffic_annotation =
26739 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
26740
26741 HttpRequestInfo request3;
26742 request3.method = "GET";
26743 request3.url = GURL("https://foo.test/3");
26744 request3.traffic_annotation =
26745 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
26746
26747 const MockWrite kWrites1[] = {
26748 MockWrite("GET /1 HTTP/1.1\r\n"
26749 "Host: foo.test\r\n"
26750 "Connection: keep-alive\r\n\r\n"),
26751 MockWrite("GET /2 HTTP/1.1\r\n"
26752 "Host: foo.test\r\n"
26753 "Connection: keep-alive\r\n\r\n"),
26754 };
26755
26756 const MockRead kReads1[] = {
26757 MockRead("HTTP/1.1 200 OK\r\n"
26758 "Connection: keep-alive\r\n"
26759 "Content-Length: 1\r\n\r\n"
26760 "1"),
26761 MockRead("HTTP/1.1 200 OK\r\n"
26762 "Connection: keep-alive\r\n"
26763 "Content-Length: 1\r\n\r\n"
26764 "2"),
26765 };
26766
26767 // The third request goes on a different socket because the SSL config has
26768 // changed.
26769 const MockWrite kWrites2[] = {
26770 MockWrite("GET /3 HTTP/1.1\r\n"
26771 "Host: foo.test\r\n"
26772 "Connection: keep-alive\r\n\r\n")};
26773
26774 const MockRead kReads2[] = {
26775 MockRead("HTTP/1.1 200 OK\r\n"
26776 "Connection: keep-alive\r\n"
26777 "Content-Length: 1\r\n\r\n"
26778 "3")};
26779
26780 StaticSocketDataProvider data1(kReads1, kWrites1);
26781 StaticSocketDataProvider data2(kReads2, kWrites2);
26782 session_deps_.socket_factory->AddSocketDataProvider(&data1);
26783 session_deps_.socket_factory->AddSocketDataProvider(&data2);
26784
26785 SSLSocketDataProvider ssl1(ASYNC, OK);
26786 ssl1.expected_ssl_version_max = SSL_PROTOCOL_VERSION_TLS1_3;
26787 SSLSocketDataProvider ssl2(ASYNC, OK);
26788 ssl2.expected_ssl_version_max = SSL_PROTOCOL_VERSION_TLS1_2;
26789 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl1);
26790 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
26791
26792 std::unique_ptr<HttpNetworkSession> session = CreateSession(&session_deps_);
26793
26794 TestCompletionCallback callback;
26795 auto trans1 =
26796 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
26797 int rv = trans1->Start(&request1, callback.callback(), NetLogWithSource());
26798 EXPECT_THAT(callback.GetResult(rv), IsOk());
26799 std::string response_data1;
26800 EXPECT_THAT(ReadTransaction(trans1.get(), &response_data1), IsOk());
26801 EXPECT_EQ("1", response_data1);
26802 trans1.reset();
26803
26804 auto trans2 =
26805 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
26806 rv = trans2->Start(&request2, callback.callback(), NetLogWithSource());
26807 EXPECT_THAT(callback.GetResult(rv), IsOk());
26808 std::string response_data2;
26809 EXPECT_THAT(ReadTransaction(trans2.get(), &response_data2), IsOk());
26810 EXPECT_EQ("2", response_data2);
26811 trans2.reset();
26812
26813 ssl_context_config.version_max = SSL_PROTOCOL_VERSION_TLS1_2;
26814 ssl_config_service_raw->UpdateSSLConfigAndNotify(ssl_context_config);
26815
26816 auto trans3 =
26817 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
26818 rv = trans3->Start(&request3, callback.callback(), NetLogWithSource());
26819 EXPECT_THAT(callback.GetResult(rv), IsOk());
26820 std::string response_data3;
26821 EXPECT_THAT(ReadTransaction(trans3.get(), &response_data3), IsOk());
26822 EXPECT_EQ("3", response_data3);
26823 trans3.reset();
26824 }
26825
TEST_P(HttpNetworkTransactionTest,SSLConfigChangedDuringTransaction)26826 TEST_P(HttpNetworkTransactionTest, SSLConfigChangedDuringTransaction) {
26827 SSLContextConfig ssl_context_config;
26828 ssl_context_config.version_max = SSL_PROTOCOL_VERSION_TLS1_3;
26829 auto ssl_config_service =
26830 std::make_unique<TestSSLConfigService>(ssl_context_config);
26831 TestSSLConfigService* ssl_config_service_raw = ssl_config_service.get();
26832 session_deps_.ssl_config_service = std::move(ssl_config_service);
26833
26834 // First request will start connecting before SSLConfig change.
26835 HttpRequestInfo request1;
26836 request1.method = "GET";
26837 request1.url = GURL("https://foo.test/1");
26838 request1.traffic_annotation =
26839 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
26840
26841 const MockWrite kWrites1[] = {
26842 MockWrite("GET /1 HTTP/1.1\r\n"
26843 "Host: foo.test\r\n"
26844 "Connection: keep-alive\r\n\r\n"),
26845 };
26846 const MockRead kReads1[] = {
26847 MockRead(ASYNC, ERR_IO_PENDING, 1),
26848 MockRead(ASYNC, 2,
26849 "HTTP/1.1 200 OK\r\n"
26850 "Connection: keep-alive\r\n"
26851 "Content-Length: 1\r\n\r\n"
26852 "1"),
26853 };
26854
26855 // Second request will be after SSLConfig changes so it should be on a new
26856 // socket.
26857 HttpRequestInfo request2;
26858 request2.method = "GET";
26859 request2.url = GURL("https://foo.test/2");
26860 request2.traffic_annotation =
26861 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
26862
26863 const MockWrite kWrites2[] = {
26864 MockWrite("GET /2 HTTP/1.1\r\n"
26865 "Host: foo.test\r\n"
26866 "Connection: keep-alive\r\n\r\n")};
26867
26868 const MockRead kReads2[] = {
26869 MockRead("HTTP/1.1 200 OK\r\n"
26870 "Connection: keep-alive\r\n"
26871 "Content-Length: 1\r\n\r\n"
26872 "2")};
26873
26874 SequencedSocketData data1(kReads1, kWrites1);
26875 StaticSocketDataProvider data2(kReads2, kWrites2);
26876 session_deps_.socket_factory->AddSocketDataProvider(&data1);
26877 session_deps_.socket_factory->AddSocketDataProvider(&data2);
26878
26879 SSLSocketDataProvider ssl1(ASYNC, OK);
26880 // 1st request starts before config change, so should see the initial
26881 // SSLConfig.
26882 ssl1.expected_ssl_version_max = SSL_PROTOCOL_VERSION_TLS1_3;
26883
26884 SSLSocketDataProvider ssl2(ASYNC, OK);
26885 // 2nd request should be made on a new socket after config change, so should
26886 // see the new SSLConfig.
26887 ssl2.expected_ssl_version_max = SSL_PROTOCOL_VERSION_TLS1_2;
26888
26889 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl1);
26890 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
26891
26892 std::unique_ptr<HttpNetworkSession> session = CreateSession(&session_deps_);
26893
26894 TestCompletionCallback callback1;
26895 auto trans1 =
26896 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
26897 int rv = trans1->Start(&request1, callback1.callback(), NetLogWithSource());
26898 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
26899
26900 // Wait for the first transaction to connect and start reading data.
26901 data1.RunUntilPaused();
26902
26903 // Change network config.
26904 ssl_context_config.version_max = SSL_PROTOCOL_VERSION_TLS1_2;
26905 ssl_config_service_raw->UpdateSSLConfigAndNotify(ssl_context_config);
26906
26907 // Resume the first transaction reads.
26908 data1.Resume();
26909 EXPECT_THAT(callback1.GetResult(rv), IsOk());
26910 std::string response_data1;
26911 EXPECT_THAT(ReadTransaction(trans1.get(), &response_data1), IsOk());
26912 EXPECT_EQ("1", response_data1);
26913 trans1.reset();
26914
26915 // Start 2nd transaction. Since the config was changed, it should use a new
26916 // socket.
26917 TestCompletionCallback callback2;
26918 auto trans2 =
26919 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
26920 rv = trans2->Start(&request2, callback2.callback(), NetLogWithSource());
26921 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
26922
26923 EXPECT_THAT(callback2.GetResult(rv), IsOk());
26924 std::string response_data2;
26925 EXPECT_THAT(ReadTransaction(trans2.get(), &response_data2), IsOk());
26926 EXPECT_EQ("2", response_data2);
26927 trans2.reset();
26928 }
26929
TEST_P(HttpNetworkTransactionTest,SSLConfigChangedPendingConnect)26930 TEST_P(HttpNetworkTransactionTest, SSLConfigChangedPendingConnect) {
26931 SSLContextConfig ssl_context_config;
26932 ssl_context_config.version_max = SSL_PROTOCOL_VERSION_TLS1_3;
26933 auto ssl_config_service =
26934 std::make_unique<TestSSLConfigService>(ssl_context_config);
26935 TestSSLConfigService* ssl_config_service_raw = ssl_config_service.get();
26936
26937 session_deps_.ssl_config_service = std::move(ssl_config_service);
26938
26939 HttpRequestInfo request;
26940 request.method = "GET";
26941 request.url = GURL("https://foo.test/1");
26942 request.traffic_annotation =
26943 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
26944
26945 const MockWrite kWrites1[] = {
26946 MockWrite("GET /1 HTTP/1.1\r\n"
26947 "Host: foo.test\r\n"
26948 "Connection: keep-alive\r\n\r\n"),
26949 };
26950 const MockRead kReads1[] = {
26951 MockRead("HTTP/1.1 200 OK\r\n"
26952 "Connection: keep-alive\r\n"
26953 "Content-Length: 1\r\n\r\n"
26954 "1"),
26955 };
26956
26957 StaticSocketDataProvider data1(kReads1, kWrites1);
26958 session_deps_.socket_factory->AddSocketDataProvider(&data1);
26959 session_deps_.socket_factory->AddSocketDataProvider(&data1);
26960
26961 // Even though the transaction was created before the change, the connection
26962 // shouldn't happen until after the SSLConfig change, so expect that the
26963 // socket will be created with the new SSLConfig.
26964 SSLSocketDataProvider ssl_data(ASYNC, OK);
26965 ssl_data.expected_ssl_version_max = SSL_PROTOCOL_VERSION_TLS1_2;
26966 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data);
26967
26968 std::unique_ptr<HttpNetworkSession> session = CreateSession(&session_deps_);
26969
26970 TestCompletionCallback callback;
26971 auto trans =
26972 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
26973 int rv = trans->Start(&request, callback.callback(), NetLogWithSource());
26974 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
26975
26976 ssl_context_config.version_max = SSL_PROTOCOL_VERSION_TLS1_2;
26977 ssl_config_service_raw->UpdateSSLConfigAndNotify(ssl_context_config);
26978
26979 EXPECT_THAT(callback.GetResult(rv), IsOk());
26980 std::string response_data;
26981 EXPECT_THAT(ReadTransaction(trans.get(), &response_data), IsOk());
26982 EXPECT_EQ("1", response_data);
26983 trans.reset();
26984 }
26985
26986 // Test that HttpNetworkTransaction correctly handles existing sockets when the
26987 // server requests a client certificate post-handshake (via a TLS
26988 // renegotiation). This is a regression test for https://crbug.com/829184.
TEST_P(HttpNetworkTransactionTest,PostHandshakeClientCertWithSockets)26989 TEST_P(HttpNetworkTransactionTest, PostHandshakeClientCertWithSockets) {
26990 const MutableNetworkTrafficAnnotationTag kTrafficAnnotation(
26991 TRAFFIC_ANNOTATION_FOR_TESTS);
26992
26993 auto cert_request_info = base::MakeRefCounted<SSLCertRequestInfo>();
26994 cert_request_info->host_and_port = HostPortPair("foo.test", 443);
26995
26996 std::unique_ptr<FakeClientCertIdentity> identity =
26997 FakeClientCertIdentity::CreateFromCertAndKeyFiles(
26998 GetTestCertsDirectory(), "client_1.pem", "client_1.pk8");
26999 ASSERT_TRUE(identity);
27000
27001 // This test will make several requests so that, when the client certificate
27002 // request comes in, we have a socket in use, an idle socket, and a socket for
27003 // an unrelated host.
27004 //
27005 // First, two long-lived requests which do not complete until after the client
27006 // certificate request. This arranges for sockets to be in use during the
27007 // request. They should not be interrupted.
27008 HttpRequestInfo request_long_lived;
27009 request_long_lived.method = "GET";
27010 request_long_lived.url = GURL("https://foo.test/long-lived");
27011 request_long_lived.traffic_annotation = kTrafficAnnotation;
27012
27013 HttpRequestInfo request_long_lived_bar;
27014 request_long_lived_bar.method = "GET";
27015 request_long_lived_bar.url = GURL("https://bar.test/long-lived");
27016 request_long_lived_bar.traffic_annotation = kTrafficAnnotation;
27017
27018 // Next, make a request that needs client certificates.
27019 HttpRequestInfo request_auth;
27020 request_auth.method = "GET";
27021 request_auth.url = GURL("https://foo.test/auth");
27022 request_auth.traffic_annotation = kTrafficAnnotation;
27023
27024 // Before responding to the challenge, make a request to an unauthenticated
27025 // endpoint. This will result in an idle socket when the client certificate
27026 // challenge is resolved.
27027 HttpRequestInfo request_unauth;
27028 request_unauth.method = "GET";
27029 request_unauth.url = GURL("https://foo.test/unauth");
27030 request_unauth.traffic_annotation = kTrafficAnnotation;
27031
27032 // After all the preceding requests complete, end with two additional requests
27033 // to ensure pre-authentication foo.test sockets are not used and bar.test
27034 // sockets are unaffected.
27035 HttpRequestInfo request_post_auth;
27036 request_post_auth.method = "GET";
27037 request_post_auth.url = GURL("https://foo.test/post-auth");
27038 request_post_auth.traffic_annotation = kTrafficAnnotation;
27039
27040 HttpRequestInfo request_post_auth_bar;
27041 request_post_auth_bar.method = "GET";
27042 request_post_auth_bar.url = GURL("https://bar.test/post-auth");
27043 request_post_auth_bar.traffic_annotation = kTrafficAnnotation;
27044
27045 // The sockets for /long-lived and /unauth complete their request but are
27046 // not allocated for /post-auth or /retry because SSL state has since changed.
27047 const MockWrite kLongLivedWrites[] = {
27048 MockWrite(ASYNC, 0,
27049 "GET /long-lived HTTP/1.1\r\n"
27050 "Host: foo.test\r\n"
27051 "Connection: keep-alive\r\n\r\n"),
27052 };
27053 const MockRead kLongLivedReads[] = {
27054 // Pause so /long-lived completes after the client presents client
27055 // certificates.
27056 MockRead(ASYNC, ERR_IO_PENDING, 1),
27057 MockRead(ASYNC, 2,
27058 "HTTP/1.1 200 OK\r\n"
27059 "Connection: keep-alive\r\n"
27060 "Content-Length: 10\r\n\r\n"
27061 "long-lived"),
27062 };
27063 SequencedSocketData data_long_lived(kLongLivedReads, kLongLivedWrites);
27064 SSLSocketDataProvider ssl_long_lived(ASYNC, OK);
27065 session_deps_.socket_factory->AddSocketDataProvider(&data_long_lived);
27066 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_long_lived);
27067
27068 // Requests for bar.test should be unaffected by foo.test and get allocated
27069 // a single socket.
27070 const MockWrite kBarWrites[] = {
27071 MockWrite(ASYNC, 0,
27072 "GET /long-lived HTTP/1.1\r\n"
27073 "Host: bar.test\r\n"
27074 "Connection: keep-alive\r\n\r\n"),
27075 MockWrite(ASYNC, 3,
27076 "GET /post-auth HTTP/1.1\r\n"
27077 "Host: bar.test\r\n"
27078 "Connection: keep-alive\r\n\r\n"),
27079 };
27080 const MockRead kBarReads[] = {
27081 // Pause on /long-lived so it completes after foo.test's authentication.
27082 MockRead(ASYNC, ERR_IO_PENDING, 1),
27083 MockRead(ASYNC, 2,
27084 "HTTP/1.1 200 OK\r\n"
27085 "Connection: keep-alive\r\n"
27086 "Content-Length: 10\r\n\r\n"
27087 "long-lived"),
27088 MockRead(ASYNC, 4,
27089 "HTTP/1.1 200 OK\r\n"
27090 "Connection: keep-alive\r\n"
27091 "Content-Length: 9\r\n\r\n"
27092 "post-auth"),
27093 };
27094 SequencedSocketData data_bar(kBarReads, kBarWrites);
27095 SSLSocketDataProvider ssl_bar(ASYNC, OK);
27096 session_deps_.socket_factory->AddSocketDataProvider(&data_bar);
27097 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_bar);
27098
27099 // Requesting /auth results in a post-handshake client certificate challenge.
27100 const MockWrite kAuthWrites[] = {
27101 MockWrite(ASYNC, 0,
27102 "GET /auth HTTP/1.1\r\n"
27103 "Host: foo.test\r\n"
27104 "Connection: keep-alive\r\n\r\n"),
27105 };
27106 const MockRead kAuthReads[] = {
27107 MockRead(ASYNC, ERR_SSL_CLIENT_AUTH_CERT_NEEDED, 1),
27108 };
27109 SequencedSocketData data_auth(kAuthReads, kAuthWrites);
27110 SSLSocketDataProvider ssl_auth(ASYNC, OK);
27111 ssl_auth.cert_request_info = cert_request_info;
27112 session_deps_.socket_factory->AddSocketDataProvider(&data_auth);
27113 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_auth);
27114
27115 // Requesting /unauth completes.
27116 const MockWrite kUnauthWrites[] = {
27117 MockWrite(ASYNC, 0,
27118 "GET /unauth HTTP/1.1\r\n"
27119 "Host: foo.test\r\n"
27120 "Connection: keep-alive\r\n\r\n"),
27121 };
27122 const MockRead kUnauthReads[] = {
27123 MockRead(ASYNC, 1,
27124 "HTTP/1.1 200 OK\r\n"
27125 "Connection: keep-alive\r\n"
27126 "Content-Length: 6\r\n\r\n"
27127 "unauth"),
27128 };
27129 SequencedSocketData data_unauth(kUnauthReads, kUnauthWrites);
27130 SSLSocketDataProvider ssl_unauth(ASYNC, OK);
27131 session_deps_.socket_factory->AddSocketDataProvider(&data_unauth);
27132 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_unauth);
27133
27134 // When the client certificate is selected, /auth is retried on a new
27135 // connection. In particular, it should not be retried on |data_unauth|,
27136 // which would not honor the new client certificate configuration.
27137 const MockWrite kRetryWrites[] = {
27138 MockWrite(ASYNC, 0,
27139 "GET /auth HTTP/1.1\r\n"
27140 "Host: foo.test\r\n"
27141 "Connection: keep-alive\r\n\r\n"),
27142 };
27143 const MockRead kRetryReads[] = {
27144 MockRead(ASYNC, 1,
27145 "HTTP/1.1 200 OK\r\n"
27146 // Close the connection so we test that /post-auth is not
27147 // allocated to |data_unauth| or |data_long_lived|.
27148 "Connection: close\r\n"
27149 "Content-Length: 4\r\n\r\n"
27150 "auth"),
27151 };
27152 SequencedSocketData data_retry(kRetryReads, kRetryWrites);
27153 SSLSocketDataProvider ssl_retry(ASYNC, OK);
27154 ssl_retry.expected_send_client_cert = true;
27155 ssl_retry.expected_client_cert = identity->certificate();
27156 session_deps_.socket_factory->AddSocketDataProvider(&data_retry);
27157 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_retry);
27158
27159 // /post-auth gets its own socket.
27160 const MockWrite kPostAuthWrites[] = {
27161 MockWrite(ASYNC, 0,
27162 "GET /post-auth HTTP/1.1\r\n"
27163 "Host: foo.test\r\n"
27164 "Connection: keep-alive\r\n\r\n"),
27165 };
27166 const MockRead kPostAuthReads[] = {
27167 MockRead(ASYNC, 1,
27168 "HTTP/1.1 200 OK\r\n"
27169 "Connection: keep-alive\r\n"
27170 "Content-Length: 9\r\n\r\n"
27171 "post-auth"),
27172 };
27173 SequencedSocketData data_post_auth(kPostAuthReads, kPostAuthWrites);
27174 SSLSocketDataProvider ssl_post_auth(ASYNC, OK);
27175 ssl_post_auth.expected_send_client_cert = true;
27176 ssl_post_auth.expected_client_cert = identity->certificate();
27177 session_deps_.socket_factory->AddSocketDataProvider(&data_post_auth);
27178 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_post_auth);
27179
27180 std::unique_ptr<HttpNetworkSession> session = CreateSession(&session_deps_);
27181
27182 // Start the two long-lived requests.
27183 TestCompletionCallback callback_long_lived;
27184 auto trans_long_lived =
27185 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
27186 int rv = trans_long_lived->Start(
27187 &request_long_lived, callback_long_lived.callback(), NetLogWithSource());
27188 ASSERT_THAT(rv, IsError(ERR_IO_PENDING));
27189 data_long_lived.RunUntilPaused();
27190
27191 TestCompletionCallback callback_long_lived_bar;
27192 auto trans_long_lived_bar =
27193 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
27194 rv = trans_long_lived_bar->Start(&request_long_lived_bar,
27195 callback_long_lived_bar.callback(),
27196 NetLogWithSource());
27197 ASSERT_THAT(rv, IsError(ERR_IO_PENDING));
27198 data_bar.RunUntilPaused();
27199
27200 // Request /auth. This gives a client certificate challenge.
27201 TestCompletionCallback callback_auth;
27202 auto trans_auth =
27203 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
27204 rv = trans_auth->Start(&request_auth, callback_auth.callback(),
27205 NetLogWithSource());
27206 EXPECT_THAT(callback_auth.GetResult(rv),
27207 IsError(ERR_SSL_CLIENT_AUTH_CERT_NEEDED));
27208
27209 // Make an unauthenticated request. This completes.
27210 TestCompletionCallback callback_unauth;
27211 auto trans_unauth =
27212 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
27213 rv = trans_unauth->Start(&request_unauth, callback_unauth.callback(),
27214 NetLogWithSource());
27215 EXPECT_THAT(callback_unauth.GetResult(rv), IsOk());
27216 std::string response_unauth;
27217 EXPECT_THAT(ReadTransaction(trans_unauth.get(), &response_unauth), IsOk());
27218 EXPECT_EQ("unauth", response_unauth);
27219 trans_unauth.reset();
27220
27221 // Complete the authenticated request.
27222 rv = trans_auth->RestartWithCertificate(identity->certificate(),
27223 identity->ssl_private_key(),
27224 callback_auth.callback());
27225 EXPECT_THAT(callback_auth.GetResult(rv), IsOk());
27226 std::string response_auth;
27227 EXPECT_THAT(ReadTransaction(trans_auth.get(), &response_auth), IsOk());
27228 EXPECT_EQ("auth", response_auth);
27229 trans_auth.reset();
27230
27231 // Complete the long-lived requests.
27232 data_long_lived.Resume();
27233 EXPECT_THAT(callback_long_lived.GetResult(ERR_IO_PENDING), IsOk());
27234 std::string response_long_lived;
27235 EXPECT_THAT(ReadTransaction(trans_long_lived.get(), &response_long_lived),
27236 IsOk());
27237 EXPECT_EQ("long-lived", response_long_lived);
27238 trans_long_lived.reset();
27239
27240 data_bar.Resume();
27241 EXPECT_THAT(callback_long_lived_bar.GetResult(ERR_IO_PENDING), IsOk());
27242 std::string response_long_lived_bar;
27243 EXPECT_THAT(
27244 ReadTransaction(trans_long_lived_bar.get(), &response_long_lived_bar),
27245 IsOk());
27246 EXPECT_EQ("long-lived", response_long_lived_bar);
27247 trans_long_lived_bar.reset();
27248
27249 // Run the post-authentication requests.
27250 TestCompletionCallback callback_post_auth;
27251 auto trans_post_auth =
27252 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
27253 rv = trans_post_auth->Start(&request_post_auth, callback_post_auth.callback(),
27254 NetLogWithSource());
27255 EXPECT_THAT(callback_post_auth.GetResult(rv), IsOk());
27256 std::string response_post_auth;
27257 EXPECT_THAT(ReadTransaction(trans_post_auth.get(), &response_post_auth),
27258 IsOk());
27259 EXPECT_EQ("post-auth", response_post_auth);
27260 trans_post_auth.reset();
27261
27262 TestCompletionCallback callback_post_auth_bar;
27263 auto trans_post_auth_bar =
27264 std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
27265 rv = trans_post_auth_bar->Start(&request_post_auth_bar,
27266 callback_post_auth_bar.callback(),
27267 NetLogWithSource());
27268 EXPECT_THAT(callback_post_auth_bar.GetResult(rv), IsOk());
27269 std::string response_post_auth_bar;
27270 EXPECT_THAT(
27271 ReadTransaction(trans_post_auth_bar.get(), &response_post_auth_bar),
27272 IsOk());
27273 EXPECT_EQ("post-auth", response_post_auth_bar);
27274 trans_post_auth_bar.reset();
27275 }
27276
TEST_P(HttpNetworkTransactionTest,RequestWithDnsAliases)27277 TEST_P(HttpNetworkTransactionTest, RequestWithDnsAliases) {
27278 // Create a request.
27279 HttpRequestInfo request;
27280 request.method = "GET";
27281 request.url = GURL("http://www.example.org/");
27282 request.traffic_annotation =
27283 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
27284
27285 // Add a rule with DNS aliases to the host resolver.
27286 std::vector<std::string> aliases({"alias1", "alias2", "www.example.org"});
27287 session_deps_.host_resolver->rules()->AddIPLiteralRuleWithDnsAliases(
27288 "www.example.org", "127.0.0.1", std::move(aliases));
27289
27290 // Create a HttpNetworkSession.
27291 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
27292
27293 // Create a transaction.
27294 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
27295
27296 // Prepare the expected data to be written and read. The client should send
27297 // the request below.
27298 MockWrite data_writes[] = {
27299 MockWrite("GET / HTTP/1.1\r\n"
27300 "Host: www.example.org\r\n"
27301 "Connection: keep-alive\r\n\r\n"),
27302 };
27303
27304 // The server should respond with the following.
27305 MockRead data_reads[] = {
27306 MockRead("HTTP/1.0 200 OK\r\n"),
27307 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
27308 MockRead("Content-Length: 100\r\n\r\n"),
27309 MockRead(SYNCHRONOUS, OK),
27310 };
27311
27312 StaticSocketDataProvider data(data_reads, data_writes);
27313 session_deps_.socket_factory->AddSocketDataProvider(&data);
27314 TestCompletionCallback callback;
27315
27316 // Start the transaction.
27317 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
27318 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
27319
27320 // Wait for completion.
27321 rv = callback.WaitForResult();
27322 EXPECT_THAT(rv, IsOk());
27323
27324 // Get the response info.
27325 const HttpResponseInfo* response = trans.GetResponseInfo();
27326
27327 // Verify that the alias list was stored in the response info as expected.
27328 ASSERT_TRUE(response);
27329 EXPECT_THAT(response->dns_aliases,
27330 testing::ElementsAre("alias1", "alias2", "www.example.org"));
27331 }
27332
TEST_P(HttpNetworkTransactionTest,RequestWithNoAdditionalDnsAliases)27333 TEST_P(HttpNetworkTransactionTest, RequestWithNoAdditionalDnsAliases) {
27334 // Create a request.
27335 HttpRequestInfo request;
27336 request.method = "GET";
27337 request.url = GURL("http://www.example.org/");
27338 request.traffic_annotation =
27339 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
27340
27341 // Add a rule without DNS aliases to the host resolver.
27342 session_deps_.host_resolver->rules()->AddRule("www.example.org", "127.0.0.1");
27343
27344 // Create a HttpNetworkSession.
27345 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
27346
27347 // Create a transaction.
27348 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
27349
27350 // Prepare the expected data to be written and read. The client should send
27351 // the request below.
27352 MockWrite data_writes[] = {
27353 MockWrite("GET / HTTP/1.1\r\n"
27354 "Host: www.example.org\r\n"
27355 "Connection: keep-alive\r\n\r\n"),
27356 };
27357
27358 // The server should respond with the following.
27359 MockRead data_reads[] = {
27360 MockRead("HTTP/1.0 200 OK\r\n"),
27361 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
27362 MockRead("Content-Length: 100\r\n\r\n"),
27363 MockRead(SYNCHRONOUS, OK),
27364 };
27365
27366 StaticSocketDataProvider data(data_reads, data_writes);
27367 session_deps_.socket_factory->AddSocketDataProvider(&data);
27368 TestCompletionCallback callback;
27369
27370 // Start the transaction.
27371 int rv = trans.Start(&request, callback.callback(), NetLogWithSource());
27372 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
27373
27374 // Wait for completion.
27375 rv = callback.WaitForResult();
27376 EXPECT_THAT(rv, IsOk());
27377
27378 // Get the response info.
27379 const HttpResponseInfo* response = trans.GetResponseInfo();
27380
27381 // Verify that the alias list was stored in the response info as expected.
27382 ASSERT_TRUE(response);
27383 EXPECT_THAT(response->dns_aliases, testing::ElementsAre("www.example.org"));
27384 }
27385
27386 // Test behavior of SetProxyInfoInResponse with a direct connection.
TEST_P(HttpNetworkTransactionTest,SetProxyInfoInResponse_Direct)27387 TEST_P(HttpNetworkTransactionTest, SetProxyInfoInResponse_Direct) {
27388 ProxyInfo proxy_info;
27389 proxy_info.UseDirect();
27390 HttpResponseInfo response_info;
27391 HttpNetworkTransaction::SetProxyInfoInResponse(proxy_info, &response_info);
27392 EXPECT_EQ(response_info.was_fetched_via_proxy, false);
27393 EXPECT_EQ(response_info.proxy_chain.is_for_ip_protection(), false);
27394 EXPECT_EQ(response_info.proxy_chain, ProxyChain::Direct());
27395 }
27396
27397 // Test behavior of SetProxyInfoInResponse with a proxied connection.
TEST_P(HttpNetworkTransactionTest,SetProxyInfoInResponse_Proxied)27398 TEST_P(HttpNetworkTransactionTest, SetProxyInfoInResponse_Proxied) {
27399 ProxyInfo proxy_info;
27400 ProxyChain proxy_chain =
27401 ProxyChain::FromSchemeHostAndPort(ProxyServer::SCHEME_HTTPS, "prx", 443);
27402 proxy_info.UseProxyChain(proxy_chain);
27403 HttpResponseInfo response_info;
27404 HttpNetworkTransaction::SetProxyInfoInResponse(proxy_info, &response_info);
27405 EXPECT_EQ(response_info.was_fetched_via_proxy, true);
27406 EXPECT_EQ(response_info.proxy_chain.is_for_ip_protection(), false);
27407 EXPECT_EQ(response_info.proxy_chain, proxy_chain);
27408 }
27409
27410 // Test behavior of SetProxyInfoInResponse with an empty ProxyInfo.
TEST_P(HttpNetworkTransactionTest,SetProxyInfoInResponse_Empty)27411 TEST_P(HttpNetworkTransactionTest, SetProxyInfoInResponse_Empty) {
27412 ProxyInfo empty_proxy_info;
27413 HttpResponseInfo response_info;
27414 HttpNetworkTransaction::SetProxyInfoInResponse(empty_proxy_info,
27415 &response_info);
27416 EXPECT_EQ(response_info.was_fetched_via_proxy, true);
27417 EXPECT_EQ(response_info.proxy_chain.is_for_ip_protection(), false);
27418 EXPECT_FALSE(response_info.proxy_chain.IsValid());
27419 }
27420
27421 // Test behavior of SetProxyInfoInResponse with a proxied connection for IP
27422 // protection.
TEST_P(HttpNetworkTransactionTest,SetProxyInfoInResponse_IpProtection)27423 TEST_P(HttpNetworkTransactionTest, SetProxyInfoInResponse_IpProtection) {
27424 ProxyInfo proxy_info;
27425 ProxyChain ip_protection_proxy_chain =
27426 ProxyChain::ForIpProtection({ProxyServer::FromSchemeHostAndPort(
27427 ProxyServer::SCHEME_HTTPS, "prx", 443)});
27428 proxy_info.UseProxyChain(ip_protection_proxy_chain);
27429 HttpResponseInfo response_info;
27430 HttpNetworkTransaction::SetProxyInfoInResponse(proxy_info, &response_info);
27431 EXPECT_EQ(response_info.was_fetched_via_proxy, true);
27432 EXPECT_EQ(response_info.proxy_chain.is_for_ip_protection(), true);
27433 EXPECT_EQ(response_info.proxy_chain, ip_protection_proxy_chain);
27434 }
27435
27436 class IpProtectionProxyDelegate : public TestProxyDelegate {
27437 public:
IpProtectionProxyDelegate()27438 IpProtectionProxyDelegate() {
27439 set_extra_header_name(net::HttpRequestHeaders::kAuthorization);
27440 }
27441
27442 // ProxyDelegate implementation:
OnResolveProxy(const GURL & url,const NetworkAnonymizationKey & network_anonymization_key,const std::string & method,const ProxyRetryInfoMap & proxy_retry_info,ProxyInfo * result)27443 void OnResolveProxy(const GURL& url,
27444 const NetworkAnonymizationKey& network_anonymization_key,
27445 const std::string& method,
27446 const ProxyRetryInfoMap& proxy_retry_info,
27447 ProxyInfo* result) override {
27448 ProxyList proxy_list;
27449 proxy_list.AddProxyChain(proxy_chain());
27450
27451 // For IP Protection we always want to fallback to direct, so emulate the
27452 // behavior of NetworkServiceProxyDelegate where a direct chain will always
27453 // be added as the last ProxyList entry.
27454 if (!proxy_chain().is_direct()) {
27455 proxy_list.AddProxyChain(ProxyChain::Direct());
27456 }
27457
27458 result->UseProxyList(proxy_list);
27459 }
27460
GetAuthorizationHeaderValue(const ProxyServer & proxy_server)27461 static std::string GetAuthorizationHeaderValue(
27462 const ProxyServer& proxy_server) {
27463 return GetExtraHeaderValue(proxy_server);
27464 }
27465 };
27466
27467 // Test that for requests sent through an IP Protection proxy, the
27468 // 'IP-Protection' header is sent as expected when the feature is enabled.
TEST_P(HttpNetworkTransactionTest,HttpsNestedProxyIpProtectionRequestHeaderAddedWhenEnabled)27469 TEST_P(HttpNetworkTransactionTest,
27470 HttpsNestedProxyIpProtectionRequestHeaderAddedWhenEnabled) {
27471 base::test::ScopedFeatureList scoped_feature_list;
27472 scoped_feature_list.InitAndEnableFeatureWithParameters(
27473 net::features::kEnableIpProtectionProxy,
27474 {{net::features::kIpPrivacyAddHeaderToProxiedRequests.name, "true"}});
27475
27476 HttpRequestInfo request;
27477 request.method = "GET";
27478 request.url = GURL("https://www.example.org/");
27479 request.traffic_annotation =
27480 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
27481
27482 const ProxyServer kProxyServer1{ProxyServer::SCHEME_HTTPS,
27483 HostPortPair("proxy1.test", 70)};
27484 const ProxyServer kProxyServer2{ProxyServer::SCHEME_HTTPS,
27485 HostPortPair("proxy2.test", 71)};
27486 ProxyChain kNestedProxyChain =
27487 ProxyChain::ForIpProtection({kProxyServer1, kProxyServer2});
27488
27489 session_deps_.proxy_resolution_service =
27490 ConfiguredProxyResolutionService::CreateFixedForTest(
27491 "https://not-used:70", TRAFFIC_ANNOTATION_FOR_TESTS);
27492 session_deps_.proxy_delegate = std::make_unique<IpProtectionProxyDelegate>();
27493 auto* proxy_delegate = static_cast<IpProtectionProxyDelegate*>(
27494 session_deps_.proxy_delegate.get());
27495 proxy_delegate->set_proxy_chain(kNestedProxyChain);
27496 session_deps_.proxy_resolution_service->SetProxyDelegate(proxy_delegate);
27497 session_deps_.net_log = NetLog::Get();
27498 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
27499
27500 const std::string kProxyServer1AuthHeaderValue =
27501 IpProtectionProxyDelegate::GetAuthorizationHeaderValue(kProxyServer1);
27502 const std::string kProxyServer2AuthHeaderValue =
27503 IpProtectionProxyDelegate::GetAuthorizationHeaderValue(kProxyServer2);
27504
27505 const std::string kProxyServer2Connect = base::StringPrintf(
27506 "CONNECT proxy2.test:71 HTTP/1.1\r\n"
27507 "Host: proxy2.test:71\r\n"
27508 "Proxy-Connection: keep-alive\r\n"
27509 "Authorization: %s\r\n\r\n",
27510 kProxyServer1AuthHeaderValue.c_str());
27511 const std::string kEndpointConnect = base::StringPrintf(
27512 "CONNECT www.example.org:443 HTTP/1.1\r\n"
27513 "Host: www.example.org:443\r\n"
27514 "Proxy-Connection: keep-alive\r\n"
27515 "Authorization: %s\r\n\r\n",
27516 kProxyServer2AuthHeaderValue.c_str());
27517
27518 MockWrite data_writes[] = {
27519 MockWrite(kProxyServer2Connect.c_str()),
27520 MockWrite(kEndpointConnect.c_str()),
27521 MockWrite("GET / HTTP/1.1\r\n"
27522 "Host: www.example.org\r\n"
27523 "Connection: keep-alive\r\n"
27524 "IP-Protection: 1\r\n\r\n"),
27525 };
27526
27527 MockRead data_reads[] = {
27528 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
27529 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
27530 MockRead("HTTP/1.1 200\r\n\r\n"),
27531 MockRead(SYNCHRONOUS, OK),
27532 };
27533
27534 StaticSocketDataProvider data(data_reads, data_writes);
27535 session_deps_.socket_factory->AddSocketDataProvider(&data);
27536
27537 SSLSocketDataProvider ssl(ASYNC, OK);
27538 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
27539
27540 SSLSocketDataProvider ssl2(ASYNC, OK);
27541 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
27542
27543 SSLSocketDataProvider ssl3(ASYNC, OK);
27544 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
27545
27546 TestCompletionCallback callback;
27547
27548 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
27549
27550 int rv = trans.Start(&request, callback.callback(),
27551 NetLogWithSource::Make(NetLogSourceType::NONE));
27552 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
27553
27554 rv = callback.WaitForResult();
27555 EXPECT_THAT(rv, IsOk());
27556
27557 const HttpResponseInfo* response = trans.GetResponseInfo();
27558 ASSERT_TRUE(response);
27559 ASSERT_TRUE(response->headers);
27560 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
27561 }
27562
27563 // Test that for direct requests that are marked as being for IP Protection, the
27564 // 'IP-Protection' header is not sent even when the feature is enabled. This
27565 // test should be removed once `kIpPrivacyDirectOnly` is.
TEST_P(HttpNetworkTransactionTest,HttpsNestedProxyIpProtectionRequestHeaderNotAddedForIpProtectionDirect)27566 TEST_P(HttpNetworkTransactionTest,
27567 HttpsNestedProxyIpProtectionRequestHeaderNotAddedForIpProtectionDirect) {
27568 base::test::ScopedFeatureList scoped_feature_list;
27569 scoped_feature_list.InitAndEnableFeatureWithParameters(
27570 net::features::kEnableIpProtectionProxy,
27571 {{net::features::kIpPrivacyAddHeaderToProxiedRequests.name, "true"},
27572 {net::features::kIpPrivacyDirectOnly.name, "true"}});
27573
27574 HttpRequestInfo request;
27575 request.method = "GET";
27576 request.url = GURL("https://www.example.org/");
27577 request.traffic_annotation =
27578 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
27579
27580 auto kIpProtectionDirectChain =
27581 ProxyChain::ForIpProtection(std::vector<ProxyServer>());
27582
27583 session_deps_.proxy_resolution_service =
27584 ConfiguredProxyResolutionService::CreateFixedForTest(
27585 "https://not-used:70", TRAFFIC_ANNOTATION_FOR_TESTS);
27586 session_deps_.proxy_delegate = std::make_unique<IpProtectionProxyDelegate>();
27587 auto* proxy_delegate = static_cast<IpProtectionProxyDelegate*>(
27588 session_deps_.proxy_delegate.get());
27589 proxy_delegate->set_proxy_chain(kIpProtectionDirectChain);
27590 session_deps_.proxy_resolution_service->SetProxyDelegate(proxy_delegate);
27591 session_deps_.net_log = NetLog::Get();
27592 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
27593
27594 MockWrite data_writes[] = {
27595 MockWrite("GET / HTTP/1.1\r\n"
27596 "Host: www.example.org\r\n"
27597 "Connection: keep-alive\r\n\r\n"),
27598 };
27599
27600 MockRead data_reads[] = {
27601 MockRead("HTTP/1.1 200\r\n\r\n"),
27602 MockRead(SYNCHRONOUS, OK),
27603 };
27604
27605 StaticSocketDataProvider data(data_reads, data_writes);
27606 session_deps_.socket_factory->AddSocketDataProvider(&data);
27607
27608 SSLSocketDataProvider ssl(ASYNC, OK);
27609 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
27610
27611 TestCompletionCallback callback;
27612
27613 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
27614
27615 int rv = trans.Start(&request, callback.callback(),
27616 NetLogWithSource::Make(NetLogSourceType::NONE));
27617 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
27618
27619 rv = callback.WaitForResult();
27620 EXPECT_THAT(rv, IsOk());
27621
27622 const HttpResponseInfo* response = trans.GetResponseInfo();
27623 ASSERT_TRUE(response);
27624 ASSERT_TRUE(response->headers);
27625 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
27626 }
27627
27628 // Test that for requests sent through an IP Protection proxy, the
27629 // 'IP-Protection' header is not sent if the feature is disabled.
TEST_P(HttpNetworkTransactionTest,HttpsNestedProxyIpProtectionRequestHeaderNotAddedIfFeatureDisabled)27630 TEST_P(HttpNetworkTransactionTest,
27631 HttpsNestedProxyIpProtectionRequestHeaderNotAddedIfFeatureDisabled) {
27632 base::test::ScopedFeatureList scoped_feature_list;
27633 scoped_feature_list.InitAndEnableFeatureWithParameters(
27634 net::features::kEnableIpProtectionProxy,
27635 {{net::features::kIpPrivacyAddHeaderToProxiedRequests.name, "false"}});
27636
27637 HttpRequestInfo request;
27638 request.method = "GET";
27639 request.url = GURL("https://www.example.org/");
27640 request.traffic_annotation =
27641 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
27642
27643 const ProxyServer kProxyServer1{ProxyServer::SCHEME_HTTPS,
27644 HostPortPair("proxy1.test", 70)};
27645 const ProxyServer kProxyServer2{ProxyServer::SCHEME_HTTPS,
27646 HostPortPair("proxy2.test", 71)};
27647 ProxyChain kNestedProxyChain =
27648 ProxyChain::ForIpProtection({kProxyServer1, kProxyServer2});
27649
27650 session_deps_.proxy_resolution_service =
27651 ConfiguredProxyResolutionService::CreateFixedForTest(
27652 "https://not-used:70", TRAFFIC_ANNOTATION_FOR_TESTS);
27653 session_deps_.proxy_delegate = std::make_unique<IpProtectionProxyDelegate>();
27654 auto* proxy_delegate = static_cast<IpProtectionProxyDelegate*>(
27655 session_deps_.proxy_delegate.get());
27656 proxy_delegate->set_proxy_chain(kNestedProxyChain);
27657 session_deps_.proxy_resolution_service->SetProxyDelegate(proxy_delegate);
27658 session_deps_.net_log = NetLog::Get();
27659 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
27660
27661 const std::string kProxyServer1AuthHeaderValue =
27662 IpProtectionProxyDelegate::GetAuthorizationHeaderValue(kProxyServer1);
27663 const std::string kProxyServer2AuthHeaderValue =
27664 IpProtectionProxyDelegate::GetAuthorizationHeaderValue(kProxyServer2);
27665
27666 const std::string kProxyServer2Connect = base::StringPrintf(
27667 "CONNECT proxy2.test:71 HTTP/1.1\r\n"
27668 "Host: proxy2.test:71\r\n"
27669 "Proxy-Connection: keep-alive\r\n"
27670 "Authorization: %s\r\n\r\n",
27671 kProxyServer1AuthHeaderValue.c_str());
27672 const std::string kEndpointConnect = base::StringPrintf(
27673 "CONNECT www.example.org:443 HTTP/1.1\r\n"
27674 "Host: www.example.org:443\r\n"
27675 "Proxy-Connection: keep-alive\r\n"
27676 "Authorization: %s\r\n\r\n",
27677 kProxyServer2AuthHeaderValue.c_str());
27678
27679 MockWrite data_writes[] = {
27680 MockWrite(kProxyServer2Connect.c_str()),
27681 MockWrite(kEndpointConnect.c_str()),
27682 MockWrite("GET / HTTP/1.1\r\n"
27683 "Host: www.example.org\r\n"
27684 "Connection: keep-alive\r\n\r\n"),
27685 };
27686
27687 MockRead data_reads[] = {
27688 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
27689 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
27690 MockRead("HTTP/1.1 200\r\n\r\n"),
27691 MockRead(SYNCHRONOUS, OK),
27692 };
27693
27694 StaticSocketDataProvider data(data_reads, data_writes);
27695 session_deps_.socket_factory->AddSocketDataProvider(&data);
27696
27697 SSLSocketDataProvider ssl(ASYNC, OK);
27698 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
27699
27700 SSLSocketDataProvider ssl2(ASYNC, OK);
27701 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
27702
27703 SSLSocketDataProvider ssl3(ASYNC, OK);
27704 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
27705
27706 TestCompletionCallback callback;
27707
27708 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
27709
27710 int rv = trans.Start(&request, callback.callback(),
27711 NetLogWithSource::Make(NetLogSourceType::NONE));
27712 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
27713
27714 rv = callback.WaitForResult();
27715 EXPECT_THAT(rv, IsOk());
27716
27717 const HttpResponseInfo* response = trans.GetResponseInfo();
27718 ASSERT_TRUE(response);
27719 ASSERT_TRUE(response->headers);
27720 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
27721 }
27722
27723 // Test that for a request that fails to be sent through an IP Protection proxy,
27724 // after we fallback to direct the 'IP-Protection' header is not added to the
27725 // request headers.
TEST_P(HttpNetworkTransactionTest,HttpsNestedProxyIpProtectionRequestHeaderNotAddedAfterFallback)27726 TEST_P(HttpNetworkTransactionTest,
27727 HttpsNestedProxyIpProtectionRequestHeaderNotAddedAfterFallback) {
27728 base::test::ScopedFeatureList scoped_feature_list;
27729 scoped_feature_list.InitAndEnableFeatureWithParameters(
27730 net::features::kEnableIpProtectionProxy,
27731 {{net::features::kIpPrivacyAddHeaderToProxiedRequests.name, "true"}});
27732 HttpRequestInfo request;
27733 request.method = "GET";
27734 request.url = GURL("https://www.example.org/");
27735 request.traffic_annotation =
27736 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
27737
27738 const ProxyServer kProxyServer1{ProxyServer::SCHEME_HTTPS,
27739 HostPortPair("proxy1.test", 70)};
27740 const ProxyServer kProxyServer2{ProxyServer::SCHEME_HTTPS,
27741 HostPortPair("proxy2.test", 71)};
27742 ProxyChain kNestedProxyChain =
27743 ProxyChain::ForIpProtection({kProxyServer1, kProxyServer2});
27744
27745 session_deps_.proxy_resolution_service =
27746 ConfiguredProxyResolutionService::CreateFixedForTest(
27747 "https://not-used:70", TRAFFIC_ANNOTATION_FOR_TESTS);
27748 session_deps_.proxy_delegate = std::make_unique<IpProtectionProxyDelegate>();
27749 auto* proxy_delegate = static_cast<IpProtectionProxyDelegate*>(
27750 session_deps_.proxy_delegate.get());
27751 proxy_delegate->set_proxy_chain(kNestedProxyChain);
27752 session_deps_.proxy_resolution_service->SetProxyDelegate(proxy_delegate);
27753 session_deps_.net_log = NetLog::Get();
27754 std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_));
27755
27756 const std::string kProxyServer1AuthHeaderValue =
27757 IpProtectionProxyDelegate::GetAuthorizationHeaderValue(kProxyServer1);
27758
27759 const std::string kProxyServer2Connect = base::StringPrintf(
27760 "CONNECT proxy2.test:71 HTTP/1.1\r\n"
27761 "Host: proxy2.test:71\r\n"
27762 "Proxy-Connection: keep-alive\r\n"
27763 "Authorization: %s\r\n\r\n",
27764 kProxyServer1AuthHeaderValue.c_str());
27765
27766 MockWrite data_writes1[] = {
27767 MockWrite(kProxyServer2Connect.c_str()),
27768 };
27769
27770 MockRead data_reads1[] = {
27771 MockRead("HTTP/1.1 401 Not Authorized\r\n\r\n"),
27772 MockRead(SYNCHRONOUS, OK),
27773 };
27774
27775 StaticSocketDataProvider data1(data_reads1, data_writes1);
27776 session_deps_.socket_factory->AddSocketDataProvider(&data1);
27777
27778 SSLSocketDataProvider ssl1(ASYNC, OK);
27779 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl1);
27780
27781 // The proxy delegate should implement falling back to direct after an error,
27782 // and we don't expect any proxying or an IP Protection request header on the
27783 // GET.
27784 MockWrite data_writes2[] = {
27785 MockWrite("GET / HTTP/1.1\r\n"
27786 "Host: www.example.org\r\n"
27787 "Connection: keep-alive\r\n\r\n"),
27788 };
27789
27790 MockRead data_reads2[] = {
27791 MockRead("HTTP/1.1 200\r\n\r\n"),
27792 MockRead(SYNCHRONOUS, OK),
27793 };
27794
27795 StaticSocketDataProvider data2(data_reads2, data_writes2);
27796 session_deps_.socket_factory->AddSocketDataProvider(&data2);
27797
27798 SSLSocketDataProvider ssl2(ASYNC, OK);
27799 session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
27800
27801 TestCompletionCallback callback;
27802
27803 HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get());
27804
27805 int rv = trans.Start(&request, callback.callback(),
27806 NetLogWithSource::Make(NetLogSourceType::NONE));
27807 EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
27808
27809 rv = callback.WaitForResult();
27810 EXPECT_THAT(rv, IsOk());
27811
27812 const HttpResponseInfo* response = trans.GetResponseInfo();
27813 ASSERT_TRUE(response);
27814 ASSERT_TRUE(response->headers);
27815 EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine());
27816 }
27817
27818 } // namespace net
27819