| // Copyright 2012 The Chromium Authors |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "content/browser/devtools/devtools_http_handler.h" |
| |
| #include <stdint.h> |
| |
| #include <memory> |
| #include <utility> |
| |
| #include "base/command_line.h" |
| #include "base/files/file_util.h" |
| #include "base/files/scoped_temp_dir.h" |
| #include "base/functional/bind.h" |
| #include "base/json/json_reader.h" |
| #include "base/location.h" |
| #include "base/memory/ptr_util.h" |
| #include "base/run_loop.h" |
| #include "base/strings/escape.h" |
| #include "base/strings/string_number_conversions.h" |
| #include "base/strings/string_split.h" |
| #include "base/strings/stringprintf.h" |
| #include "base/task/single_thread_task_runner.h" |
| #include "base/test/task_environment.h" |
| #include "base/values.h" |
| #include "content/browser/devtools/devtools_agent_host_impl.h" |
| #include "content/browser/devtools/devtools_manager.h" |
| #include "content/public/browser/browser_task_traits.h" |
| #include "content/public/browser/browser_thread.h" |
| #include "content/public/browser/content_browser_client.h" |
| #include "content/public/browser/devtools_manager_delegate.h" |
| #include "content/public/browser/devtools_socket_factory.h" |
| #include "content/public/common/content_client.h" |
| #include "content/public/common/content_switches.h" |
| #include "content/public/test/browser_task_environment.h" |
| #include "content/public/test/mock_devtools_agent_host.h" |
| #include "content/public/test/test_utils.h" |
| #include "net/base/completion_once_callback.h" |
| #include "net/base/ip_address.h" |
| #include "net/base/ip_endpoint.h" |
| #include "net/base/net_errors.h" |
| #include "net/socket/server_socket.h" |
| #include "net/socket/tcp_server_socket.h" |
| #include "net/traffic_annotation/network_traffic_annotation_test_helper.h" |
| #include "net/url_request/url_request_context.h" |
| #include "net/url_request/url_request_context_builder.h" |
| #include "net/url_request/url_request_test_util.h" |
| #include "testing/gmock/include/gmock/gmock.h" |
| #include "testing/gtest/include/gtest/gtest.h" |
| |
| namespace content { |
| namespace { |
| |
| using ::testing::HasSubstr; |
| using ::testing::Not; |
| using ::testing::Return; |
| |
| const uint16_t kDummyPort = 4321; |
| const base::FilePath::CharType kDevToolsActivePortFileName[] = |
| FILE_PATH_LITERAL("DevToolsActivePort"); |
| |
| class DummyServerSocket : public net::ServerSocket { |
| public: |
| // net::ServerSocket "implementation" |
| int Listen(const net::IPEndPoint& address, |
| int backlog, |
| std::optional<bool> ipv6_only) override { |
| return net::OK; |
| } |
| |
| int GetLocalAddress(net::IPEndPoint* address) const override { |
| *address = net::IPEndPoint(net::IPAddress::IPv4Localhost(), kDummyPort); |
| return net::OK; |
| } |
| |
| int Accept(std::unique_ptr<net::StreamSocket>* socket, |
| net::CompletionOnceCallback callback) override { |
| return net::ERR_IO_PENDING; |
| } |
| }; |
| |
| class DummyServerSocketFactory : public DevToolsSocketFactory { |
| public: |
| DummyServerSocketFactory(base::OnceClosure create_socket_callback, |
| base::OnceClosure shutdown_callback) |
| : create_socket_callback_(std::move(create_socket_callback)), |
| shutdown_callback_(std::move(shutdown_callback)) {} |
| |
| ~DummyServerSocketFactory() override { |
| GetUIThreadTaskRunner({})->PostTask(FROM_HERE, |
| std::move(shutdown_callback_)); |
| } |
| |
| protected: |
| std::unique_ptr<net::ServerSocket> CreateForHttpServer() override { |
| GetUIThreadTaskRunner({})->PostTask(FROM_HERE, |
| std::move(create_socket_callback_)); |
| return std::make_unique<DummyServerSocket>(); |
| } |
| |
| std::unique_ptr<net::ServerSocket> CreateForTethering( |
| std::string* out_name) override { |
| return nullptr; |
| } |
| |
| base::OnceClosure create_socket_callback_; |
| base::OnceClosure shutdown_callback_; |
| }; |
| |
| class FailingServerSocketFactory : public DummyServerSocketFactory { |
| public: |
| FailingServerSocketFactory(base::OnceClosure create_socket_callback, |
| base::OnceClosure shutdown_callback) |
| : DummyServerSocketFactory(std::move(create_socket_callback), |
| std::move(shutdown_callback)) {} |
| |
| private: |
| std::unique_ptr<net::ServerSocket> CreateForHttpServer() override { |
| GetUIThreadTaskRunner({})->PostTask(FROM_HERE, |
| std::move(create_socket_callback_)); |
| return nullptr; |
| } |
| }; |
| |
| class TCPServerSocketFactory : public DummyServerSocketFactory { |
| public: |
| TCPServerSocketFactory(base::OnceClosure create_socket_callback, |
| base::OnceClosure shutdown_callback) |
| : DummyServerSocketFactory(std::move(create_socket_callback), |
| std::move(shutdown_callback)) {} |
| |
| int port() { return port_; } |
| |
| private: |
| std::unique_ptr<net::ServerSocket> CreateForHttpServer() override { |
| std::unique_ptr<net::ServerSocket> socket( |
| new net::TCPServerSocket(nullptr, net::NetLogSource())); |
| while (socket->ListenWithAddressAndPort("127.0.0.1", port_, 10) != |
| net::OK) { |
| if (++port_ > kDummyPort + 100) |
| return nullptr; |
| } |
| GetUIThreadTaskRunner({})->PostTask(FROM_HERE, |
| std::move(create_socket_callback_)); |
| return socket; |
| } |
| |
| int port_ = kDummyPort; |
| }; |
| |
| class MockDevToolsManagerDelegate : public DevToolsManagerDelegate { |
| public: |
| static MockDevToolsManagerDelegate* last_instance; |
| MockDevToolsManagerDelegate() { last_instance = this; } |
| MOCK_METHOD(scoped_refptr<DevToolsAgentHost>, |
| CreateNewTarget, |
| (const GURL& url, TargetType target_type, bool new_window), |
| (override)); |
| MOCK_METHOD(DevToolsAgentHost::List, |
| RemoteDebuggingTargets, |
| (TargetType target_type), |
| (override)); |
| }; |
| |
| MockDevToolsManagerDelegate* MockDevToolsManagerDelegate::last_instance = |
| nullptr; |
| |
| class MockDevToolsAgentHostWithType : public MockDevToolsAgentHost { |
| public: |
| explicit MockDevToolsAgentHostWithType(const std::string& type) |
| : type_(type) {} |
| |
| std::string GetType() override { return type_; } |
| |
| private: |
| ~MockDevToolsAgentHostWithType() override = default; |
| |
| std::string type_; |
| }; |
| |
| class BrowserClient : public ContentBrowserClient { |
| public: |
| BrowserClient() {} |
| ~BrowserClient() override {} |
| std::unique_ptr<content::DevToolsManagerDelegate> |
| CreateDevToolsManagerDelegate() override { |
| return std::make_unique<MockDevToolsManagerDelegate>(); |
| } |
| }; |
| |
| } |
| |
| class DevToolsHttpHandlerTest : public testing::Test { |
| public: |
| DevToolsHttpHandlerTest() |
| : task_environment_(content::BrowserTaskEnvironment::IO_MAINLOOP) {} |
| |
| void SetUp() override { |
| content_client_ = std::make_unique<ContentClient>(); |
| browser_content_client_ = std::make_unique<BrowserClient>(); |
| original_client_ = |
| SetBrowserClientForTesting(browser_content_client_.get()); |
| DevToolsManager::ShutdownForTests(); |
| } |
| |
| void TearDown() override { |
| SetBrowserClientForTesting(original_client_); |
| DevToolsManager::ShutdownForTests(); |
| } |
| |
| private: |
| std::unique_ptr<ContentClient> content_client_; |
| std::unique_ptr<ContentBrowserClient> browser_content_client_; |
| raw_ptr<ContentBrowserClient> original_client_ = nullptr; |
| content::BrowserTaskEnvironment task_environment_; |
| }; |
| |
| TEST_F(DevToolsHttpHandlerTest, TestStartStop) { |
| base::RunLoop run_loop, run_loop_2; |
| auto factory = std::make_unique<DummyServerSocketFactory>( |
| run_loop.QuitClosure(), run_loop_2.QuitClosure()); |
| DevToolsAgentHost::StartRemoteDebuggingServer( |
| std::move(factory), base::FilePath(), base::FilePath()); |
| // Our dummy socket factory will post a quit message once the server will |
| // become ready. |
| run_loop.Run(); |
| DevToolsAgentHost::StopRemoteDebuggingServer(); |
| // Make sure the handler actually stops. |
| run_loop_2.Run(); |
| } |
| |
| TEST_F(DevToolsHttpHandlerTest, TestServerSocketFailed) { |
| base::RunLoop run_loop, run_loop_2; |
| auto factory = std::make_unique<FailingServerSocketFactory>( |
| run_loop.QuitClosure(), run_loop_2.QuitClosure()); |
| LOG(INFO) << "Following error message is expected:"; |
| DevToolsAgentHost::StartRemoteDebuggingServer( |
| std::move(factory), base::FilePath(), base::FilePath()); |
| // Our dummy socket factory will post a quit message once the server will |
| // become ready. |
| run_loop.Run(); |
| for (int i = 0; i < 5; i++) |
| RunAllPendingInMessageLoop(BrowserThread::UI); |
| DevToolsAgentHost::StopRemoteDebuggingServer(); |
| // Make sure the handler actually stops. |
| run_loop_2.Run(); |
| } |
| |
| TEST_F(DevToolsHttpHandlerTest, TestDevToolsActivePort) { |
| base::RunLoop run_loop, run_loop_2; |
| base::ScopedTempDir temp_dir; |
| EXPECT_TRUE(temp_dir.CreateUniqueTempDir()); |
| auto factory = std::make_unique<DummyServerSocketFactory>( |
| run_loop.QuitClosure(), run_loop_2.QuitClosure()); |
| |
| DevToolsAgentHost::StartRemoteDebuggingServer( |
| std::move(factory), temp_dir.GetPath(), base::FilePath()); |
| // Our dummy socket factory will post a quit message once the server will |
| // become ready. |
| run_loop.Run(); |
| DevToolsAgentHost::StopRemoteDebuggingServer(); |
| // Make sure the handler actually stops. |
| run_loop_2.Run(); |
| |
| // Now make sure the DevToolsActivePort was written into the |
| // temporary directory and its contents are as expected. |
| base::FilePath active_port_file = |
| temp_dir.GetPath().Append(kDevToolsActivePortFileName); |
| EXPECT_TRUE(base::PathExists(active_port_file)); |
| std::string file_contents; |
| EXPECT_TRUE(base::ReadFileToString(active_port_file, &file_contents)); |
| std::vector<std::string> tokens = base::SplitString( |
| file_contents, "\n", base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL); |
| int port = 0; |
| EXPECT_TRUE(base::StringToInt(tokens[0], &port)); |
| EXPECT_EQ(static_cast<int>(kDummyPort), port); |
| } |
| |
| TEST_F(DevToolsHttpHandlerTest, MutatingActionsiRequireSafeVerb) { |
| base::RunLoop run_loop, run_loop_2; |
| auto* factory = new TCPServerSocketFactory(run_loop.QuitClosure(), |
| run_loop_2.QuitClosure()); |
| DevToolsAgentHost::StartRemoteDebuggingServer( |
| base::WrapUnique(factory), base::FilePath(), base::FilePath()); |
| // Our dummy socket factory will post a quit message once the server will |
| // become ready. |
| run_loop.Run(); |
| int port = factory->port(); |
| |
| net::TestDelegate delegate; |
| GURL url(base::StringPrintf("http://127.0.0.1:%d/json/new", port)); |
| auto request_context = net::CreateTestURLRequestContextBuilder()->Build(); |
| auto request = request_context->CreateRequest( |
| url, net::DEFAULT_PRIORITY, &delegate, TRAFFIC_ANNOTATION_FOR_TESTS); |
| request->Start(); |
| delegate.RunUntilComplete(); |
| EXPECT_GE(delegate.request_status(), 0); |
| EXPECT_EQ(405, request->response_info().headers->response_code()); |
| |
| request = request_context->CreateRequest( |
| url, net::DEFAULT_PRIORITY, &delegate, TRAFFIC_ANNOTATION_FOR_TESTS); |
| request->set_method("POST"); |
| request->Start(); |
| delegate.RunUntilComplete(); |
| EXPECT_GE(delegate.request_status(), 0); |
| EXPECT_EQ(405, request->response_info().headers->response_code()); |
| |
| EXPECT_CALL( |
| *MockDevToolsManagerDelegate::last_instance, |
| CreateNewTarget(GURL("about:blank"), DevToolsManagerDelegate::kFrame, |
| /*new_window=*/false)) |
| .WillOnce(Return(base::MakeRefCounted<MockDevToolsAgentHost>())); |
| |
| request = request_context->CreateRequest( |
| url, net::DEFAULT_PRIORITY, &delegate, TRAFFIC_ANNOTATION_FOR_TESTS); |
| request->set_method("PUT"); |
| request->Start(); |
| delegate.RunUntilComplete(); |
| EXPECT_GE(delegate.request_status(), 0); |
| EXPECT_EQ(200, request->response_info().headers->response_code()); |
| |
| DevToolsAgentHost::StopRemoteDebuggingServer(); |
| // Make sure the handler actually stops. |
| run_loop_2.Run(); |
| } |
| |
| TEST_F(DevToolsHttpHandlerTest, TestJsonNew) { |
| base::RunLoop run_loop, run_loop_2; |
| auto* factory = new TCPServerSocketFactory(run_loop.QuitClosure(), |
| run_loop_2.QuitClosure()); |
| DevToolsAgentHost::StartRemoteDebuggingServer( |
| base::WrapUnique(factory), base::FilePath(), base::FilePath()); |
| // Our dummy socket factory will post a quit message once the server will |
| // become ready. |
| run_loop.Run(); |
| int port = factory->port(); |
| net::TestDelegate delegate; |
| |
| EXPECT_CALL( |
| *MockDevToolsManagerDelegate::last_instance, |
| CreateNewTarget(GURL("about:blank"), DevToolsManagerDelegate::kFrame, |
| /*new_window=*/false)); |
| GURL url(base::StringPrintf("http://127.0.0.1:%d/json/new", port)); |
| auto request_context = net::CreateTestURLRequestContextBuilder()->Build(); |
| auto request = request_context->CreateRequest( |
| url, net::DEFAULT_PRIORITY, &delegate, TRAFFIC_ANNOTATION_FOR_TESTS); |
| request->set_method("PUT"); |
| request->Start(); |
| delegate.RunUntilComplete(); |
| EXPECT_GE(delegate.request_status(), 0); |
| |
| EXPECT_CALL( |
| *MockDevToolsManagerDelegate::last_instance, |
| CreateNewTarget(GURL("http://example.com"), |
| DevToolsManagerDelegate::kFrame, /*new_window=*/false)); |
| url = GURL(base::StringPrintf( |
| "http://127.0.0.1:%d/json/new?%s", port, |
| base::EscapeQueryParamValue("http://example.com", true).c_str())); |
| request = request_context->CreateRequest( |
| url, net::DEFAULT_PRIORITY, &delegate, TRAFFIC_ANNOTATION_FOR_TESTS); |
| request->set_method("PUT"); |
| request->Start(); |
| delegate.RunUntilComplete(); |
| EXPECT_GE(delegate.request_status(), 0); |
| |
| EXPECT_CALL( |
| *MockDevToolsManagerDelegate::last_instance, |
| CreateNewTarget(GURL("http://example.com"), DevToolsManagerDelegate::kTab, |
| /*new_window=*/false)); |
| url = GURL(base::StringPrintf( |
| "http://127.0.0.1:%d/json/new?%s&for_tab", port, |
| base::EscapeQueryParamValue("http://example.com", true).c_str())); |
| request = request_context->CreateRequest( |
| url, net::DEFAULT_PRIORITY, &delegate, TRAFFIC_ANNOTATION_FOR_TESTS); |
| request->set_method("PUT"); |
| request->Start(); |
| delegate.RunUntilComplete(); |
| EXPECT_GE(delegate.request_status(), 0); |
| |
| DevToolsAgentHost::StopRemoteDebuggingServer(); |
| // Make sure the handler actually stops. |
| run_loop_2.Run(); |
| } |
| |
| TEST_F(DevToolsHttpHandlerTest, TestJsonList) { |
| base::RunLoop run_loop, run_loop_2; |
| auto* factory = new TCPServerSocketFactory(run_loop.QuitClosure(), |
| run_loop_2.QuitClosure()); |
| DevToolsAgentHost::StartRemoteDebuggingServer( |
| base::WrapUnique(factory), base::FilePath(), base::FilePath()); |
| // Our dummy socket factory will post a quit message once the server will |
| // become ready. |
| run_loop.Run(); |
| int port = factory->port(); |
| net::TestDelegate delegate; |
| |
| EXPECT_CALL(*MockDevToolsManagerDelegate::last_instance, |
| RemoteDebuggingTargets(DevToolsManagerDelegate::kFrame)); |
| GURL url(base::StringPrintf("http://127.0.0.1:%d/json", port)); |
| auto request_context = net::CreateTestURLRequestContextBuilder()->Build(); |
| auto request = request_context->CreateRequest( |
| url, net::DEFAULT_PRIORITY, &delegate, TRAFFIC_ANNOTATION_FOR_TESTS); |
| request->set_method("PUT"); |
| request->Start(); |
| delegate.RunUntilComplete(); |
| |
| EXPECT_CALL(*MockDevToolsManagerDelegate::last_instance, |
| RemoteDebuggingTargets(DevToolsManagerDelegate::kFrame)) |
| .WillOnce(Return(std::vector<scoped_refptr<DevToolsAgentHost>>{ |
| base::MakeRefCounted<MockDevToolsAgentHostWithType>("service_worker"), |
| base::MakeRefCounted<MockDevToolsAgentHostWithType>("tab")})); |
| url = GURL(base::StringPrintf("http://127.0.0.1:%d/json/list", port)); |
| request = request_context->CreateRequest( |
| url, net::DEFAULT_PRIORITY, &delegate, TRAFFIC_ANNOTATION_FOR_TESTS); |
| request->set_method("PUT"); |
| request->Start(); |
| delegate.RunUntilComplete(); |
| EXPECT_THAT(delegate.data_received(), |
| HasSubstr(R"("type": "service_worker")")); |
| EXPECT_THAT(delegate.data_received(), Not(HasSubstr(R"("type": "tab")"))); |
| |
| EXPECT_CALL(*MockDevToolsManagerDelegate::last_instance, |
| RemoteDebuggingTargets(DevToolsManagerDelegate::kTab)) |
| .WillOnce(Return(std::vector<scoped_refptr<DevToolsAgentHost>>{ |
| base::MakeRefCounted<MockDevToolsAgentHostWithType>("service_worker"), |
| base::MakeRefCounted<MockDevToolsAgentHostWithType>("tab")})); |
| url = GURL(base::StringPrintf("http://127.0.0.1:%d/json/list?for_tab", port)); |
| request = request_context->CreateRequest( |
| url, net::DEFAULT_PRIORITY, &delegate, TRAFFIC_ANNOTATION_FOR_TESTS); |
| request->set_method("PUT"); |
| request->Start(); |
| delegate.RunUntilComplete(); |
| EXPECT_THAT(delegate.data_received(), |
| HasSubstr(R"("type": "service_worker")")); |
| EXPECT_THAT(delegate.data_received(), HasSubstr(R"("type": "tab")")); |
| |
| DevToolsAgentHost::StopRemoteDebuggingServer(); |
| // Make sure the handler actually stops. |
| run_loop_2.Run(); |
| } |
| |
| class DevToolsWebSocketHandlerTest : public DevToolsHttpHandlerTest { |
| public: |
| DevToolsWebSocketHandlerTest() = default; |
| |
| int StartServer() { |
| std::unique_ptr<TCPServerSocketFactory> factory = |
| std::make_unique<TCPServerSocketFactory>(run_loop_.QuitClosure(), |
| run_loop_2_.QuitClosure()); |
| TCPServerSocketFactory* factory_raw = factory.get(); |
| |
| DevToolsAgentHost::StartRemoteDebuggingServer( |
| std::move(factory), base::FilePath(), base::FilePath()); |
| // Our dummy socket factory will post a quit message once the server will |
| // become ready. |
| run_loop_.Run(); |
| return factory_raw->port(); |
| } |
| |
| void StopServer() { |
| DevToolsAgentHost::StopRemoteDebuggingServer(); |
| // Make sure the handler actually stops. |
| run_loop_2_.Run(); |
| } |
| |
| std::string GetWebSocketDebuggingURL(int port) { |
| GURL url(base::StringPrintf("http://127.0.0.1:%d/json/version", port)); |
| net::TestDelegate delegate; |
| auto request = request_context_->CreateRequest( |
| url, net::DEFAULT_PRIORITY, &delegate, TRAFFIC_ANNOTATION_FOR_TESTS); |
| request->Start(); |
| delegate.RunUntilComplete(); |
| EXPECT_GE(delegate.request_status(), 0); |
| std::optional<base::Value> response = |
| base::JSONReader::Read(delegate.data_received()); |
| base::Value::Dict* dict = response->GetIfDict(); |
| // Compute HTTP upgrade request URL. |
| std::string debugging_url = *dict->FindString("webSocketDebuggerUrl"); |
| std::string prefix = "ws://"; |
| return "http://" + debugging_url.substr(prefix.length()); |
| } |
| |
| std::unique_ptr<net::URLRequest> RunRequestUntilCompletion( |
| std::string url, |
| std::map<std::string, std::string> headers) { |
| net::TestDelegate delegate; |
| auto request = request_context_->CreateRequest( |
| GURL(url), net::DEFAULT_PRIORITY, &delegate, |
| TRAFFIC_ANNOTATION_FOR_TESTS); |
| for (auto const& [key, value] : headers) { |
| request->SetExtraRequestHeaderByName(key, value, true); |
| } |
| |
| request->Start(); |
| delegate.RunUntilComplete(); |
| EXPECT_GE(delegate.request_status(), 0); |
| return request; |
| } |
| |
| private: |
| std::unique_ptr<net::URLRequestContext> request_context_ = |
| net::CreateTestURLRequestContextBuilder()->Build(); |
| base::RunLoop run_loop_; |
| base::RunLoop run_loop_2_; |
| }; |
| |
| TEST_F(DevToolsWebSocketHandlerTest, |
| TestRejectsWebSocketConnectionsWithOrigin) { |
| int port = StartServer(); |
| |
| std::string debugging_url = GetWebSocketDebuggingURL(port); |
| |
| // Accepts an upgrade request without an Origin header. |
| auto request = |
| RunRequestUntilCompletion(debugging_url, { |
| {"connection", "upgrade"}, |
| {"upgrade", "websocket"}, |
| }); |
| // This error is expected because it's not a well-formed WS request. |
| // It means that the request is accepted by the server though. |
| EXPECT_EQ(request->GetResponseCode(), 500); |
| |
| // Denies an upgrade request with an Origin header. |
| request = RunRequestUntilCompletion(debugging_url, |
| {{"connection", "upgrade"}, |
| {"upgrade", "websocket"}, |
| {"origin", "http://localhost"}}); |
| EXPECT_EQ(request->GetResponseCode(), 403); |
| |
| StopServer(); |
| } |
| |
| TEST_F(DevToolsWebSocketHandlerTest, TestAllowsCLIOverrideAllowsOriginsStar) { |
| base::CommandLine::ForCurrentProcess()->AppendSwitchASCII( |
| switches::kRemoteAllowOrigins, "*"); |
| int port = StartServer(); |
| |
| std::string debugging_url = GetWebSocketDebuggingURL(port); |
| |
| auto request = RunRequestUntilCompletion(debugging_url, |
| { |
| {"connection", "upgrade"}, |
| {"upgrade", "websocket"}, |
| {"origin", "http://localhost"}, |
| }); |
| // This error is expected because it's not a well-formed WS request. |
| // It means that the request is accepted by the server though. |
| EXPECT_EQ(request->GetResponseCode(), 500); |
| |
| StopServer(); |
| } |
| |
| TEST_F(DevToolsWebSocketHandlerTest, TestAllowsCLIOverrideAllowsOrigins) { |
| base::CommandLine::ForCurrentProcess()->AppendSwitchASCII( |
| switches::kRemoteAllowOrigins, "http://localhost"); |
| int port = StartServer(); |
| |
| std::string debugging_url = GetWebSocketDebuggingURL(port); |
| |
| auto request = RunRequestUntilCompletion(debugging_url, |
| { |
| {"connection", "upgrade"}, |
| {"upgrade", "websocket"}, |
| {"origin", "http://localhost"}, |
| }); |
| // This error is expected because it's not a well-formed WS request. |
| // It means that the request is accepted by the server though. |
| EXPECT_EQ(request->GetResponseCode(), 500); |
| |
| request = RunRequestUntilCompletion(debugging_url, |
| { |
| {"connection", "upgrade"}, |
| {"upgrade", "websocket"}, |
| {"origin", "http://127.0.0.1"}, |
| }); |
| EXPECT_EQ(request->GetResponseCode(), 403); |
| |
| StopServer(); |
| } |
| |
| } // namespace content |