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

#include "base/barrier_closure.h"
#include "base/command_line.h"
#include "base/memory/raw_ptr.h"
#include "base/run_loop.h"
#include "base/test/gmock_callback_support.h"
#include "base/test/repeating_test_future.h"
#include "base/test/test_future.h"
#include "content/browser/serial/serial_test_utils.h"
#include "content/public/common/content_client.h"
#include "content/public/common/content_switches.h"
#include "content/public/test/navigation_simulator.h"
#include "content/test/test_render_view_host.h"
#include "content/test/test_web_contents.h"
#include "device/bluetooth/public/cpp/bluetooth_uuid.h"
#include "mojo/public/cpp/bindings/remote.h"
#include "mojo/public/cpp/test_support/fake_message_dispatch_context.h"
#include "mojo/public/cpp/test_support/test_utils.h"
#include "services/device/public/cpp/test/fake_serial_port_client.h"
#include "services/device/public/cpp/test/fake_serial_port_manager.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/blink/public/mojom/serial/serial.mojom.h"
#include "url/origin.h"

namespace content {

namespace {

using ::base::test::InvokeFuture;
using ::base::test::TestFuture;
using ::testing::_;
using ::testing::Return;

const char kTestUrl[] = "https://www.google.com";
const char kCrossOriginTestUrl[] = "https://www.chromium.org";

class MockSerialServiceClient : public blink::mojom::SerialServiceClient {
 public:
  MockSerialServiceClient() = default;
  MockSerialServiceClient(const MockSerialServiceClient&) = delete;
  MockSerialServiceClient& operator=(const MockSerialServiceClient&) = delete;

  ~MockSerialServiceClient() override {
    // Flush the pipe to make sure there aren't any lingering events.
    receiver_.FlushForTesting();
  }

  mojo::PendingRemote<blink::mojom::SerialServiceClient>
  BindNewPipeAndPassRemote() {
    return receiver_.BindNewPipeAndPassRemote();
  }

  // blink::mojom::SerialPortManagerClient
  MOCK_METHOD1(OnPortConnectedStateChanged,
               void(blink::mojom::SerialPortInfoPtr));

 private:
  mojo::Receiver<blink::mojom::SerialServiceClient> receiver_{this};
};

class SerialTest : public RenderViewHostImplTestHarness {
 public:
  SerialTest() {
    ON_CALL(delegate(), GetPortManager).WillByDefault(Return(&port_manager_));
    ON_CALL(delegate(), AddObserver)
        .WillByDefault(testing::SaveArg<1>(&observer_));
    ON_CALL(delegate(), RemoveObserver)
        .WillByDefault([&](RenderFrameHost*, SerialDelegate::Observer*) {
          observer_ = nullptr;
        });
  }

  SerialTest(const SerialTest&) = delete;
  SerialTest& operator=(const SerialTest&) = delete;

  ~SerialTest() override = default;

  void SetUp() override {
    base::CommandLine::ForCurrentProcess()->AppendSwitch(
        switches::kEnableExperimentalWebPlatformFeatures);
    original_client_ = SetBrowserClientForTesting(&test_client_);
    RenderViewHostTestHarness::SetUp();
  }

  void TearDown() override {
    RenderViewHostTestHarness::TearDown();
    if (original_client_)
      SetBrowserClientForTesting(original_client_);
  }

  MockSerialDelegate& delegate() { return test_client_.delegate(); }
  device::FakeSerialPortManager* port_manager() { return &port_manager_; }
  SerialDelegate::Observer* observer() { return observer_; }

