chromium/content/browser/direct_sockets/direct_sockets_tcp_browsertest.cc

// Copyright 2020 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifdef UNSAFE_BUFFERS_BUILD
// TODO(crbug.com/342213636): Remove this and spanify to fix the errors.
#pragma allow_unsafe_buffers
#endif

#include <stdint.h>

#include <optional>
#include <string>

#include "base/containers/span.h"
#include "base/run_loop.h"
#include "base/strings/strcat.h"
#include "base/test/bind.h"
#include "base/test/scoped_feature_list.h"
#include "base/test/test_future.h"
#include "build/build_config.h"
#include "content/browser/direct_sockets/direct_sockets_service_impl.h"
#include "content/browser/direct_sockets/direct_sockets_test_utils.h"
#include "content/browser/renderer_host/frame_tree_node.h"
#include "content/browser/renderer_host/render_frame_host_impl.h"
#include "content/public/browser/browser_context.h"
#include "content/public/browser/storage_partition.h"
#include "content/public/browser/web_contents.h"
#include "content/public/common/content_client.h"
#include "content/public/test/browser_test.h"
#include "content/public/test/browser_test_utils.h"
#include "content/public/test/content_browser_test.h"
#include "content/public/test/content_browser_test_utils.h"
#include "content/shell/browser/shell.h"
#include "mojo/public/cpp/bindings/remote.h"
#include "mojo/public/cpp/system/data_pipe.h"
#include "net/base/ip_address.h"
#include "net/base/ip_endpoint.h"
#include "net/base/net_errors.h"
#include "net/net_buildflags.h"
#include "net/test/embedded_test_server/embedded_test_server.h"
#include "net/traffic_annotation/network_traffic_annotation.h"
#include "net/traffic_annotation/network_traffic_annotation_test_helper.h"
#include "services/network/public/mojom/clear_data_filter.mojom.h"
#include "services/network/public/mojom/host_resolver.mojom.h"
#include "services/network/public/mojom/network_context.mojom.h"
#include "services/network/public/mojom/tcp_socket.mojom.h"
#include "testing/gmock/include/gmock/gmock-matchers.h"
#include "third_party/blink/public/common/features.h"
#include "third_party/blink/public/common/permissions_policy/permissions_policy.h"
#include "url/gurl.h"

#if BUILDFLAG(IS_CHROMEOS)
#include "chromeos/dbus/permission_broker/fake_permission_broker_client.h"  // nogncheck
#endif  // BUILDFLAG(IS_CHROMEOS)

// The tests in this file use the Network Service implementation of
// NetworkContext, to test sending and receiving of data over TCP sockets.

StartsWith;

