blob: 7a97f50b41fe6e8299accf0e95beefca33127948 [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>
15
16#include "base/bind.h"
17#include "base/bind_helpers.h"
18#include "base/callback.h"
skyostil4891b25b2015-06-11 11:43:4519#include "base/location.h"
Avi Drissman13fc8932015-12-20 04:40:4620#include "base/macros.h"
danakj9c5cab52016-04-16 00:54:3321#include "base/memory/ptr_util.h"
ricea433bdab2015-01-26 07:25:3722#include "base/run_loop.h"
skyostil4891b25b2015-06-11 11:43:4523#include "base/single_thread_task_runner.h"
Adam Ricecb76ac62015-02-20 05:33:2524#include "base/strings/string_piece.h"
gabf767595f2016-05-11 18:50:3525#include "base/threading/thread_task_runner_handle.h"
Sergey Ulanova337dcd2017-09-08 20:53:1426#include "build/build_config.h"
ricea433bdab2015-01-26 07:25:3727#include "net/base/auth.h"
ryansturm7de050c2016-02-23 00:10:2128#include "net/base/proxy_delegate.h"
ricea433bdab2015-01-26 07:25:3729#include "net/proxy/proxy_service.h"
tommycli59a63432015-11-06 00:10:5530#include "net/test/embedded_test_server/embedded_test_server.h"
ricea433bdab2015-01-26 07:25:3731#include "net/test/spawned_test_server/spawned_test_server.h"
rsleevia69c79a2016-06-22 03:28:4332#include "net/test/test_data_directory.h"
rhalavati9ebaba7e2017-04-27 06:16:2933#include "net/traffic_annotation/network_traffic_annotation_test_helper.h"
ricea433bdab2015-01-26 07:25:3734#include "net/url_request/url_request_test_util.h"
35#include "net/websockets/websocket_channel.h"
36#include "net/websockets/websocket_event_interface.h"
37#include "testing/gtest/include/gtest/gtest.h"
mkwst4997ce82015-07-25 12:00:0538#include "url/origin.h"
ricea433bdab2015-01-26 07:25:3739
40namespace net {
41
yhirano4a593832016-10-24 18:58:2242class URLRequest;
43
ricea433bdab2015-01-26 07:25:3744namespace {
45
46static const char kEchoServer[] = "echo-with-no-extension";
47
Adam Ricecb76ac62015-02-20 05:33:2548// Simplify changing URL schemes.
49GURL ReplaceUrlScheme(const GURL& in_url, const base::StringPiece& scheme) {
50 GURL::Replacements replacements;
51 replacements.SetSchemeStr(scheme);
52 return in_url.ReplaceComponents(replacements);
53}
54
ricea433bdab2015-01-26 07:25:3755// An implementation of WebSocketEventInterface that waits for and records the
56// results of the connect.
57class ConnectTestingEventInterface : public WebSocketEventInterface {
58 public:
59 ConnectTestingEventInterface();
60
61 void WaitForResponse();
62
63 bool failed() const { return failed_; }
64
65 // Only set if the handshake failed, otherwise empty.
66 std::string failure_message() const;
67
68 std::string selected_subprotocol() const;
69
70 std::string extensions() const;
71
72 // Implementation of WebSocketEventInterface.
yhirano4a593832016-10-24 18:58:2273 void OnCreateURLRequest(URLRequest* request) override {}
74
tyoshinoc06da562015-03-06 06:02:4275 ChannelState OnAddChannelResponse(const std::string& selected_subprotocol,
ricea433bdab2015-01-26 07:25:3776 const std::string& extensions) override;
77
78 ChannelState OnDataFrame(bool fin,
79 WebSocketMessageType type,
darin0da77e922016-10-04 17:31:2380 scoped_refptr<IOBuffer> data,
81 size_t data_size) override;
ricea433bdab2015-01-26 07:25:3782
tfarina8a2c66c22015-10-13 19:14:4983 ChannelState OnFlowControl(int64_t quota) override;
ricea433bdab2015-01-26 07:25:3784
85 ChannelState OnClosingHandshake() override;
86
87 ChannelState OnDropChannel(bool was_clean,
tfarina8a2c66c22015-10-13 19:14:4988 uint16_t code,
ricea433bdab2015-01-26 07:25:3789 const std::string& reason) override;
90
91 ChannelState OnFailChannel(const std::string& message) override;
92
93 ChannelState OnStartOpeningHandshake(
danakj9c5cab52016-04-16 00:54:3394 std::unique_ptr<WebSocketHandshakeRequestInfo> request) override;
ricea433bdab2015-01-26 07:25:3795
96 ChannelState OnFinishOpeningHandshake(
danakj9c5cab52016-04-16 00:54:3397 std::unique_ptr<WebSocketHandshakeResponseInfo> response) override;
ricea433bdab2015-01-26 07:25:3798
99 ChannelState OnSSLCertificateError(
danakj9c5cab52016-04-16 00:54:33100 std::unique_ptr<SSLErrorCallbacks> ssl_error_callbacks,
ricea433bdab2015-01-26 07:25:37101 const GURL& url,
102 const SSLInfo& ssl_info,
103 bool fatal) override;
104
105 private:
106 void QuitNestedEventLoop();
107
108 // failed_ is true if the handshake failed (ie. OnFailChannel was called).
109 bool failed_;
110 std::string selected_subprotocol_;
111 std::string extensions_;
112 std::string failure_message_;
113 base::RunLoop run_loop_;
114
115 DISALLOW_COPY_AND_ASSIGN(ConnectTestingEventInterface);
116};
117
tyoshinoc06da562015-03-06 06:02:42118ConnectTestingEventInterface::ConnectTestingEventInterface() : failed_(false) {
ricea433bdab2015-01-26 07:25:37119}
120
121void ConnectTestingEventInterface::WaitForResponse() {
122 run_loop_.Run();
123}
124
125std::string ConnectTestingEventInterface::failure_message() const {
126 return failure_message_;
127}
128
129std::string ConnectTestingEventInterface::selected_subprotocol() const {
130 return selected_subprotocol_;
131}
132
133std::string ConnectTestingEventInterface::extensions() const {
134 return extensions_;
135}
136
137// Make the function definitions below less verbose.
138typedef ConnectTestingEventInterface::ChannelState ChannelState;
139
140ChannelState ConnectTestingEventInterface::OnAddChannelResponse(
ricea433bdab2015-01-26 07:25:37141 const std::string& selected_subprotocol,
142 const std::string& extensions) {
ricea433bdab2015-01-26 07:25:37143 selected_subprotocol_ = selected_subprotocol;
144 extensions_ = extensions;
145 QuitNestedEventLoop();
tyoshinoc06da562015-03-06 06:02:42146 return CHANNEL_ALIVE;
ricea433bdab2015-01-26 07:25:37147}
148
149ChannelState ConnectTestingEventInterface::OnDataFrame(
150 bool fin,
151 WebSocketMessageType type,
darin0da77e922016-10-04 17:31:23152 scoped_refptr<IOBuffer> data,
153 size_t data_size) {
ricea433bdab2015-01-26 07:25:37154 return CHANNEL_ALIVE;
155}
156
tfarina8a2c66c22015-10-13 19:14:49157ChannelState ConnectTestingEventInterface::OnFlowControl(int64_t quota) {
ricea433bdab2015-01-26 07:25:37158 return CHANNEL_ALIVE;
159}
160
161ChannelState ConnectTestingEventInterface::OnClosingHandshake() {
162 return CHANNEL_ALIVE;
163}
164
165ChannelState ConnectTestingEventInterface::OnDropChannel(
166 bool was_clean,
tfarina8a2c66c22015-10-13 19:14:49167 uint16_t code,
ricea433bdab2015-01-26 07:25:37168 const std::string& reason) {
169 return CHANNEL_DELETED;
170}
171
172ChannelState ConnectTestingEventInterface::OnFailChannel(
173 const std::string& message) {
174 failed_ = true;
175 failure_message_ = message;
176 QuitNestedEventLoop();
177 return CHANNEL_DELETED;
178}
179
180ChannelState ConnectTestingEventInterface::OnStartOpeningHandshake(
danakj9c5cab52016-04-16 00:54:33181 std::unique_ptr<WebSocketHandshakeRequestInfo> request) {
ricea433bdab2015-01-26 07:25:37182 return CHANNEL_ALIVE;
183}
184
185ChannelState ConnectTestingEventInterface::OnFinishOpeningHandshake(
danakj9c5cab52016-04-16 00:54:33186 std::unique_ptr<WebSocketHandshakeResponseInfo> response) {
ricea433bdab2015-01-26 07:25:37187 return CHANNEL_ALIVE;
188}
189
190ChannelState ConnectTestingEventInterface::OnSSLCertificateError(
danakj9c5cab52016-04-16 00:54:33191 std::unique_ptr<SSLErrorCallbacks> ssl_error_callbacks,
ricea433bdab2015-01-26 07:25:37192 const GURL& url,
193 const SSLInfo& ssl_info,
194 bool fatal) {
skyostil4891b25b2015-06-11 11:43:45195 base::ThreadTaskRunnerHandle::Get()->PostTask(
ricea433bdab2015-01-26 07:25:37196 FROM_HERE, base::Bind(&SSLErrorCallbacks::CancelSSLRequest,
197 base::Owned(ssl_error_callbacks.release()),
198 ERR_SSL_PROTOCOL_ERROR, &ssl_info));
199 return CHANNEL_ALIVE;
200}
201
202void ConnectTestingEventInterface::QuitNestedEventLoop() {
203 run_loop_.Quit();
204}
205
206// A subclass of TestNetworkDelegate that additionally implements the
207// OnResolveProxy callback and records the information passed to it.
ryansturm7de050c2016-02-23 00:10:21208class TestProxyDelegateWithProxyInfo : public ProxyDelegate {
ricea433bdab2015-01-26 07:25:37209 public:
ryansturm7de050c2016-02-23 00:10:21210 TestProxyDelegateWithProxyInfo() {}
ricea433bdab2015-01-26 07:25:37211
212 struct ResolvedProxyInfo {
213 GURL url;
214 ProxyInfo proxy_info;
215 };
216
217 const ResolvedProxyInfo& resolved_proxy_info() const {
218 return resolved_proxy_info_;
219 }
220
221 protected:
222 void OnResolveProxy(const GURL& url,
ryansturm4bab06832016-03-03 23:41:07223 const std::string& method,
Reilly Grantb414ace72017-11-14 23:03:22224 const ProxyRetryInfoMap& proxy_retry_info,
ricea433bdab2015-01-26 07:25:37225 ProxyInfo* result) override {
226 resolved_proxy_info_.url = url;
227 resolved_proxy_info_.proxy_info = *result;
228 }
229
ryansturm7de050c2016-02-23 00:10:21230 void OnTunnelConnectCompleted(const HostPortPair& endpoint,
231 const HostPortPair& proxy_server,
232 int net_error) override {}
233 void OnFallback(const ProxyServer& bad_proxy, int net_error) override {}
ryansturm7de050c2016-02-23 00:10:21234 void OnBeforeTunnelRequest(const HostPortPair& proxy_server,
235 HttpRequestHeaders* extra_headers) override {}
236 void OnTunnelHeadersReceived(
237 const HostPortPair& origin,
238 const HostPortPair& proxy_server,
239 const HttpResponseHeaders& response_headers) override {}
240 bool IsTrustedSpdyProxy(const net::ProxyServer& proxy_server) override {
241 return true;
242 }
tbansalc3308d72016-08-27 10:25:04243 void GetAlternativeProxy(
244 const GURL& url,
245 const ProxyServer& resolved_proxy_server,
246 ProxyServer* alternative_proxy_server) const override {}
247 void OnAlternativeProxyBroken(
248 const ProxyServer& alternative_proxy_server) override {}
ryansturm7de050c2016-02-23 00:10:21249
ricea433bdab2015-01-26 07:25:37250 private:
251 ResolvedProxyInfo resolved_proxy_info_;
252
ryansturm7de050c2016-02-23 00:10:21253 DISALLOW_COPY_AND_ASSIGN(TestProxyDelegateWithProxyInfo);
ricea433bdab2015-01-26 07:25:37254};
255
256class WebSocketEndToEndTest : public ::testing::Test {
257 protected:
258 WebSocketEndToEndTest()
Adam Ricecb76ac62015-02-20 05:33:25259 : event_interface_(),
ryansturm7de050c2016-02-23 00:10:21260 proxy_delegate_(new TestProxyDelegateWithProxyInfo),
ricea433bdab2015-01-26 07:25:37261 context_(true),
Adam Ricecb76ac62015-02-20 05:33:25262 channel_(),
ricea433bdab2015-01-26 07:25:37263 initialised_context_(false) {}
264
265 // Initialise the URLRequestContext. Normally done automatically by
266 // ConnectAndWait(). This method is for the use of tests that need the
267 // URLRequestContext initialised before calling ConnectAndWait().
268 void InitialiseContext() {
ryansturm7de050c2016-02-23 00:10:21269 context_.set_proxy_delegate(proxy_delegate_.get());
ricea433bdab2015-01-26 07:25:37270 context_.Init();
271 initialised_context_ = true;
272 }
273
274 // Send the connect request to |socket_url| and wait for a response. Returns
275 // true if the handshake succeeded.
276 bool ConnectAndWait(const GURL& socket_url) {
277 if (!initialised_context_) {
278 InitialiseContext();
279 }
Daniel Cheng88186bd52017-10-20 08:14:46280 url::Origin origin = url::Origin::Create(GURL("http://localhost"));
Mike Westb85da8ed2017-08-10 14:16:46281 GURL site_for_cookies("http://localhost/");
Adam Ricecb76ac62015-02-20 05:33:25282 event_interface_ = new ConnectTestingEventInterface;
283 channel_.reset(
danakj9c5cab52016-04-16 00:54:33284 new WebSocketChannel(base::WrapUnique(event_interface_), &context_));
alladacef397d2016-06-29 17:52:23285 channel_->SendAddChannelRequest(GURL(socket_url), sub_protocols_, origin,
Mike Westb85da8ed2017-08-10 14:16:46286 site_for_cookies, "");
ricea433bdab2015-01-26 07:25:37287 event_interface_->WaitForResponse();
288 return !event_interface_->failed();
289 }
290
291 ConnectTestingEventInterface* event_interface_; // owned by channel_
danakj9c5cab52016-04-16 00:54:33292 std::unique_ptr<TestProxyDelegateWithProxyInfo> proxy_delegate_;
ricea433bdab2015-01-26 07:25:37293 TestURLRequestContext context_;
danakj9c5cab52016-04-16 00:54:33294 std::unique_ptr<WebSocketChannel> channel_;
ricea5acb1faf72015-03-16 15:34:00295 std::vector<std::string> sub_protocols_;
ricea433bdab2015-01-26 07:25:37296 bool initialised_context_;
297};
298
ricea433bdab2015-01-26 07:25:37299// Basic test of connectivity. If this test fails, nothing else can be expected
300// to work.
Sergey Ulanov4c786d32017-09-08 22:53:25301TEST_F(WebSocketEndToEndTest, BasicSmokeTest) {
ricea433bdab2015-01-26 07:25:37302 SpawnedTestServer ws_server(SpawnedTestServer::TYPE_WS,
ricea433bdab2015-01-26 07:25:37303 GetWebSocketTestDataDirectory());
304 ASSERT_TRUE(ws_server.Start());
305 EXPECT_TRUE(ConnectAndWait(ws_server.GetURL(kEchoServer)));
306}
307
308// Test for issue crbug.com/433695 "Unencrypted WebSocket connection via
309// authenticated proxy times out"
310// TODO(ricea): Enable this when the issue is fixed.
311TEST_F(WebSocketEndToEndTest, DISABLED_HttpsProxyUnauthedFails) {
312 SpawnedTestServer proxy_server(SpawnedTestServer::TYPE_BASIC_AUTH_PROXY,
ricea433bdab2015-01-26 07:25:37313 base::FilePath());
314 SpawnedTestServer ws_server(SpawnedTestServer::TYPE_WS,
ricea433bdab2015-01-26 07:25:37315 GetWebSocketTestDataDirectory());
316 ASSERT_TRUE(proxy_server.StartInBackground());
317 ASSERT_TRUE(ws_server.StartInBackground());
318 ASSERT_TRUE(proxy_server.BlockUntilStarted());
319 ASSERT_TRUE(ws_server.BlockUntilStarted());
320 std::string proxy_config =
321 "https=" + proxy_server.host_port_pair().ToString();
danakj9c5cab52016-04-16 00:54:33322 std::unique_ptr<ProxyService> proxy_service(
ricea433bdab2015-01-26 07:25:37323 ProxyService::CreateFixed(proxy_config));
324 ASSERT_TRUE(proxy_service);
325 context_.set_proxy_service(proxy_service.get());
326 EXPECT_FALSE(ConnectAndWait(ws_server.GetURL(kEchoServer)));
327 EXPECT_EQ("Proxy authentication failed", event_interface_->failure_message());
328}
329
Sergey Ulanov4c786d32017-09-08 22:53:25330// These test are not compatible with RemoteTestServer because RemoteTestServer
331// doesn't support TYPE_BASIC_AUTH_PROXY.
332// TODO(ricea): Make these tests work. See crbug.com/441711.
333#if defined(OS_ANDROID) || defined(OS_FUCHSIA)
334#define MAYBE_HttpsWssProxyUnauthedFails DISABLED_HttpsWssProxyUnauthedFails
335#define MAYBE_HttpsProxyUsed DISABLED_HttpsProxyUsed
336#else
337#define MAYBE_HttpsWssProxyUnauthedFails HttpsWssProxyUnauthedFails
338#define MAYBE_HttpsProxyUsed HttpsProxyUsed
339#endif
340
341TEST_F(WebSocketEndToEndTest, MAYBE_HttpsWssProxyUnauthedFails) {
ricea433bdab2015-01-26 07:25:37342 SpawnedTestServer proxy_server(SpawnedTestServer::TYPE_BASIC_AUTH_PROXY,
ricea433bdab2015-01-26 07:25:37343 base::FilePath());
344 SpawnedTestServer wss_server(SpawnedTestServer::TYPE_WSS,
ricea433bdab2015-01-26 07:25:37345 GetWebSocketTestDataDirectory());
346 ASSERT_TRUE(proxy_server.StartInBackground());
347 ASSERT_TRUE(wss_server.StartInBackground());
348 ASSERT_TRUE(proxy_server.BlockUntilStarted());
349 ASSERT_TRUE(wss_server.BlockUntilStarted());
350 std::string proxy_config =
351 "https=" + proxy_server.host_port_pair().ToString();
danakj9c5cab52016-04-16 00:54:33352 std::unique_ptr<ProxyService> proxy_service(
ricea433bdab2015-01-26 07:25:37353 ProxyService::CreateFixed(proxy_config));
354 ASSERT_TRUE(proxy_service);
355 context_.set_proxy_service(proxy_service.get());
356 EXPECT_FALSE(ConnectAndWait(wss_server.GetURL(kEchoServer)));
357 EXPECT_EQ("Proxy authentication failed", event_interface_->failure_message());
358}
359
360// Regression test for crbug/426736 "WebSocket connections not using configured
361// system HTTPS Proxy".
Sergey Ulanov4c786d32017-09-08 22:53:25362TEST_F(WebSocketEndToEndTest, MAYBE_HttpsProxyUsed) {
ricea433bdab2015-01-26 07:25:37363 SpawnedTestServer proxy_server(SpawnedTestServer::TYPE_BASIC_AUTH_PROXY,
ricea433bdab2015-01-26 07:25:37364 base::FilePath());
365 SpawnedTestServer ws_server(SpawnedTestServer::TYPE_WS,
ricea433bdab2015-01-26 07:25:37366 GetWebSocketTestDataDirectory());
367 ASSERT_TRUE(proxy_server.StartInBackground());
368 ASSERT_TRUE(ws_server.StartInBackground());
369 ASSERT_TRUE(proxy_server.BlockUntilStarted());
370 ASSERT_TRUE(ws_server.BlockUntilStarted());
371 std::string proxy_config = "https=" +
372 proxy_server.host_port_pair().ToString() + ";" +
373 "http=" + proxy_server.host_port_pair().ToString();
danakj9c5cab52016-04-16 00:54:33374 std::unique_ptr<ProxyService> proxy_service(
ricea433bdab2015-01-26 07:25:37375 ProxyService::CreateFixed(proxy_config));
376 context_.set_proxy_service(proxy_service.get());
377 InitialiseContext();
378
379 // The test server doesn't have an unauthenticated proxy mode. WebSockets
380 // cannot provide auth information that isn't already cached, so it's
381 // necessary to preflight an HTTP request to authenticate against the proxy.
ricea433bdab2015-01-26 07:25:37382 // It doesn't matter what the URL is, as long as it is an HTTP navigation.
383 GURL http_page =
Adam Ricecb76ac62015-02-20 05:33:25384 ReplaceUrlScheme(ws_server.GetURL("connect_check.html"), "http");
ricea433bdab2015-01-26 07:25:37385 TestDelegate delegate;
386 delegate.set_credentials(
387 AuthCredentials(base::ASCIIToUTF16("foo"), base::ASCIIToUTF16("bar")));
388 {
rhalavati9ebaba7e2017-04-27 06:16:29389 std::unique_ptr<URLRequest> request(context_.CreateRequest(
390 http_page, DEFAULT_PRIORITY, &delegate, TRAFFIC_ANNOTATION_FOR_TESTS));
ricea433bdab2015-01-26 07:25:37391 request->Start();
392 // TestDelegate exits the message loop when the request completes by
393 // default.
394 base::RunLoop().Run();
395 EXPECT_TRUE(delegate.auth_required_called());
396 }
397
398 GURL ws_url = ws_server.GetURL(kEchoServer);
399 EXPECT_TRUE(ConnectAndWait(ws_url));
ryansturm7de050c2016-02-23 00:10:21400 const TestProxyDelegateWithProxyInfo::ResolvedProxyInfo& info =
401 proxy_delegate_->resolved_proxy_info();
ricea433bdab2015-01-26 07:25:37402 EXPECT_EQ(ws_url, info.url);
403 EXPECT_TRUE(info.proxy_info.is_http());
404}
405
ricea23c3f942015-02-02 13:35:13406// This is a regression test for crbug.com/408061 Crash in
407// net::WebSocketBasicHandshakeStream::Upgrade.
Sergey Ulanov4c786d32017-09-08 22:53:25408TEST_F(WebSocketEndToEndTest, TruncatedResponse) {
ricea23c3f942015-02-02 13:35:13409 SpawnedTestServer ws_server(SpawnedTestServer::TYPE_WS,
ricea23c3f942015-02-02 13:35:13410 GetWebSocketTestDataDirectory());
411 ASSERT_TRUE(ws_server.Start());
412 InitialiseContext();
413
414 GURL ws_url = ws_server.GetURL("truncated-headers");
415 EXPECT_FALSE(ConnectAndWait(ws_url));
416}
417
Adam Ricecb76ac62015-02-20 05:33:25418// Regression test for crbug.com/455215 "HSTS not applied to WebSocket"
Sergey Ulanov4c786d32017-09-08 22:53:25419TEST_F(WebSocketEndToEndTest, HstsHttpsToWebSocket) {
tommycli59a63432015-11-06 00:10:55420 EmbeddedTestServer https_server(net::EmbeddedTestServer::Type::TYPE_HTTPS);
421 https_server.SetSSLConfig(
422 net::EmbeddedTestServer::CERT_COMMON_NAME_IS_DOMAIN);
423 https_server.ServeFilesFromSourceDirectory("net/data/url_request_unittest");
424
estarka5da76702015-04-09 04:00:16425 SpawnedTestServer::SSLOptions ssl_options(
426 SpawnedTestServer::SSLOptions::CERT_COMMON_NAME_IS_DOMAIN);
Adam Ricecb76ac62015-02-20 05:33:25427 SpawnedTestServer wss_server(SpawnedTestServer::TYPE_WSS, ssl_options,
428 GetWebSocketTestDataDirectory());
estarka5da76702015-04-09 04:00:16429
tommycli59a63432015-11-06 00:10:55430 ASSERT_TRUE(https_server.Start());
431 ASSERT_TRUE(wss_server.Start());
Adam Ricecb76ac62015-02-20 05:33:25432 InitialiseContext();
433 // Set HSTS via https:
434 TestDelegate delegate;
tommycli59a63432015-11-06 00:10:55435 GURL https_page = https_server.GetURL("/hsts-headers.html");
rhalavati9ebaba7e2017-04-27 06:16:29436 std::unique_ptr<URLRequest> request(context_.CreateRequest(
437 https_page, DEFAULT_PRIORITY, &delegate, TRAFFIC_ANNOTATION_FOR_TESTS));
Adam Ricecb76ac62015-02-20 05:33:25438 request->Start();
439 // TestDelegate exits the message loop when the request completes.
440 base::RunLoop().Run();
maksim.sisov7f60c8e2016-09-16 19:38:17441 EXPECT_EQ(OK, delegate.request_status());
Adam Ricecb76ac62015-02-20 05:33:25442
443 // Check HSTS with ws:
444 // Change the scheme from wss: to ws: to verify that it is switched back.
445 GURL ws_url = ReplaceUrlScheme(wss_server.GetURL(kEchoServer), "ws");
446 EXPECT_TRUE(ConnectAndWait(ws_url));
447}
448
Sergey Ulanov4c786d32017-09-08 22:53:25449TEST_F(WebSocketEndToEndTest, HstsWebSocketToHttps) {
tommycli59a63432015-11-06 00:10:55450 EmbeddedTestServer https_server(net::EmbeddedTestServer::Type::TYPE_HTTPS);
451 https_server.SetSSLConfig(
452 net::EmbeddedTestServer::CERT_COMMON_NAME_IS_DOMAIN);
453 https_server.ServeFilesFromSourceDirectory("net/data/url_request_unittest");
454
estarka5da76702015-04-09 04:00:16455 SpawnedTestServer::SSLOptions ssl_options(
456 SpawnedTestServer::SSLOptions::CERT_COMMON_NAME_IS_DOMAIN);
Adam Ricecb76ac62015-02-20 05:33:25457 SpawnedTestServer wss_server(SpawnedTestServer::TYPE_WSS, ssl_options,
458 GetWebSocketTestDataDirectory());
tommycli59a63432015-11-06 00:10:55459 ASSERT_TRUE(https_server.Start());
460 ASSERT_TRUE(wss_server.Start());
Adam Ricecb76ac62015-02-20 05:33:25461 InitialiseContext();
462 // Set HSTS via wss:
463 GURL wss_url = wss_server.GetURL("set-hsts");
464 EXPECT_TRUE(ConnectAndWait(wss_url));
465
466 // Verify via http:
467 TestDelegate delegate;
468 GURL http_page =
tommycli59a63432015-11-06 00:10:55469 ReplaceUrlScheme(https_server.GetURL("/simple.html"), "http");
rhalavati9ebaba7e2017-04-27 06:16:29470 std::unique_ptr<URLRequest> request(context_.CreateRequest(
471 http_page, DEFAULT_PRIORITY, &delegate, TRAFFIC_ANNOTATION_FOR_TESTS));
Adam Ricecb76ac62015-02-20 05:33:25472 request->Start();
473 // TestDelegate exits the message loop when the request completes.
474 base::RunLoop().Run();
maksim.sisov7f60c8e2016-09-16 19:38:17475 EXPECT_EQ(OK, delegate.request_status());
Adam Ricecb76ac62015-02-20 05:33:25476 EXPECT_TRUE(request->url().SchemeIs("https"));
477}
478
Sergey Ulanov4c786d32017-09-08 22:53:25479TEST_F(WebSocketEndToEndTest, HstsWebSocketToWebSocket) {
estarka5da76702015-04-09 04:00:16480 SpawnedTestServer::SSLOptions ssl_options(
481 SpawnedTestServer::SSLOptions::CERT_COMMON_NAME_IS_DOMAIN);
Adam Ricecb76ac62015-02-20 05:33:25482 SpawnedTestServer wss_server(SpawnedTestServer::TYPE_WSS, ssl_options,
483 GetWebSocketTestDataDirectory());
484 ASSERT_TRUE(wss_server.Start());
485 InitialiseContext();
486 // Set HSTS via wss:
487 GURL wss_url = wss_server.GetURL("set-hsts");
488 EXPECT_TRUE(ConnectAndWait(wss_url));
489
490 // Verify via wss:
491 GURL ws_url = ReplaceUrlScheme(wss_server.GetURL(kEchoServer), "ws");
492 EXPECT_TRUE(ConnectAndWait(ws_url));
493}
494
ricea5acb1faf72015-03-16 15:34:00495// Regression test for crbug.com/180504 "WebSocket handshake fails when HTTP
496// headers have trailing LWS".
Sergey Ulanov4c786d32017-09-08 22:53:25497TEST_F(WebSocketEndToEndTest, TrailingWhitespace) {
ricea5acb1faf72015-03-16 15:34:00498 SpawnedTestServer ws_server(SpawnedTestServer::TYPE_WS,
ricea5acb1faf72015-03-16 15:34:00499 GetWebSocketTestDataDirectory());
500 ASSERT_TRUE(ws_server.Start());
501
502 GURL ws_url = ws_server.GetURL("trailing-whitespace");
503 sub_protocols_.push_back("sip");
504 EXPECT_TRUE(ConnectAndWait(ws_url));
505 EXPECT_EQ("sip", event_interface_->selected_subprotocol());
506}
507
riceae1d67672015-03-19 10:10:17508// This is a regression test for crbug.com/169448 "WebSockets should support
509// header continuations"
510// TODO(ricea): HTTP continuation headers have been deprecated by RFC7230. If
511// support for continuation headers is removed from Chrome, then this test will
512// break and should be removed.
Sergey Ulanov4c786d32017-09-08 22:53:25513TEST_F(WebSocketEndToEndTest, HeaderContinuations) {
riceae1d67672015-03-19 10:10:17514 SpawnedTestServer ws_server(SpawnedTestServer::TYPE_WS,
riceae1d67672015-03-19 10:10:17515 GetWebSocketTestDataDirectory());
516 ASSERT_TRUE(ws_server.Start());
517
518 GURL ws_url = ws_server.GetURL("header-continuation");
519
520 EXPECT_TRUE(ConnectAndWait(ws_url));
521 EXPECT_EQ("permessage-deflate; server_max_window_bits=10",
522 event_interface_->extensions());
523}
524
ricea433bdab2015-01-26 07:25:37525} // namespace
526
527} // namespace net