 private:
  SerialTestContentBrowserClient test_client_;
  raw_ptr<ContentBrowserClient> original_client_ = nullptr;
  device::FakeSerialPortManager port_manager_;
  raw_ptr<SerialDelegate::Observer> observer_ = nullptr;
};

}  // namespace

TEST_F(SerialTest, GetPortsForAllDeviceTypes) {
  NavigateAndCommit(GURL(kTestUrl));

  mojo::Remote<blink::mojom::SerialService> service;
  contents()->GetPrimaryMainFrame()->BindSerialService(
      service.BindNewPipeAndPassReceiver());

  MockSerialServiceClient client;
  service->SetClient(client.BindNewPipeAndPassRemote());
  service.FlushForTesting();

  // Platform Serial port
  auto platform_token = base::UnguessableToken::Create();
  auto platform_port_info = device::mojom::SerialPortInfo::New();
  platform_port_info->token = platform_token;
  port_manager()->AddPort(std::move(platform_port_info));

  // USB Serial port
  auto usb_token = base::UnguessableToken::Create();
  auto usb_port_info = device::mojom::SerialPortInfo::New();
  usb_port_info->token = usb_token;
  usb_port_info->has_vendor_id = true;
  usb_port_info->vendor_id = 0x1111;
  usb_port_info->has_product_id = true;
  usb_port_info->product_id = 0x2222;
  port_manager()->AddPort(std::move(usb_port_info));

  // Bluetooth Serial port
  const device::BluetoothUUID kServiceClassId(
      "ac822b69-d7e9-4bab-8fa6-ce40c87e1ac4");
  auto bluetooth_token = base::UnguessableToken::Create();
  auto bluetooth_port_info = device::mojom::SerialPortInfo::New();
  bluetooth_port_info->token = bluetooth_token;
  bluetooth_port_info->bluetooth_service_class_id = kServiceClassId;
  port_manager()->AddPort(std::move(bluetooth_port_info));

  EXPECT_CALL(delegate(), HasPortPermission(_, _))
      .Times(3)
      .WillRepeatedly(Return(true));
  TestFuture<std::vector<blink::mojom::SerialPortInfoPtr>> future;
  service->GetPorts(future.GetCallback());

  auto ports = future.Take();
  // Assert as we need to access all three ports.
  ASSERT_EQ(ports.size(), 3u);
  // Ports are not in any particular order so we will loop through and check
  // according to the token.
  bool has_platform = false;
  bool has_usb = false;
  bool has_bluetooth = false;
  for (const auto& port : ports) {
    if (port->token == platform_token) {
      has_platform = true;
      EXPECT_EQ(port->has_usb_vendor_id, false);
      EXPECT_EQ(port->has_usb_product_id, false);
      EXPECT_FALSE(port->bluetooth_service_class_id.has_value());
    } else if (port->token == usb_token) {
      has_usb = true;
      EXPECT_EQ(port->has_usb_vendor_id, true);
      EXPECT_EQ(port->usb_vendor_id, 0x1111);
      EXPECT_EQ(port->has_usb_product_id, true);
      EXPECT_EQ(port->usb_product_id, 0x2222);
      EXPECT_FALSE(port->bluetooth_service_class_id.has_value());
    } else if (port->token == bluetooth_token) {
      has_bluetooth = true;
      EXPECT_EQ(port->has_usb_vendor_id, false);
      EXPECT_EQ(port->has_usb_product_id, false);
      EXPECT_EQ(port->bluetooth_service_class_id, kServiceClassId);
    } else {
      ADD_FAILURE() << "Unexpected port token: " << port->token;
    }
  }
  EXPECT_TRUE(has_platform);
  EXPECT_TRUE(has_usb);
  EXPECT_TRUE(has_bluetooth);
}

TEST_F(SerialTest, OpenAndClosePort) {
  NavigateAndCommit(GURL(kTestUrl));

  mojo::Remote<blink::mojom::SerialService> service;
  contents()->GetPrimaryMainFrame()->BindSerialService(
      service.BindNewPipeAndPassReceiver());

  auto token = base::UnguessableToken::Create();
  auto port_info = device::mojom::SerialPortInfo::New();
  port_info->token = token;
  port_manager()->AddPort(port_info->Clone());

  EXPECT_FALSE(
      contents()->IsCapabilityActive(WebContentsCapabilityType::kSerial));

  EXPECT_CALL(delegate(), GetPortInfo(_, _)).WillOnce(Return(port_info.get()));
  EXPECT_CALL(delegate(), HasPortPermission(_, _)).WillOnce(Return(true));

  TestFuture<mojo::PendingRemote<device::mojom::SerialPort>> future;
  service->OpenPort(token, device::mojom::SerialConnectionOptions::New(),
                    device::FakeSerialPortClient::Create(),
                    future.GetCallback());
  auto port = future.Take();
  EXPECT_TRUE(port.is_valid());
  EXPECT_TRUE(
      contents()->IsCapabilityActive(WebContentsCapabilityType::kSerial));

  port.reset();
  base::RunLoop().RunUntilIdle();
  EXPECT_FALSE(
      contents()->IsCapabilityActive(WebContentsCapabilityType::kSerial));
}

TEST_F(SerialTest, OpenWithoutPermission) {
  NavigateAndCommit(GURL(kTestUrl));

  mojo::Remote<blink::mojom::SerialService> service;
  contents()->GetPrimaryMainFrame()->BindSerialService(
      service.BindNewPipeAndPassReceiver());

  auto token = base::UnguessableToken::Create();
  auto port_info = device::mojom::SerialPortInfo::New();
  port_info->token = token;
  port_manager()->AddPort(port_info->Clone());

  EXPECT_FALSE(
      contents()->IsCapabilityActive(WebContentsCapabilityType::kSerial));

  EXPECT_CALL(delegate(), GetPortInfo(_, _)).WillOnce(Return(port_info.get()));
  EXPECT_CALL(delegate(), HasPortPermission(_, _)).WillOnce(Return(false));

  TestFuture<mojo::PendingRemote<device::mojom::SerialPort>> future;
  service->OpenPort(token, device::mojom::SerialConnectionOptions::New(),
                    device::FakeSerialPortClient::Create(),
                    future.GetCallback());
  auto port = future.Take();
  EXPECT_FALSE(port.is_valid());

  // Allow extra time for the watcher connection failure to propagate.
  base::RunLoop().RunUntilIdle();
  EXPECT_FALSE(
      contents()->IsCapabilityActive(WebContentsCapabilityType::kSerial));
}

TEST_F(SerialTest, OpenFailure) {
  NavigateAndCommit(GURL(kTestUrl));

  mojo::Remote<blink::mojom::SerialService> service;
  contents()->GetPrimaryMainFrame()->BindSerialService(
      service.BindNewPipeAndPassReceiver());

  auto token = base::UnguessableToken::Create();
  auto port_info = device::mojom::SerialPortInfo::New();
  port_info->token = token;
  port_manager()->AddPort(port_info->Clone());
  port_manager()->set_simulate_open_failure(true);

  EXPECT_FALSE(
      contents()->IsCapabilityActive(WebContentsCapabilityType::kSerial));

  EXPECT_CALL(delegate(), GetPortInfo(_, _)).WillOnce(Return(port_info.get()));
  EXPECT_CALL(delegate(), HasPortPermission(_, _)).WillOnce(Return(true));

  TestFuture<mojo::PendingRemote<device::mojom::SerialPort>> future;
  service->OpenPort(token, device::mojom::SerialConnectionOptions::New(),
                    device::FakeSerialPortClient::Create(),
                    future.GetCallback());
  auto port = future.Take();
  EXPECT_FALSE(port.is_valid());

  // Allow extra time for the watcher connection failure to propagate.
  base::RunLoop().RunUntilIdle();
  EXPECT_FALSE(
      contents()->IsCapabilityActive(WebContentsCapabilityType::kSerial));
}

TEST_F(SerialTest, OpenAndNavigateCrossOrigin) {
  NavigateAndCommit(GURL(kTestUrl));

  mojo::Remote<blink::mojom::SerialService> service;
  contents()->GetPrimaryMainFrame()->BindSerialService(
      service.BindNewPipeAndPassReceiver());

  auto token = base::UnguessableToken::Create();
  auto port_info = device::mojom::SerialPortInfo::New();
  port_info->token = token;
  port_manager()->AddPort(port_info->Clone());

  EXPECT_FALSE(
      contents()->IsCapabilityActive(WebContentsCapabilityType::kSerial));

  EXPECT_CALL(delegate(), GetPortInfo(_, _)).WillOnce(Return(port_info.get()));
  EXPECT_CALL(delegate(), HasPortPermission(_, _)).WillOnce(Return(true));

  TestFuture<mojo::PendingRemote<device::mojom::SerialPort>> future;
  service->OpenPort(token, device::mojom::SerialConnectionOptions::New(),
                    device::FakeSerialPortClient::Create(),
                    future.GetCallback());
  mojo::Remote<device::mojom::SerialPort> port(future.Take());
  EXPECT_TRUE(port.is_connected());
  EXPECT_TRUE(
      contents()->IsCapabilityActive(WebContentsCapabilityType::kSerial));

  NavigateAndCommit(GURL(kCrossOriginTestUrl));
  base::RunLoop().RunUntilIdle();
  EXPECT_FALSE(
      contents()->IsCapabilityActive(WebContentsCapabilityType::kSerial));
  port.FlushForTesting();
  EXPECT_FALSE(port.is_connected());
}

TEST_F(SerialTest, SameBluetoothSerialPortSameToken) {
  NavigateAndCommit(GURL(kTestUrl));
  mojo::Remote<blink::mojom::SerialService> service;
  contents()->GetPrimaryMainFrame()->BindSerialService(
      service.BindNewPipeAndPassReceiver());
  MockSerialServiceClient client;
  service->SetClient(client.BindNewPipeAndPassRemote());
  service.FlushForTesting();
  ASSERT_TRUE(observer());

  const device::BluetoothUUID kServiceClassId(
      "ac822b69-d7e9-4bab-8fa6-ce40c87e1ac4");
  base::UnguessableToken bluetooth_token;
  std::vector<device::mojom::SerialPortInfoPtr> ports;
  for (size_t i = 0; i < 2; i++) {
    auto port = device::mojom::SerialPortInfo::New();
    port->token = base::UnguessableToken::Create();
    port->bluetooth_service_class_id = kServiceClassId;
    ports.push_back(std::move(port));
    if (i == 0) {
      // Both SerialPortInfos describe the same port (same device address and
      // service UUID). When the ports are delivered to the renderer, the
      // second port reuses the token from the first port even though they were
      // created with different tokens.
      bluetooth_token = ports[i]->token;
    }
  }

  for (size_t i = 0; i < 2; i++) {
    TestFuture<blink::mojom::SerialPortInfoPtr> future;
    EXPECT_CALL(delegate(), HasPortPermission(_, _)).WillOnce(Return(true));
    EXPECT_CALL(client, OnPortConnectedStateChanged)
        .WillOnce(InvokeFuture(future));
    observer()->OnPortAdded(*ports[i]);
    EXPECT_EQ(future.Get()->token, bluetooth_token);
  }
}

TEST_F(SerialTest, AddAndRemovePorts) {
  NavigateAndCommit(GURL(kTestUrl));

  mojo::Remote<blink::mojom::SerialService> service;
  contents()->GetPrimaryMainFrame()->BindSerialService(
      service.BindNewPipeAndPassReceiver());

  MockSerialServiceClient client;
  service->SetClient(client.BindNewPipeAndPassRemote());
  service.FlushForTesting();

  ASSERT_TRUE(observer());

  // Three ports will be added and then removed. Only the 1st and 3rd will have
  // permission granted.
  std::vector<device::mojom::SerialPortInfoPtr> ports;
  for (size_t i = 0; i < 3; i++) {
    auto port = device::mojom::SerialPortInfo::New();
    port->token = base::UnguessableToken::Create();
    ports.push_back(std::move(port));
  }

  EXPECT_CALL(delegate(), HasPortPermission(_, _))
      .WillOnce(Return(true))
      .WillOnce(Return(false))
      .WillOnce(Return(true))
      .WillOnce(Return(true))
      .WillOnce(Return(false))
      .WillOnce(Return(true));

  {
    base::RunLoop run_loop;
    auto closure = base::BarrierClosure(2, run_loop.QuitClosure());
    EXPECT_CALL(client, OnPortConnectedStateChanged)
        .Times(2)
        .WillRepeatedly(base::test::RunClosure(closure));

    for (const auto& port : ports)
      observer()->OnPortAdded(*port);
    run_loop.Run();
  }

  {
    base::RunLoop run_loop;
    auto closure = base::BarrierClosure(2, run_loop.QuitClosure());
    EXPECT_CALL(client, OnPortConnectedStateChanged)
        .Times(2)
        .WillRepeatedly(base::test::RunClosure(closure));

    for (const auto& port : ports)
      observer()->OnPortRemoved(*port);
    run_loop.Run();
  }
}

TEST_F(SerialTest, PortConnectedState) {
  NavigateAndCommit(GURL(kTestUrl));

  mojo::Remote<blink::mojom::SerialService> service;
  contents()->GetPrimaryMainFrame()->BindSerialService(
      service.BindNewPipeAndPassReceiver());

  MockSerialServiceClient client;
  service->SetClient(client.BindNewPipeAndPassRemote());
  service.FlushForTesting();

  ASSERT_TRUE(observer());

  // Create a disconnected port.
  auto port = device::mojom::SerialPortInfo::New();
  port->token = base::UnguessableToken::Create();
  port->connected = false;

  EXPECT_CALL(delegate(), HasPortPermission).WillRepeatedly(Return(true));

  // Add the disconnected port. The client is not notified.
  EXPECT_CALL(client, OnPortConnectedStateChanged).Times(0);
  observer()->OnPortAdded(*port);
  base::RunLoop().RunUntilIdle();

  // Connect the port.
  TestFuture<blink::mojom::SerialPortInfoPtr> connect_future;
  EXPECT_CALL(client, OnPortConnectedStateChanged)
      .WillOnce(InvokeFuture(connect_future));
  port->connected = true;
  observer()->OnPortConnectedStateChanged(*port);
  EXPECT_EQ(connect_future.Get()->token, port->token);
  EXPECT_TRUE(connect_future.Get()->connected);

  // Disconnect the port.
  TestFuture<blink::mojom::SerialPortInfoPtr> disconnect_future;
  EXPECT_CALL(client, OnPortConnectedStateChanged)
      .WillOnce(InvokeFuture(disconnect_future));
  port->connected = false;
  observer()->OnPortConnectedStateChanged(*port);
  EXPECT_EQ(disconnect_future.Get()->token, port->token);
  EXPECT_FALSE(disconnect_future.Get()->connected);
}

TEST_F(SerialTest, OpenAndClosePortManagerConnection) {
  NavigateAndCommit(GURL(kTestUrl));

  mojo::Remote<blink::mojom::SerialService> service;
  contents()->GetPrimaryMainFrame()->BindSerialService(
      service.BindNewPipeAndPassReceiver());

  auto token = base::UnguessableToken::Create();
  auto port_info = device::mojom::SerialPortInfo::New();
  port_info->token = token;
  port_manager()->AddPort(port_info->Clone());

  EXPECT_FALSE(
      contents()->IsCapabilityActive(WebContentsCapabilityType::kSerial));

  EXPECT_CALL(delegate(), GetPortInfo(_, _)).WillOnce(Return(port_info.get()));
  EXPECT_CALL(delegate(), HasPortPermission(_, _)).WillOnce(Return(true));

  TestFuture<mojo::PendingRemote<device::mojom::SerialPort>> future;
  service->OpenPort(token, device::mojom::SerialConnectionOptions::New(),
                    device::FakeSerialPortClient::Create(),
                    future.GetCallback());
  mojo::Remote<device::mojom::SerialPort> port(future.Take());
  EXPECT_TRUE(port.is_connected());
  EXPECT_TRUE(
      contents()->IsCapabilityActive(WebContentsCapabilityType::kSerial));

  ASSERT_TRUE(observer());
  observer()->OnPortManagerConnectionError();
  EXPECT_FALSE(
      contents()->IsCapabilityActive(WebContentsCapabilityType::kSerial));
  port.FlushForTesting();
  EXPECT_FALSE(port.is_connected());
  service.FlushForTesting();
  EXPECT_FALSE(service.is_connected());
}

TEST_F(SerialTest, OpenAndRevokePermission) {
  NavigateAndCommit(GURL(kTestUrl));

  mojo::Remote<blink::mojom::SerialService> service;
  contents()->GetPrimaryMainFrame()->BindSerialService(
      service.BindNewPipeAndPassReceiver());

  auto token = base::UnguessableToken::Create();
  auto port_info = device::mojom::SerialPortInfo::New();
  port_info->token = token;
  port_manager()->AddPort(port_info->Clone());

  EXPECT_FALSE(
      contents()->IsCapabilityActive(WebContentsCapabilityType::kSerial));

  EXPECT_CALL(delegate(), GetPortInfo(_, _)).WillOnce(Return(port_info.get()));
  EXPECT_CALL(delegate(), HasPortPermission(_, _)).WillOnce(Return(true));

  TestFuture<mojo::PendingRemote<device::mojom::SerialPort>> future;
  service->OpenPort(token, device::mojom::SerialConnectionOptions::New(),
                    device::FakeSerialPortClient::Create(),
                    future.GetCallback());
  mojo::Remote<device::mojom::SerialPort> port(future.Take());
  EXPECT_TRUE(port.is_connected());
  EXPECT_TRUE(
      contents()->IsCapabilityActive(WebContentsCapabilityType::kSerial));

  EXPECT_CALL(delegate(), GetPortInfo(_, _)).WillOnce(Return(port_info.get()));
  EXPECT_CALL(delegate(), HasPortPermission(_, _)).WillOnce(Return(false));

  ASSERT_TRUE(observer());
  url::Origin origin = url::Origin::Create(GURL(kTestUrl));
  observer()->OnPermissionRevoked(origin);
  EXPECT_FALSE(
      contents()->IsCapabilityActive(WebContentsCapabilityType::kSerial));
  port.FlushForTesting();
  EXPECT_FALSE(port.is_connected());
  service.FlushForTesting();
  EXPECT_TRUE(service.is_connected());
}

TEST_F(SerialTest, OpenAndRevokePermissionOnDifferentOrigin) {
  NavigateAndCommit(GURL(kTestUrl));

  mojo::Remote<blink::mojom::SerialService> service;
  contents()->GetPrimaryMainFrame()->BindSerialService(
      service.BindNewPipeAndPassReceiver());

  auto token = base::UnguessableToken::Create();
  auto port_info = device::mojom::SerialPortInfo::New();
  port_info->token = token;
  port_manager()->AddPort(port_info->Clone());

  EXPECT_FALSE(
      contents()->IsCapabilityActive(WebContentsCapabilityType::kSerial));

  EXPECT_CALL(delegate(), GetPortInfo(_, _)).WillOnce(Return(port_info.get()));
  EXPECT_CALL(delegate(), HasPortPermission(_, _)).WillOnce(Return(true));

  TestFuture<mojo::PendingRemote<device::mojom::SerialPort>> future;
  service->OpenPort(token, device::mojom::SerialConnectionOptions::New(),
                    device::FakeSerialPortClient::Create(),
                    future.GetCallback());
  mojo::Remote<device::mojom::SerialPort> port(future.Take());
  EXPECT_TRUE(port.is_connected());
  EXPECT_TRUE(
      contents()->IsCapabilityActive(WebContentsCapabilityType::kSerial));

  ASSERT_TRUE(observer());
  url::Origin different_origin =
      url::Origin::Create(GURL("http://different-origin.com"));
  observer()->OnPermissionRevoked(different_origin);
  EXPECT_TRUE(
      contents()->IsCapabilityActive(WebContentsCapabilityType::kSerial));
  port.FlushForTesting();
  EXPECT_TRUE(port.is_connected());
  service.FlushForTesting();
  EXPECT_TRUE(service.is_connected());
}

TEST_F(SerialTest, OpenTwoPortsAndRevokePermission) {
  NavigateAndCommit(GURL(kTestUrl));

  mojo::Remote<blink::mojom::SerialService> service;
  contents()->GetPrimaryMainFrame()->BindSerialService(
      service.BindNewPipeAndPassReceiver());

  auto token1 = base::UnguessableToken::Create();
  auto port_info1 = device::mojom::SerialPortInfo::New();
  port_info1->token = token1;
  port_manager()->AddPort(port_info1->Clone());

  auto token2 = base::UnguessableToken::Create();
  auto port_info2 = device::mojom::SerialPortInfo::New();
  port_info2->token = token2;
  port_manager()->AddPort(port_info2->Clone());

  EXPECT_FALSE(
      contents()->IsCapabilityActive(WebContentsCapabilityType::kSerial));

  EXPECT_CALL(delegate(), GetPortInfo(_, _)).WillOnce(Return(port_info1.get()));
  EXPECT_CALL(delegate(), HasPortPermission(_, _)).WillOnce(Return(true));

  TestFuture<mojo::PendingRemote<device::mojom::SerialPort>> future1;
  service->OpenPort(token1, device::mojom::SerialConnectionOptions::New(),
                    device::FakeSerialPortClient::Create(),
                    future1.GetCallback());
  mojo::Remote<device::mojom::SerialPort> port1(future1.Take());
  EXPECT_TRUE(port1.is_connected());
  EXPECT_TRUE(
      contents()->IsCapabilityActive(WebContentsCapabilityType::kSerial));

  EXPECT_CALL(delegate(), GetPortInfo(_, _)).WillOnce(Return(port_info2.get()));
  EXPECT_CALL(delegate(), HasPortPermission(_, _)).WillOnce(Return(true));

  TestFuture<mojo::PendingRemote<device::mojom::SerialPort>> future2;
  service->OpenPort(token2, device::mojom::SerialConnectionOptions::New(),
                    device::FakeSerialPortClient::Create(),
                    future2.GetCallback());
  mojo::Remote<device::mojom::SerialPort> port2(future2.Take());
  EXPECT_TRUE(port2.is_connected());
  EXPECT_TRUE(
      contents()->IsCapabilityActive(WebContentsCapabilityType::kSerial));

  EXPECT_CALL(delegate(), GetPortInfo(_, token1))
      .WillOnce(Return(port_info1.get()));
  EXPECT_CALL(delegate(), GetPortInfo(_, token2))
      .WillOnce(Return(port_info2.get()));
  EXPECT_CALL(delegate(), HasPortPermission(_, _))
      .Times(2)
      .WillRepeatedly([&](auto rfh, auto port_info) {
        if (port_info.token == port_info1->token) {
          return false;
        } else {
          return true;
        }
      });

  ASSERT_TRUE(observer());
  url::Origin origin = url::Origin::Create(GURL(kTestUrl));
  observer()->OnPermissionRevoked(origin);
  EXPECT_TRUE(
      contents()->IsCapabilityActive(WebContentsCapabilityType::kSerial));
  port1.FlushForTesting();
  EXPECT_FALSE(port1.is_connected());
  port2.FlushForTesting();
  EXPECT_TRUE(port2.is_connected());
  service.FlushForTesting();
  EXPECT_TRUE(service.is_connected());
}

TEST_F(SerialTest, RejectOpaqueOrigin) {
  // Create a fake dispatch context to trigger a bad message in.
  mojo::FakeMessageDispatchContext fake_dispatch_context;
  mojo::test::BadMessageObserver bad_message_observer;

  auto response_headers =
      base::MakeRefCounted<net::HttpResponseHeaders>(std::string());
  response_headers->SetHeader("Content-Security-Policy",
                              "sandbox allow-scripts");
  auto navigation_simulator = NavigationSimulator::CreateRendererInitiated(
      GURL("https://opaque.com"), main_test_rfh());
  navigation_simulator->SetResponseHeaders(response_headers);
  navigation_simulator->Start();
  navigation_simulator->Commit();

  mojo::Remote<blink::mojom::SerialService> service;
  main_test_rfh()->BindSerialService(service.BindNewPipeAndPassReceiver());
  EXPECT_EQ(bad_message_observer.WaitForBadMessage(),
            "Web Serial is not allowed when the top-level document has an "
            "opaque origin.");
}

TEST_F(SerialTest, RejectOpaqueOriginEmbeddedFrame) {
  // Create a fake dispatch context to trigger a bad message in.
  mojo::FakeMessageDispatchContext fake_dispatch_context;
  mojo::test::BadMessageObserver bad_message_observer;

  auto response_headers =
      base::MakeRefCounted<net::HttpResponseHeaders>(std::string());
  response_headers->SetHeader("Content-Security-Policy",
                              "sandbox allow-scripts");
  auto navigation_simulator = NavigationSimulator::CreateRendererInitiated(
      GURL("https://opaque.com"), main_test_rfh());
  navigation_simulator->SetResponseHeaders(response_headers);
  navigation_simulator->Start();
  navigation_simulator->Commit();

  const GURL kEmbeddedUrl("https://opaque.com");
  RenderFrameHost* embedded_rfh =
      RenderFrameHostTester::For(main_test_rfh())
          ->AppendChildWithPolicy(
              "embedded_frame",
              {{network::mojom::PermissionsPolicyFeature::kSerial,
                /*allowed_origins=*/{},
                /*self_if_matches=*/url::Origin::Create(kEmbeddedUrl),
                /*matches_all_origins=*/false, /*matches_opaque_src=*/true}});
  embedded_rfh = NavigationSimulator::NavigateAndCommitFromDocument(
      kEmbeddedUrl, embedded_rfh);

  mojo::Remote<blink::mojom::SerialService> service;
  static_cast<TestRenderFrameHost*>(embedded_rfh)
      ->BindSerialService(service.BindNewPipeAndPassReceiver());
  EXPECT_EQ(bad_message_observer.WaitForBadMessage(),
            "Web Serial is not allowed when the top-level document has an "
            "opaque origin.");
}

}  // namespace content
