blob: 5d7bf6ee394c68fa3ca5bb5d578c32ac49cd8c69 [file] [log] [blame]
ricea433bdab2015-01-26 07:25:371// Copyright 2014 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5// End-to-end tests for WebSocket.
6//
7// A python server is (re)started for each test, which is moderately
8// inefficient. However, it makes these tests a good fit for scenarios which
9// require special server configurations.
10
tfarina8a2c66c22015-10-13 19:14:4911#include <stdint.h>
ryansturm4bab06832016-03-03 23:41:0712
danakj9c5cab52016-04-16 00:54:3313#include <memory>
ricea433bdab2015-01-26 07:25:3714#include <string>
Adam Rice5b4a3d82018-08-02 15:28:4315#include <utility>
ricea433bdab2015-01-26 07:25:3716
17#include "base/bind.h"
ricea433bdab2015-01-26 07:25:3718#include "base/callback.h"
danakjdb9ae7942020-11-11 16:01:3519#include "base/callback_helpers.h"
Eric Orthcd71ede2021-09-14 18:18:5020#include "base/files/file_path.h"
skyostil4891b25b2015-06-11 11:43:4521#include "base/location.h"
danakj9c5cab52016-04-16 00:54:3322#include "base/memory/ptr_util.h"
Keishi Hattori0e45c022021-11-27 09:25:5223#include "base/memory/raw_ptr.h"
Bence Béky65623972018-03-05 15:31:5624#include "base/memory/scoped_refptr.h"
ricea433bdab2015-01-26 07:25:3725#include "base/run_loop.h"
Adam Rice5b4a3d82018-08-02 15:28:4326#include "base/strings/strcat.h"
Eric Orthcd71ede2021-09-14 18:18:5027#include "base/strings/string_number_conversions.h"
Adam Ricecb76ac62015-02-20 05:33:2528#include "base/strings/string_piece.h"
Adam Rice5b4a3d82018-08-02 15:28:4329#include "base/strings/stringprintf.h"
Patrick Monette643cdf62021-10-15 19:13:4230#include "base/task/single_thread_task_runner.h"
Eric Orthcd71ede2021-09-14 18:18:5031#include "base/test/scoped_feature_list.h"
gabf767595f2016-05-11 18:50:3532#include "base/threading/thread_task_runner_handle.h"
Sergey Ulanova337dcd2017-09-08 20:53:1433#include "build/build_config.h"
ricea433bdab2015-01-26 07:25:3734#include "net/base/auth.h"
Eric Orthcd71ede2021-09-14 18:18:5035#include "net/base/features.h"
Adam Rice5b4a3d82018-08-02 15:28:4336#include "net/base/host_port_pair.h"
Tsuyoshi Horo01faed62019-02-20 22:11:3737#include "net/base/ip_endpoint.h"
Matt Menke29a538d2020-04-29 16:12:1738#include "net/base/isolation_info.h"
Chris Thompsone3c3a3b02020-12-17 23:20:4039#include "net/base/net_errors.h"
ryansturm7de050c2016-02-23 00:10:2140#include "net/base/proxy_delegate.h"
Adam Rice5b4a3d82018-08-02 15:28:4341#include "net/base/url_util.h"
Chris Thompsone3c3a3b02020-12-17 23:20:4042#include "net/cert/ct_policy_status.h"
Eric Orthcd71ede2021-09-14 18:18:5043#include "net/dns/mock_host_resolver.h"
Yutaka Hirano2f65eec2018-05-23 01:58:2244#include "net/http/http_request_headers.h"
Matt Menkece5d765372021-08-17 18:24:1245#include "net/http/transport_security_state.h"
Adam Rice5b4a3d82018-08-02 15:28:4346#include "net/log/net_log.h"
Nicolas Arciniegad2013f92020-02-07 23:00:5647#include "net/proxy_resolution/configured_proxy_resolution_service.h"
Adam Rice5b4a3d82018-08-02 15:28:4348#include "net/proxy_resolution/proxy_config.h"
49#include "net/proxy_resolution/proxy_config_service.h"
50#include "net/proxy_resolution/proxy_config_service_fixed.h"
51#include "net/proxy_resolution/proxy_config_with_annotation.h"
52#include "net/proxy_resolution/proxy_info.h"
tommycli59a63432015-11-06 00:10:5553#include "net/test/embedded_test_server/embedded_test_server.h"
Adam Rice5b4a3d82018-08-02 15:28:4354#include "net/test/embedded_test_server/http_request.h"
55#include "net/test/embedded_test_server/http_response.h"
ricea433bdab2015-01-26 07:25:3756#include "net/test/spawned_test_server/spawned_test_server.h"
rsleevia69c79a2016-06-22 03:28:4357#include "net/test/test_data_directory.h"
Gabriel Charettec7108742019-08-23 03:31:4058#include "net/test/test_with_task_environment.h"
rhalavati9ebaba7e2017-04-27 06:16:2959#include "net/traffic_annotation/network_traffic_annotation_test_helper.h"
Adam Rice5b4a3d82018-08-02 15:28:4360#include "net/url_request/url_request.h"
61#include "net/url_request/url_request_context.h"
ricea433bdab2015-01-26 07:25:3762#include "net/url_request/url_request_test_util.h"
ricea433bdab2015-01-26 07:25:3763#include "net/websockets/websocket_channel.h"
64#include "net/websockets/websocket_event_interface.h"
ricea433bdab2015-01-26 07:25:3765#include "testing/gtest/include/gtest/gtest.h"
Adam Rice5b4a3d82018-08-02 15:28:4366#include "url/gurl.h"
mkwst4997ce82015-07-25 12:00:0567#include "url/origin.h"
Eric Orthbe86fee2021-10-28 22:31:1168#include "url/url_constants.h"
ricea433bdab2015-01-26 07:25:3769
70namespace net {
71
yhirano4a593832016-10-24 18:58:2272class URLRequest;
73
ricea433bdab2015-01-26 07:25:3774namespace {
75
Adam Rice5b4a3d82018-08-02 15:28:4376using test_server::BasicHttpResponse;
77using test_server::HttpRequest;
78using test_server::HttpResponse;
79
ricea433bdab2015-01-26 07:25:3780static const char kEchoServer[] = "echo-with-no-extension";
81
David Benjamin51eeec92021-09-21 03:56:3682// Simplify changing URL schemes.
83GURL ReplaceUrlScheme(const GURL& in_url, const base::StringPiece& scheme) {
84 GURL::Replacements replacements;
85 replacements.SetSchemeStr(scheme);
86 return in_url.ReplaceComponents(replacements);
87}
88
ricea433bdab2015-01-26 07:25:3789// An implementation of WebSocketEventInterface that waits for and records the
90// results of the connect.
91class ConnectTestingEventInterface : public WebSocketEventInterface {
92 public:
93 ConnectTestingEventInterface();
94
Peter Boström407869b2021-10-07 04:42:4895 ConnectTestingEventInterface(const ConnectTestingEventInterface&) = delete;
96 ConnectTestingEventInterface& operator=(const ConnectTestingEventInterface&) =
97 delete;
98
ricea433bdab2015-01-26 07:25:3799 void WaitForResponse();
100
101 bool failed() const { return failed_; }
102
Eric Orthcd71ede2021-09-14 18:18:50103 const std::unique_ptr<WebSocketHandshakeResponseInfo>& response() const {
104 return response_;
105 }
106
ricea433bdab2015-01-26 07:25:37107 // Only set if the handshake failed, otherwise empty.
108 std::string failure_message() const;
109
110 std::string selected_subprotocol() const;
111
112 std::string extensions() const;
113
114 // Implementation of WebSocketEventInterface.
yhirano4a593832016-10-24 18:58:22115 void OnCreateURLRequest(URLRequest* request) override {}
116
Yoichi Osato1ead61a2020-01-06 04:52:57117 void OnAddChannelResponse(
118 std::unique_ptr<WebSocketHandshakeResponseInfo> response,
119 const std::string& selected_subprotocol,
Adam Rice250bb012020-05-26 15:56:10120 const std::string& extensions) override;
ricea433bdab2015-01-26 07:25:37121
Yutaka Hirano4165de92018-04-10 11:46:49122 void OnDataFrame(bool fin,
123 WebSocketMessageType type,
Yutaka Hirano76aacb202019-09-05 16:36:56124 base::span<const char> payload) override;
ricea433bdab2015-01-26 07:25:37125
Yoichi Osatofcaa2a22019-08-28 08:22:36126 bool HasPendingDataFrames() override { return false; }
127
Adam Riced0095702020-05-26 06:18:25128 void OnSendDataFrameDone() override;
ricea433bdab2015-01-26 07:25:37129
Yutaka Hirano4165de92018-04-10 11:46:49130 void OnClosingHandshake() override;
ricea433bdab2015-01-26 07:25:37131
Yutaka Hirano4165de92018-04-10 11:46:49132 void OnDropChannel(bool was_clean,
133 uint16_t code,
134 const std::string& reason) override;
ricea433bdab2015-01-26 07:25:37135
Adam Langleya48b636a2020-11-12 23:42:52136 void OnFailChannel(const std::string& message,
137 int net_error,
Anton Bikineev068d2912021-05-15 20:43:52138 absl::optional<int> response_code) override;
ricea433bdab2015-01-26 07:25:37139
Yutaka Hirano4165de92018-04-10 11:46:49140 void OnStartOpeningHandshake(
danakj9c5cab52016-04-16 00:54:33141 std::unique_ptr<WebSocketHandshakeRequestInfo> request) override;
ricea433bdab2015-01-26 07:25:37142
Yutaka Hirano4165de92018-04-10 11:46:49143 void OnSSLCertificateError(
danakj9c5cab52016-04-16 00:54:33144 std::unique_ptr<SSLErrorCallbacks> ssl_error_callbacks,
ricea433bdab2015-01-26 07:25:37145 const GURL& url,
Emily Starkd9df3d32019-04-29 17:54:57146 int net_error,
ricea433bdab2015-01-26 07:25:37147 const SSLInfo& ssl_info,
148 bool fatal) override;
149
Emily Starkf2c9bbd2019-04-09 17:08:58150 int OnAuthRequired(const AuthChallengeInfo& auth_info,
Yutaka Hirano70fa25912018-06-06 05:26:54151 scoped_refptr<HttpResponseHeaders> response_headers,
Tsuyoshi Horo01faed62019-02-20 22:11:37152 const IPEndPoint& remote_endpoint,
Yutaka Hirano70fa25912018-06-06 05:26:54153 base::OnceCallback<void(const AuthCredentials*)> callback,
Anton Bikineev068d2912021-05-15 20:43:52154 absl::optional<AuthCredentials>* credentials) override;
Yutaka Hirano70fa25912018-06-06 05:26:54155
ricea433bdab2015-01-26 07:25:37156 private:
157 void QuitNestedEventLoop();
158
159 // failed_ is true if the handshake failed (ie. OnFailChannel was called).
160 bool failed_;
Eric Orthcd71ede2021-09-14 18:18:50161 std::unique_ptr<WebSocketHandshakeResponseInfo> response_;
ricea433bdab2015-01-26 07:25:37162 std::string selected_subprotocol_;
163 std::string extensions_;
164 std::string failure_message_;
165 base::RunLoop run_loop_;
ricea433bdab2015-01-26 07:25:37166};
167
tyoshinoc06da562015-03-06 06:02:42168ConnectTestingEventInterface::ConnectTestingEventInterface() : failed_(false) {
ricea433bdab2015-01-26 07:25:37169}
170
171void ConnectTestingEventInterface::WaitForResponse() {
172 run_loop_.Run();
173}
174
175std::string ConnectTestingEventInterface::failure_message() const {
176 return failure_message_;
177}
178
179std::string ConnectTestingEventInterface::selected_subprotocol() const {
180 return selected_subprotocol_;
181}
182
183std::string ConnectTestingEventInterface::extensions() const {
184 return extensions_;
185}
186
Yutaka Hirano4165de92018-04-10 11:46:49187void ConnectTestingEventInterface::OnAddChannelResponse(
Yoichi Osato1ead61a2020-01-06 04:52:57188 std::unique_ptr<WebSocketHandshakeResponseInfo> response,
ricea433bdab2015-01-26 07:25:37189 const std::string& selected_subprotocol,
Adam Rice250bb012020-05-26 15:56:10190 const std::string& extensions) {
Eric Orthcd71ede2021-09-14 18:18:50191 response_ = std::move(response);
ricea433bdab2015-01-26 07:25:37192 selected_subprotocol_ = selected_subprotocol;
193 extensions_ = extensions;
194 QuitNestedEventLoop();
ricea433bdab2015-01-26 07:25:37195}
196
Yutaka Hirano4165de92018-04-10 11:46:49197void ConnectTestingEventInterface::OnDataFrame(bool fin,
198 WebSocketMessageType type,
Yutaka Hirano76aacb202019-09-05 16:36:56199 base::span<const char> payload) {
200}
ricea433bdab2015-01-26 07:25:37201
Adam Riced0095702020-05-26 06:18:25202void ConnectTestingEventInterface::OnSendDataFrameDone() {}
ricea433bdab2015-01-26 07:25:37203
Yutaka Hirano4165de92018-04-10 11:46:49204void ConnectTestingEventInterface::OnClosingHandshake() {}
ricea433bdab2015-01-26 07:25:37205
Yutaka Hirano4165de92018-04-10 11:46:49206void ConnectTestingEventInterface::OnDropChannel(bool was_clean,
207 uint16_t code,
208 const std::string& reason) {}
ricea433bdab2015-01-26 07:25:37209
Adam Langleya48b636a2020-11-12 23:42:52210void ConnectTestingEventInterface::OnFailChannel(
211 const std::string& message,
212 int net_error,
Anton Bikineev068d2912021-05-15 20:43:52213 absl::optional<int> response_code) {
ricea433bdab2015-01-26 07:25:37214 failed_ = true;
215 failure_message_ = message;
216 QuitNestedEventLoop();
ricea433bdab2015-01-26 07:25:37217}
218
Yutaka Hirano4165de92018-04-10 11:46:49219void ConnectTestingEventInterface::OnStartOpeningHandshake(
220 std::unique_ptr<WebSocketHandshakeRequestInfo> request) {}
ricea433bdab2015-01-26 07:25:37221
Yutaka Hirano4165de92018-04-10 11:46:49222void ConnectTestingEventInterface::OnSSLCertificateError(
danakj9c5cab52016-04-16 00:54:33223 std::unique_ptr<SSLErrorCallbacks> ssl_error_callbacks,
ricea433bdab2015-01-26 07:25:37224 const GURL& url,
Emily Starkd9df3d32019-04-29 17:54:57225 int net_error,
ricea433bdab2015-01-26 07:25:37226 const SSLInfo& ssl_info,
227 bool fatal) {
skyostil4891b25b2015-06-11 11:43:45228 base::ThreadTaskRunnerHandle::Get()->PostTask(
kylecharf4fe5172019-02-15 18:53:49229 FROM_HERE, base::BindOnce(&SSLErrorCallbacks::CancelSSLRequest,
230 base::Owned(ssl_error_callbacks.release()),
231 ERR_SSL_PROTOCOL_ERROR, &ssl_info));
ricea433bdab2015-01-26 07:25:37232}
233
Yutaka Hirano70fa25912018-06-06 05:26:54234int ConnectTestingEventInterface::OnAuthRequired(
Emily Starkf2c9bbd2019-04-09 17:08:58235 const AuthChallengeInfo& auth_info,
Yutaka Hirano70fa25912018-06-06 05:26:54236 scoped_refptr<HttpResponseHeaders> response_headers,
Tsuyoshi Horo01faed62019-02-20 22:11:37237 const IPEndPoint& remote_endpoint,
Yutaka Hirano70fa25912018-06-06 05:26:54238 base::OnceCallback<void(const AuthCredentials*)> callback,
Anton Bikineev068d2912021-05-15 20:43:52239 absl::optional<AuthCredentials>* credentials) {
240 *credentials = absl::nullopt;
Yutaka Hirano70fa25912018-06-06 05:26:54241 return OK;
242}
243
ricea433bdab2015-01-26 07:25:37244void ConnectTestingEventInterface::QuitNestedEventLoop() {
245 run_loop_.Quit();
246}
247
248// A subclass of TestNetworkDelegate that additionally implements the
249// OnResolveProxy callback and records the information passed to it.
ryansturm7de050c2016-02-23 00:10:21250class TestProxyDelegateWithProxyInfo : public ProxyDelegate {
ricea433bdab2015-01-26 07:25:37251 public:
Chris Watkins28c2fdd2017-11-30 06:06:52252 TestProxyDelegateWithProxyInfo() = default;
ricea433bdab2015-01-26 07:25:37253
Peter Boström407869b2021-10-07 04:42:48254 TestProxyDelegateWithProxyInfo(const TestProxyDelegateWithProxyInfo&) =
255 delete;
256 TestProxyDelegateWithProxyInfo& operator=(
257 const TestProxyDelegateWithProxyInfo&) = delete;
258
ricea433bdab2015-01-26 07:25:37259 struct ResolvedProxyInfo {
260 GURL url;
261 ProxyInfo proxy_info;
262 };
263
264 const ResolvedProxyInfo& resolved_proxy_info() const {
265 return resolved_proxy_info_;
266 }
267
268 protected:
269 void OnResolveProxy(const GURL& url,
ryansturm4bab06832016-03-03 23:41:07270 const std::string& method,
Reilly Grantb414ace72017-11-14 23:03:22271 const ProxyRetryInfoMap& proxy_retry_info,
ricea433bdab2015-01-26 07:25:37272 ProxyInfo* result) override {
273 resolved_proxy_info_.url = url;
274 resolved_proxy_info_.proxy_info = *result;
275 }
276
ryansturm7de050c2016-02-23 00:10:21277 void OnFallback(const ProxyServer& bad_proxy, int net_error) override {}
ryansturm7de050c2016-02-23 00:10:21278
Robert Ogden78d4f9eb2020-03-17 20:56:38279 void OnBeforeTunnelRequest(const ProxyServer& proxy_server,
280 HttpRequestHeaders* extra_headers) override {}
Wojciech Dzierżanowski1f823562019-01-18 11:26:00281
Robert Ogden78d4f9eb2020-03-17 20:56:38282 Error OnTunnelHeadersReceived(
Wojciech Dzierżanowski1f823562019-01-18 11:26:00283 const ProxyServer& proxy_server,
284 const HttpResponseHeaders& response_headers) override {
285 return OK;
286 }
287
ricea433bdab2015-01-26 07:25:37288 private:
289 ResolvedProxyInfo resolved_proxy_info_;
ricea433bdab2015-01-26 07:25:37290};
291
Gabriel Charette694c3c332019-08-19 14:53:05292class WebSocketEndToEndTest : public TestWithTaskEnvironment {
ricea433bdab2015-01-26 07:25:37293 protected:
294 WebSocketEndToEndTest()
Adam Ricecb76ac62015-02-20 05:33:25295 : event_interface_(),
Bence Béky65623972018-03-05 15:31:56296 proxy_delegate_(std::make_unique<TestProxyDelegateWithProxyInfo>()),
ricea433bdab2015-01-26 07:25:37297 context_(true),
Adam Ricecb76ac62015-02-20 05:33:25298 channel_(),
ricea433bdab2015-01-26 07:25:37299 initialised_context_(false) {}
300
301 // Initialise the URLRequestContext. Normally done automatically by
302 // ConnectAndWait(). This method is for the use of tests that need the
303 // URLRequestContext initialised before calling ConnectAndWait().
304 void InitialiseContext() {
ricea433bdab2015-01-26 07:25:37305 context_.Init();
Eric Roman3d8546a2018-09-10 17:00:52306 context_.proxy_resolution_service()->SetProxyDelegate(
307 proxy_delegate_.get());
ricea433bdab2015-01-26 07:25:37308 initialised_context_ = true;
309 }
310
311 // Send the connect request to |socket_url| and wait for a response. Returns
312 // true if the handshake succeeded.
313 bool ConnectAndWait(const GURL& socket_url) {
314 if (!initialised_context_) {
315 InitialiseContext();
316 }
Daniel Cheng88186bd52017-10-20 08:14:46317 url::Origin origin = url::Origin::Create(GURL("http://localhost"));
Maks Orlovich8be0e252019-12-09 18:35:49318 net::SiteForCookies site_for_cookies =
319 net::SiteForCookies::FromOrigin(origin);
shivanigithub4e78015f592020-10-21 13:26:23320 IsolationInfo isolation_info =
321 IsolationInfo::Create(IsolationInfo::RequestType::kOther, origin,
322 origin, SiteForCookies::FromOrigin(origin));
Adam Rice5b4a3d82018-08-02 15:28:43323 event_interface_ = new ConnectTestingEventInterface();
Bence Béky65623972018-03-05 15:31:56324 channel_ = std::make_unique<WebSocketChannel>(
Keishi Hattori0e45c022021-11-27 09:25:52325 base::WrapUnique(event_interface_.get()), &context_);
Adam Langleyacbad242020-08-18 15:14:52326 channel_->SendAddChannelRequest(
327 GURL(socket_url), sub_protocols_, origin, site_for_cookies,
328 isolation_info, HttpRequestHeaders(), TRAFFIC_ANNOTATION_FOR_TESTS);
ricea433bdab2015-01-26 07:25:37329 event_interface_->WaitForResponse();
330 return !event_interface_->failed();
331 }
332
Keishi Hattori0e45c022021-11-27 09:25:52333 raw_ptr<ConnectTestingEventInterface> event_interface_; // owned by channel_
danakj9c5cab52016-04-16 00:54:33334 std::unique_ptr<TestProxyDelegateWithProxyInfo> proxy_delegate_;
ricea433bdab2015-01-26 07:25:37335 TestURLRequestContext context_;
danakj9c5cab52016-04-16 00:54:33336 std::unique_ptr<WebSocketChannel> channel_;
ricea5acb1faf72015-03-16 15:34:00337 std::vector<std::string> sub_protocols_;
ricea433bdab2015-01-26 07:25:37338 bool initialised_context_;
339};
340
ricea433bdab2015-01-26 07:25:37341// Basic test of connectivity. If this test fails, nothing else can be expected
342// to work.
Sergey Ulanov4c786d32017-09-08 22:53:25343TEST_F(WebSocketEndToEndTest, BasicSmokeTest) {
ricea433bdab2015-01-26 07:25:37344 SpawnedTestServer ws_server(SpawnedTestServer::TYPE_WS,
ricea433bdab2015-01-26 07:25:37345 GetWebSocketTestDataDirectory());
346 ASSERT_TRUE(ws_server.Start());
347 EXPECT_TRUE(ConnectAndWait(ws_server.GetURL(kEchoServer)));
348}
349
350// Test for issue crbug.com/433695 "Unencrypted WebSocket connection via
351// authenticated proxy times out"
352// TODO(ricea): Enable this when the issue is fixed.
353TEST_F(WebSocketEndToEndTest, DISABLED_HttpsProxyUnauthedFails) {
354 SpawnedTestServer proxy_server(SpawnedTestServer::TYPE_BASIC_AUTH_PROXY,
ricea433bdab2015-01-26 07:25:37355 base::FilePath());
356 SpawnedTestServer ws_server(SpawnedTestServer::TYPE_WS,
ricea433bdab2015-01-26 07:25:37357 GetWebSocketTestDataDirectory());
358 ASSERT_TRUE(proxy_server.StartInBackground());
359 ASSERT_TRUE(ws_server.StartInBackground());
360 ASSERT_TRUE(proxy_server.BlockUntilStarted());
361 ASSERT_TRUE(ws_server.BlockUntilStarted());
362 std::string proxy_config =
363 "https=" + proxy_server.host_port_pair().ToString();
Nicolas Arciniega8ec5bfa2020-03-20 05:07:26364 std::unique_ptr<ProxyResolutionService> proxy_resolution_service(
Nicolas Arciniegad2013f92020-02-07 23:00:56365 ConfiguredProxyResolutionService::CreateFixed(
366 proxy_config, TRAFFIC_ANNOTATION_FOR_TESTS));
Lily Houghton8c2f97d2018-01-22 05:06:59367 ASSERT_TRUE(proxy_resolution_service);
368 context_.set_proxy_resolution_service(proxy_resolution_service.get());
ricea433bdab2015-01-26 07:25:37369 EXPECT_FALSE(ConnectAndWait(ws_server.GetURL(kEchoServer)));
370 EXPECT_EQ("Proxy authentication failed", event_interface_->failure_message());
371}
372
Sergey Ulanov4c786d32017-09-08 22:53:25373// These test are not compatible with RemoteTestServer because RemoteTestServer
374// doesn't support TYPE_BASIC_AUTH_PROXY.
375// TODO(ricea): Make these tests work. See crbug.com/441711.
Xiaohan Wang2a6845b2022-01-08 04:40:57376#if BUILDFLAG(IS_ANDROID) || BUILDFLAG(IS_FUCHSIA)
Sergey Ulanov4c786d32017-09-08 22:53:25377#define MAYBE_HttpsWssProxyUnauthedFails DISABLED_HttpsWssProxyUnauthedFails
378#define MAYBE_HttpsProxyUsed DISABLED_HttpsProxyUsed
379#else
380#define MAYBE_HttpsWssProxyUnauthedFails HttpsWssProxyUnauthedFails
381#define MAYBE_HttpsProxyUsed HttpsProxyUsed
382#endif
383
384TEST_F(WebSocketEndToEndTest, MAYBE_HttpsWssProxyUnauthedFails) {
ricea433bdab2015-01-26 07:25:37385 SpawnedTestServer proxy_server(SpawnedTestServer::TYPE_BASIC_AUTH_PROXY,
ricea433bdab2015-01-26 07:25:37386 base::FilePath());
387 SpawnedTestServer wss_server(SpawnedTestServer::TYPE_WSS,
ricea433bdab2015-01-26 07:25:37388 GetWebSocketTestDataDirectory());
389 ASSERT_TRUE(proxy_server.StartInBackground());
390 ASSERT_TRUE(wss_server.StartInBackground());
391 ASSERT_TRUE(proxy_server.BlockUntilStarted());
392 ASSERT_TRUE(wss_server.BlockUntilStarted());
Eric Romanda790f92018-11-07 19:17:15393 ProxyConfig proxy_config;
394 proxy_config.proxy_rules().ParseFromString(
395 "https=" + proxy_server.host_port_pair().ToString());
396 // TODO(https://crbug.com/901896): Don't rely on proxying localhost.
397 proxy_config.proxy_rules().bypass_rules.AddRulesToSubtractImplicit();
398
Nicolas Arciniega8ec5bfa2020-03-20 05:07:26399 std::unique_ptr<ProxyResolutionService> proxy_resolution_service(
Nicolas Arciniegad2013f92020-02-07 23:00:56400 ConfiguredProxyResolutionService::CreateFixed(ProxyConfigWithAnnotation(
Eric Romanda790f92018-11-07 19:17:15401 proxy_config, TRAFFIC_ANNOTATION_FOR_TESTS)));
Lily Houghton8c2f97d2018-01-22 05:06:59402 ASSERT_TRUE(proxy_resolution_service);
403 context_.set_proxy_resolution_service(proxy_resolution_service.get());
ricea433bdab2015-01-26 07:25:37404 EXPECT_FALSE(ConnectAndWait(wss_server.GetURL(kEchoServer)));
405 EXPECT_EQ("Proxy authentication failed", event_interface_->failure_message());
406}
407
408// Regression test for crbug/426736 "WebSocket connections not using configured
409// system HTTPS Proxy".
Sergey Ulanov4c786d32017-09-08 22:53:25410TEST_F(WebSocketEndToEndTest, MAYBE_HttpsProxyUsed) {
Adam Rice5b4a3d82018-08-02 15:28:43411 SpawnedTestServer proxy_server(SpawnedTestServer::TYPE_PROXY,
ricea433bdab2015-01-26 07:25:37412 base::FilePath());
413 SpawnedTestServer ws_server(SpawnedTestServer::TYPE_WS,
ricea433bdab2015-01-26 07:25:37414 GetWebSocketTestDataDirectory());
415 ASSERT_TRUE(proxy_server.StartInBackground());
416 ASSERT_TRUE(ws_server.StartInBackground());
417 ASSERT_TRUE(proxy_server.BlockUntilStarted());
418 ASSERT_TRUE(ws_server.BlockUntilStarted());
Eric Romanda790f92018-11-07 19:17:15419 ProxyConfig proxy_config;
420 proxy_config.proxy_rules().ParseFromString(
421 "https=" + proxy_server.host_port_pair().ToString() + ";" +
422 "http=" + proxy_server.host_port_pair().ToString());
423 // TODO(https://crbug.com/901896): Don't rely on proxying localhost.
424 proxy_config.proxy_rules().bypass_rules.AddRulesToSubtractImplicit();
425
Nicolas Arciniega8ec5bfa2020-03-20 05:07:26426 std::unique_ptr<ProxyResolutionService> proxy_resolution_service(
Nicolas Arciniegad2013f92020-02-07 23:00:56427 ConfiguredProxyResolutionService::CreateFixed(ProxyConfigWithAnnotation(
Eric Romanda790f92018-11-07 19:17:15428 proxy_config, TRAFFIC_ANNOTATION_FOR_TESTS)));
Lily Houghton8c2f97d2018-01-22 05:06:59429 context_.set_proxy_resolution_service(proxy_resolution_service.get());
ricea433bdab2015-01-26 07:25:37430 InitialiseContext();
431
ricea433bdab2015-01-26 07:25:37432 GURL ws_url = ws_server.GetURL(kEchoServer);
433 EXPECT_TRUE(ConnectAndWait(ws_url));
ryansturm7de050c2016-02-23 00:10:21434 const TestProxyDelegateWithProxyInfo::ResolvedProxyInfo& info =
435 proxy_delegate_->resolved_proxy_info();
ricea433bdab2015-01-26 07:25:37436 EXPECT_EQ(ws_url, info.url);
437 EXPECT_TRUE(info.proxy_info.is_http());
438}
439
Adam Rice5b4a3d82018-08-02 15:28:43440std::unique_ptr<HttpResponse> ProxyPacHandler(const HttpRequest& request) {
441 GURL url = request.GetURL();
442 EXPECT_EQ(url.path_piece(), "/proxy.pac");
443 EXPECT_TRUE(url.has_query());
444 std::string proxy;
445 EXPECT_TRUE(GetValueForKeyInQuery(url, "proxy", &proxy));
446 auto response = std::make_unique<BasicHttpResponse>();
447 response->set_content_type("application/x-ns-proxy-autoconfig");
448 response->set_content(
449 base::StringPrintf("function FindProxyForURL(url, host) {\n"
450 " return 'PROXY %s';\n"
451 "}\n",
452 proxy.c_str()));
453 return response;
454}
455
456// This tests the proxy.pac resolver that is built into the system. This is not
457// the one that Chrome normally uses. Chrome's normal implementation is defined
458// as a mojo service. It is outside //net and we can't use it from here. This
459// tests the alternative implementations that are selected when the
460// --winhttp-proxy-resolver flag is provided to Chrome. These only exist on OS X
461// and Windows.
462// TODO(ricea): Remove this test if --winhttp-proxy-resolver flag is removed.
463// See crbug.com/644030.
464
Xiaohan Wang2a6845b2022-01-08 04:40:57465#if BUILDFLAG(IS_WIN) || BUILDFLAG(IS_APPLE)
Adam Rice5b4a3d82018-08-02 15:28:43466#define MAYBE_ProxyPacUsed ProxyPacUsed
467#else
468#define MAYBE_ProxyPacUsed DISABLED_ProxyPacUsed
469#endif
470
471TEST_F(WebSocketEndToEndTest, MAYBE_ProxyPacUsed) {
472 EmbeddedTestServer proxy_pac_server(net::EmbeddedTestServer::Type::TYPE_HTTP);
473 SpawnedTestServer proxy_server(SpawnedTestServer::TYPE_PROXY,
474 base::FilePath());
475 SpawnedTestServer ws_server(SpawnedTestServer::TYPE_WS,
476 GetWebSocketTestDataDirectory());
477 proxy_pac_server.RegisterRequestHandler(base::BindRepeating(ProxyPacHandler));
478 proxy_server.set_redirect_connect_to_localhost(true);
479
480 ASSERT_TRUE(proxy_pac_server.Start());
481 ASSERT_TRUE(proxy_server.StartInBackground());
482 ASSERT_TRUE(ws_server.StartInBackground());
483 ASSERT_TRUE(proxy_server.BlockUntilStarted());
484 ASSERT_TRUE(ws_server.BlockUntilStarted());
485
486 ProxyConfig proxy_config =
487 ProxyConfig::CreateFromCustomPacURL(proxy_pac_server.GetURL(base::StrCat(
488 {"/proxy.pac?proxy=", proxy_server.host_port_pair().ToString()})));
489 proxy_config.set_pac_mandatory(true);
490 auto proxy_config_service = std::make_unique<ProxyConfigServiceFixed>(
491 ProxyConfigWithAnnotation(proxy_config, TRAFFIC_ANNOTATION_FOR_TESTS));
Nicolas Arciniega8ec5bfa2020-03-20 05:07:26492 std::unique_ptr<ProxyResolutionService> proxy_resolution_service(
Nicolas Arciniegad2013f92020-02-07 23:00:56493 ConfiguredProxyResolutionService::CreateUsingSystemProxyResolver(
Eric Roman3be01ba2020-04-03 21:37:09494 std::move(proxy_config_service), NetLog::Get(),
495 /*quick_check_enabled=*/true));
Adam Rice5b4a3d82018-08-02 15:28:43496 ASSERT_EQ(ws_server.host_port_pair().host(), "127.0.0.1");
497 context_.set_proxy_resolution_service(proxy_resolution_service.get());
498 InitialiseContext();
499
Eric Romanda790f92018-11-07 19:17:15500 // Use a name other than localhost, since localhost implicitly bypasses the
501 // use of proxy.pac.
Adam Rice5b4a3d82018-08-02 15:28:43502 HostPortPair fake_ws_host_port_pair("stealth-localhost",
503 ws_server.host_port_pair().port());
504
505 GURL ws_url(base::StrCat(
506 {"ws://", fake_ws_host_port_pair.ToString(), "/", kEchoServer}));
507 EXPECT_TRUE(ConnectAndWait(ws_url));
508 const auto& info = proxy_delegate_->resolved_proxy_info();
509 EXPECT_EQ(ws_url, info.url);
510 EXPECT_TRUE(info.proxy_info.is_http());
511 EXPECT_EQ(info.proxy_info.ToPacString(),
512 base::StrCat({"PROXY ", proxy_server.host_port_pair().ToString()}));
513}
514
ricea23c3f942015-02-02 13:35:13515// This is a regression test for crbug.com/408061 Crash in
516// net::WebSocketBasicHandshakeStream::Upgrade.
Sergey Ulanov4c786d32017-09-08 22:53:25517TEST_F(WebSocketEndToEndTest, TruncatedResponse) {
ricea23c3f942015-02-02 13:35:13518 SpawnedTestServer ws_server(SpawnedTestServer::TYPE_WS,
ricea23c3f942015-02-02 13:35:13519 GetWebSocketTestDataDirectory());
520 ASSERT_TRUE(ws_server.Start());
521 InitialiseContext();
522
523 GURL ws_url = ws_server.GetURL("truncated-headers");
524 EXPECT_FALSE(ConnectAndWait(ws_url));
525}
526
David Benjamin51eeec92021-09-21 03:56:36527// Regression test for crbug.com/455215 "HSTS not applied to WebSocket"
528TEST_F(WebSocketEndToEndTest, HstsHttpsToWebSocket) {
529 EmbeddedTestServer https_server(net::EmbeddedTestServer::Type::TYPE_HTTPS);
530 https_server.SetSSLConfig(
531 net::EmbeddedTestServer::CERT_COMMON_NAME_IS_DOMAIN);
532 https_server.ServeFilesFromSourceDirectory("net/data/url_request_unittest");
533
534 SpawnedTestServer::SSLOptions ssl_options(
535 SpawnedTestServer::SSLOptions::CERT_COMMON_NAME_IS_DOMAIN);
536 SpawnedTestServer wss_server(SpawnedTestServer::TYPE_WSS, ssl_options,
537 GetWebSocketTestDataDirectory());
538
539 ASSERT_TRUE(https_server.Start());
540 ASSERT_TRUE(wss_server.Start());
541 InitialiseContext();
542 // Set HSTS via https:
543 TestDelegate delegate;
544 GURL https_page = https_server.GetURL("/hsts-headers.html");
545 std::unique_ptr<URLRequest> request(context_.CreateRequest(
546 https_page, DEFAULT_PRIORITY, &delegate, TRAFFIC_ANNOTATION_FOR_TESTS));
547 request->Start();
548 delegate.RunUntilComplete();
549 EXPECT_EQ(OK, delegate.request_status());
550
551 // Check HSTS with ws:
552 // Change the scheme from wss: to ws: to verify that it is switched back.
553 GURL ws_url = ReplaceUrlScheme(wss_server.GetURL(kEchoServer), "ws");
554 EXPECT_TRUE(ConnectAndWait(ws_url));
555}
556
557TEST_F(WebSocketEndToEndTest, HstsWebSocketToHttps) {
558 EmbeddedTestServer https_server(net::EmbeddedTestServer::Type::TYPE_HTTPS);
559 https_server.SetSSLConfig(
560 net::EmbeddedTestServer::CERT_COMMON_NAME_IS_DOMAIN);
561 https_server.ServeFilesFromSourceDirectory("net/data/url_request_unittest");
562
563 SpawnedTestServer::SSLOptions ssl_options(
564 SpawnedTestServer::SSLOptions::CERT_COMMON_NAME_IS_DOMAIN);
565 SpawnedTestServer wss_server(SpawnedTestServer::TYPE_WSS, ssl_options,
566 GetWebSocketTestDataDirectory());
567 ASSERT_TRUE(https_server.Start());
568 ASSERT_TRUE(wss_server.Start());
569 InitialiseContext();
570 // Set HSTS via wss:
571 GURL wss_url = wss_server.GetURL("set-hsts");
572 EXPECT_TRUE(ConnectAndWait(wss_url));
573
574 // Verify via http:
575 TestDelegate delegate;
576 GURL http_page =
577 ReplaceUrlScheme(https_server.GetURL("/simple.html"), "http");
578 std::unique_ptr<URLRequest> request(context_.CreateRequest(
579 http_page, DEFAULT_PRIORITY, &delegate, TRAFFIC_ANNOTATION_FOR_TESTS));
580 request->Start();
581 delegate.RunUntilComplete();
582 EXPECT_EQ(OK, delegate.request_status());
583 EXPECT_TRUE(request->url().SchemeIs("https"));
584}
585
586TEST_F(WebSocketEndToEndTest, HstsWebSocketToWebSocket) {
587 SpawnedTestServer::SSLOptions ssl_options(
588 SpawnedTestServer::SSLOptions::CERT_COMMON_NAME_IS_DOMAIN);
589 SpawnedTestServer wss_server(SpawnedTestServer::TYPE_WSS, ssl_options,
590 GetWebSocketTestDataDirectory());
591 ASSERT_TRUE(wss_server.Start());
592 InitialiseContext();
593 // Set HSTS via wss:
594 GURL wss_url = wss_server.GetURL("set-hsts");
595 EXPECT_TRUE(ConnectAndWait(wss_url));
596
597 // Verify via wss:
598 GURL ws_url = ReplaceUrlScheme(wss_server.GetURL(kEchoServer), "ws");
599 EXPECT_TRUE(ConnectAndWait(ws_url));
600}
601
ricea5acb1faf72015-03-16 15:34:00602// Regression test for crbug.com/180504 "WebSocket handshake fails when HTTP
603// headers have trailing LWS".
Sergey Ulanov4c786d32017-09-08 22:53:25604TEST_F(WebSocketEndToEndTest, TrailingWhitespace) {
ricea5acb1faf72015-03-16 15:34:00605 SpawnedTestServer ws_server(SpawnedTestServer::TYPE_WS,
ricea5acb1faf72015-03-16 15:34:00606 GetWebSocketTestDataDirectory());
607 ASSERT_TRUE(ws_server.Start());
608
609 GURL ws_url = ws_server.GetURL("trailing-whitespace");
610 sub_protocols_.push_back("sip");
611 EXPECT_TRUE(ConnectAndWait(ws_url));
612 EXPECT_EQ("sip", event_interface_->selected_subprotocol());
613}
614
riceae1d67672015-03-19 10:10:17615// This is a regression test for crbug.com/169448 "WebSockets should support
616// header continuations"
617// TODO(ricea): HTTP continuation headers have been deprecated by RFC7230. If
618// support for continuation headers is removed from Chrome, then this test will
619// break and should be removed.
Sergey Ulanov4c786d32017-09-08 22:53:25620TEST_F(WebSocketEndToEndTest, HeaderContinuations) {
riceae1d67672015-03-19 10:10:17621 SpawnedTestServer ws_server(SpawnedTestServer::TYPE_WS,
riceae1d67672015-03-19 10:10:17622 GetWebSocketTestDataDirectory());
623 ASSERT_TRUE(ws_server.Start());
624
625 GURL ws_url = ws_server.GetURL("header-continuation");
626
627 EXPECT_TRUE(ConnectAndWait(ws_url));
628 EXPECT_EQ("permessage-deflate; server_max_window_bits=10",
629 event_interface_->extensions());
630}
631
Eric Orthcd71ede2021-09-14 18:18:50632// Test that ws->wss scheme upgrade is supported on receiving a DNS HTTPS
633// record.
David Benjamin51eeec92021-09-21 03:56:36634TEST_F(WebSocketEndToEndTest, DnsSchemeUpgradeSupported) {
Eric Orthcd71ede2021-09-14 18:18:50635 base::test::ScopedFeatureList features;
636 features.InitAndEnableFeatureWithParameters(
637 features::kUseDnsHttpsSvcb, {{"UseDnsHttpsSvcbHttpUpgrade", "true"}});
638
639 SpawnedTestServer wss_server(SpawnedTestServer::TYPE_WSS,
640 SpawnedTestServer::SSLOptions(base::FilePath(
641 FILE_PATH_LITERAL("test_names.pem"))),
642 GetWebSocketTestDataDirectory());
643 ASSERT_TRUE(wss_server.Start());
644
645 GURL wss_url("wss://a.test:" +
646 base::NumberToString(wss_server.host_port_pair().port()) + "/" +
647 kEchoServer);
648 GURL::Replacements replacements;
649 replacements.SetSchemeStr(url::kWsScheme);
650 GURL ws_url = wss_url.ReplaceComponents(replacements);
651
Eric Orthbe86fee2021-10-28 22:31:11652 // Note that due to socket pool behavior, HostResolver will see the ws/wss
653 // requests as http/https.
Eric Orthcd71ede2021-09-14 18:18:50654 MockHostResolver host_resolver;
Eric Orthbe86fee2021-10-28 22:31:11655 MockHostResolverBase::RuleResolver::RuleKey unencrypted_resolve_key;
656 unencrypted_resolve_key.scheme = url::kHttpScheme;
657 host_resolver.rules()->AddRule(std::move(unencrypted_resolve_key),
658 ERR_DNS_NAME_HTTPS_ONLY);
659 MockHostResolverBase::RuleResolver::RuleKey encrypted_resolve_key;
660 encrypted_resolve_key.scheme = url::kHttpsScheme;
661 host_resolver.rules()->AddRule(std::move(encrypted_resolve_key), "127.0.0.1");
Eric Orthcd71ede2021-09-14 18:18:50662 context_.set_host_resolver(&host_resolver);
663
664 EXPECT_TRUE(ConnectAndWait(ws_url));
665
666 // Expect request to have reached the server using the upgraded URL.
667 EXPECT_EQ(event_interface_->response()->url, wss_url);
668}
669
ricea433bdab2015-01-26 07:25:37670} // namespace
671
672} // namespace net