namespace content {

namespace {

constexpr char kLocalhostAddress[] =;

class ReadWriteWaiter {};

}  // anonymous namespace

class DirectSocketsTcpBrowserTest : public ContentBrowserTest {};

IN_PROC_BROWSER_TEST_F(DirectSocketsTcpBrowserTest, OpenTcp_Success) {}

IN_PROC_BROWSER_TEST_F(DirectSocketsTcpBrowserTest, OpenTcp_Success_Global) {}

IN_PROC_BROWSER_TEST_F(DirectSocketsTcpBrowserTest, CloseTcp) {}

IN_PROC_BROWSER_TEST_F(DirectSocketsTcpBrowserTest, WriteTcp) {}

IN_PROC_BROWSER_TEST_F(DirectSocketsTcpBrowserTest, WriteLargeTcpPacket) {}

IN_PROC_BROWSER_TEST_F(DirectSocketsTcpBrowserTest, ReadTcp) {}

IN_PROC_BROWSER_TEST_F(DirectSocketsTcpBrowserTest, ReadWriteTcp) {}

class MockTcpNetworkContext : public content::test::MockNetworkContext {};

IN_PROC_BROWSER_TEST_F(DirectSocketsTcpBrowserTest, ReadTcpOnReadError) {}

IN_PROC_BROWSER_TEST_F(DirectSocketsTcpBrowserTest, ReadTcpOnPeerClosed) {}

IN_PROC_BROWSER_TEST_F(DirectSocketsTcpBrowserTest, WriteTcpOnWriteError) {}

IN_PROC_BROWSER_TEST_F(DirectSocketsTcpBrowserTest,
                       ReadWriteTcpOnSocketObserverError) {}

IN_PROC_BROWSER_TEST_F(DirectSocketsTcpBrowserTest,
                       BarrierCallbackFiresWithErrorOnReadWriteError) {}

IN_PROC_BROWSER_TEST_F(DirectSocketsTcpBrowserTest,
                       BarrierCallbackFiresWithOkOnReaderAndWriterClose) {}

IN_PROC_BROWSER_TEST_F(DirectSocketsTcpBrowserTest,
                       BarrierCallbackFiresWithOkOnPeerAndWriterClose) {}

class DirectSocketsTcpServerBrowserTest : public DirectSocketsTcpBrowserTest {};

IN_PROC_BROWSER_TEST_F(DirectSocketsTcpServerBrowserTest, ExchangeTcpServer) {}

#if BUILDFLAG(IS_CHROMEOS)
IN_PROC_BROWSER_TEST_F(DirectSocketsTcpServerBrowserTest, HasFirewallHole) {
  class DelegateImpl : public chromeos::FakePermissionBrokerClient::Delegate {
   public:
    DelegateImpl(uint16_t port, base::OnceClosure quit_closure)
        : port_(port), quit_closure_(std::move(quit_closure)) {}

    void OnTcpPortReleased(uint16_t port,
                           const std::string& interface) override {
      if (port == port_) {
        ASSERT_EQ(interface, "");
        ASSERT_TRUE(quit_closure_);
        std::move(quit_closure_).Run();
      }
    }

   private:
    uint16_t port_;
    base::OnceClosure quit_closure_;
  };

  auto* client = chromeos::FakePermissionBrokerClient::Get();

  const std::string open_script = R"(
    (async () => {
      socket = new TCPServerSocket('127.0.0.1');
      const { localPort } = await socket.opened;
      return localPort;
    })();
  )";

  const int32_t local_port = EvalJs(shell(), open_script).ExtractInt();
  ASSERT_TRUE(client->HasTcpHole(local_port, "" /* all interfaces */));

  base::RunLoop run_loop;
  auto delegate =
      std::make_unique<DelegateImpl>(local_port, run_loop.QuitClosure());
  client->AttachDelegate(delegate.get());

  EXPECT_TRUE(EvalJs(shell(), content::test::WrapAsync("socket.close()"))
                  .error.empty());
  run_loop.Run();
}

IN_PROC_BROWSER_TEST_F(DirectSocketsTcpServerBrowserTest, FirewallHoleDenied) {
  auto* client = chromeos::FakePermissionBrokerClient::Get();
  client->SetTcpDenyAll();

  const std::string open_script = R"(
    (async () => {
      socket = new TCPServerSocket('127.0.0.1');
      return await socket.opened.catch(err => err.message);
    })();
  )";

  EXPECT_THAT(EvalJs(shell(), open_script).ExtractString(),
              testing::HasSubstr("Firewall"));
}

#endif  // BUILDFLAG(IS_CHROMEOS)

IN_PROC_BROWSER_TEST_F(DirectSocketsTcpServerBrowserTest, OkOnClose) {}

class MockNetworkContextWithTCPServerSocketReceiver
    : public network::TestNetworkContext {};

IN_PROC_BROWSER_TEST_F(DirectSocketsTcpServerBrowserTest, ErrorOnRemoteReset) {}

IN_PROC_BROWSER_TEST_F(DirectSocketsTcpServerBrowserTest, Ipv6Only) {}

// A ContentBrowserClient that grants Isolated Web Apps the "direct-sockets"
// permission, but not "cross-origin-isolated", which should result in Direct
// Sockets being disabled.
class NoCoiPermissionIsolatedWebAppContentBrowserClient
    : public test::IsolatedWebAppContentBrowserClient {};

IN_PROC_BROWSER_TEST_F(DirectSocketsTcpBrowserTest, NoCoiPermission) {}

IN_PROC_BROWSER_TEST_F(DirectSocketsTcpBrowserTest, NotInCrossOriginIframe) {}

class IsolatedContextContentBrowserClient
    : public ContentBrowserTestContentBrowserClient {};

class DirectSocketsIsolatedContextTcpBrowserTest
    : public DirectSocketsTcpBrowserTest {};

IN_PROC_BROWSER_TEST_F(DirectSocketsIsolatedContextTcpBrowserTest,
                       NotAvailableInSandboxedIframes) {}

}  // namespace content