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

#include <vector>

#include "base/containers/flat_map.h"
#include "base/functional/callback_helpers.h"
#include "base/no_destructor.h"
#include "base/run_loop.h"
#include "base/strings/utf_string_conversions.h"
#include "base/test/bind.h"
#include "base/test/test_future.h"
#include "base/test/values_test_util.h"
#include "base/values.h"
#include "build/chromeos_buildflags.h"
#include "chrome/browser/content_settings/host_content_settings_map_factory.h"
#include "chrome/browser/usb/usb_chooser_context.h"
#include "chrome/browser/usb/usb_chooser_context_factory.h"
#include "chrome/browser/usb/usb_chooser_context_mock_device_observer.h"
#include "chrome/common/chrome_constants.h"
#include "chrome/test/base/testing_profile.h"
#include "components/content_settings/core/browser/host_content_settings_map.h"
#include "components/content_settings/core/common/pref_names.h"
#include "components/permissions/test/object_permission_context_base_mock_permission_observer.h"
#include "components/prefs/pref_service.h"
#include "components/sync_preferences/testing_pref_service_syncable.h"
#include "content/public/test/browser_task_environment.h"
#include "services/device/public/cpp/test/fake_usb_device_manager.h"
#include "services/device/public/mojom/usb_device.mojom.h"
#include "services/device/public/mojom/usb_manager.mojom.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"

#if BUILDFLAG(IS_CHROMEOS_ASH)
#include "chrome/browser/ash/settings/scoped_cros_settings_test_helper.h"
#include "chrome/browser/ash/settings/stub_cros_settings_provider.h"
#include "chromeos/ash/components/settings/cros_settings_names.h"
#endif

#if BUILDFLAG(IS_CHROMEOS_LACROS)
#include "chromeos/crosapi/mojom/crosapi.mojom.h"
#include "chromeos/crosapi/mojom/device_settings_service.mojom.h"
#include "chromeos/startup/browser_init_params.h"
#endif

using ::base::test::TestFuture;
using ::device::mojom::UsbDeviceInfoPtr;
using ::testing::_;
using ::testing::AnyNumber;
using ::testing::NiceMock;

namespace {

constexpr char kDeviceNameKey[] = "name";
constexpr char kGuidKey[] = "ephemeral-guid";
constexpr char kProductIdKey[] = "product-id";
constexpr char kSerialNumberKey[] = "serial-number";
constexpr char kVendorIdKey[] = "vendor-id";
constexpr int kDeviceIdWildcard = -1;

class UsbChooserContextTest : public testing::Test {
 public:
  UsbChooserContextTest() {
#if BUILDFLAG(IS_CHROMEOS_ASH)
    profile_.ScopedCrosSettingsTestHelper()
        ->ReplaceDeviceSettingsProviderWithStub();
#endif  // BUILDFLAG(IS_CHROMEOS_ASH)
  }

  ~UsbChooserContextTest() override {
    // When UsbChooserContext is destroyed, OnDeviceManagerConnectionError will
    // be called for each device observer.
    for (const auto& entry : mock_device_observers_) {
      EXPECT_CALL(*entry.second, OnDeviceManagerConnectionError)
          .Times(AnyNumber());
    }

    // OnPermissionRevoked and OnObjectPermissionChanged will be called for any
    // ephemeral device permissions that are active.
    for (const auto& entry : mock_permission_observers_) {
      EXPECT_CALL(*entry.second, OnPermissionRevoked).Times(AnyNumber());
      EXPECT_CALL(*entry.second, OnObjectPermissionChanged).Times(AnyNumber());
    }

#if BUILDFLAG(IS_CHROMEOS_ASH)
    profile_.ScopedCrosSettingsTestHelper()
        ->RestoreRealDeviceSettingsProvider();
#endif  // BUILDFLAG(IS_CHROMEOS_ASH)
  }

 protected:
  TestingProfile* profile() { return &profile_; }

  UsbChooserContext* GetChooserContext(Profile* profile) {
    auto* chooser_context = UsbChooserContextFactory::GetForProfile(profile);
    mojo::PendingRemote<device::mojom::UsbDeviceManager> device_manager;
    device_manager_.AddReceiver(
        device_manager.InitWithNewPipeAndPassReceiver());
    chooser_context->SetDeviceManagerForTesting(std::move(device_manager));

    // Call GetDevices once to make sure the connection with DeviceManager has
    // been set up, so that it can be notified when device is removed.
    TestFuture<std::vector<device::mojom::UsbDeviceInfoPtr>> devices_future;
    chooser_context->GetDevices(devices_future.GetCallback());
    EXPECT_TRUE(devices_future.Wait());

    // Add observers
    EXPECT_FALSE(base::Contains(mock_permission_observers_, profile));
    EXPECT_FALSE(base::Contains(mock_device_observers_, profile));
    mock_permission_observers_.emplace(
        profile,
        std::make_unique<NiceMock<permissions::MockPermissionObserver>>());
    mock_device_observers_.emplace(profile,
                                   std::make_unique<MockDeviceObserver>());
    NiceMock<permissions::MockPermissionObserver>* permission_observer =
        mock_permission_observers_[profile].get();
    chooser_context->permissions::ObjectPermissionContextBase::AddObserver(
        permission_observer);
    MockDeviceObserver* device_observer = mock_device_observers_[profile].get();
    chooser_context->AddObserver(device_observer);
    EXPECT_CALL(*device_observer, OnBrowserContextShutdown)
        .WillOnce([chooser_context, permission_observer, device_observer]() {
          chooser_context
              ->permissions::ObjectPermissionContextBase::RemoveObserver(
                  permission_observer);
          chooser_context->RemoveObserver(device_observer);
        });
    return chooser_context;
  }

  device::FakeUsbDeviceManager device_manager_;

  // Mock observers
  base::flat_map<Profile*,
                 std::unique_ptr<NiceMock<permissions::MockPermissionObserver>>>
      mock_permission_observers_;
  base::flat_map<Profile*, std::unique_ptr<MockDeviceObserver>>
      mock_device_observers_;

 private:
  content::BrowserTaskEnvironment task_environment_;
  TestingProfile profile_;
};

}  // namespace

TEST_F(UsbChooserContextTest, CheckGrantAndRevokePermission) {
  GURL url("https://www.google.com");
  const auto origin = url::Origin::Create(url);
  UsbDeviceInfoPtr device_info =
      device_manager_.CreateAndAddDevice(0, 0, "Google", "Gizmo", "123ABC");
  UsbChooserContext* store = GetChooserContext(profile());

  auto object = base::Value(base::Value::Dict()
                                .Set(kDeviceNameKey, "Gizmo")
                                .Set(kVendorIdKey, 0)
                                .Set(kProductIdKey, 0)
                                .Set(kSerialNumberKey, "123ABC"));

  EXPECT_FALSE(store->HasDevicePermission(origin, *device_info));
  EXPECT_CALL(*mock_permission_observers_[profile()],
              OnObjectPermissionChanged(
                  std::make_optional(ContentSettingsType::USB_GUARD),
                  ContentSettingsType::USB_CHOOSER_DATA));

  store->GrantDevicePermission(origin, *device_info);
  EXPECT_TRUE(store->HasDevicePermission(origin, *device_info));
  std::vector<std::unique_ptr<UsbChooserContext::Object>> objects =
      store->GetGrantedObjects(origin);
  ASSERT_EQ(1u, objects.size());
  EXPECT_EQ(object, objects[0]->value);

  std::vector<std::unique_ptr<UsbChooserContext::Object>> all_origin_objects =
      store->GetAllGrantedObjects();
  ASSERT_EQ(1u, all_origin_objects.size());
  EXPECT_EQ(url, all_origin_objects[0]->origin);
  EXPECT_EQ(object, all_origin_objects[0]->value);
  EXPECT_FALSE(all_origin_objects[0]->incognito);

  EXPECT_CALL(*mock_permission_observers_[profile()],
              OnObjectPermissionChanged(
                  std::make_optional(ContentSettingsType::USB_GUARD),
                  ContentSettingsType::USB_CHOOSER_DATA));
  EXPECT_CALL(*mock_permission_observers_[profile()],
              OnPermissionRevoked(origin));

  store->RevokeObjectPermission(origin, objects[0]->value);
  EXPECT_FALSE(store->HasDevicePermission(origin, *device_info));

  objects = store->GetGrantedObjects(origin);
  EXPECT_EQ(0u, objects.size());

  all_origin_objects = store->GetAllGrantedObjects();
  EXPECT_EQ(0u, all_origin_objects.size());
}

TEST_F(UsbChooserContextTest, CheckGrantAndRevokeEphemeralPermission) {
  GURL url("https://www.google.com");
  const auto origin = url::Origin::Create(url);
  UsbDeviceInfoPtr device_info =
      device_manager_.CreateAndAddDevice(0, 0, "Google", "Gizmo", "");
  UsbDeviceInfoPtr other_device_info =
      device_manager_.CreateAndAddDevice(0, 0, "Google", "Gizmo", "");

  UsbChooserContext* store = GetChooserContext(profile());

  auto object = base::Value(
      base::Value::Dict()
          .Set(kDeviceNameKey, "Gizmo")
          .Set(kGuidKey, device_info->guid)
          .Set(kVendorIdKey, static_cast<int>(device_info->vendor_id))
          .Set(kProductIdKey, static_cast<int>(device_info->product_id)));

  EXPECT_FALSE(store->HasDevicePermission(origin, *device_info));
  EXPECT_CALL(*mock_permission_observers_[profile()],
              OnObjectPermissionChanged(
                  std::make_optional(ContentSettingsType::USB_GUARD),
                  ContentSettingsType::USB_CHOOSER_DATA));

  store->GrantDevicePermission(origin, *device_info);
  EXPECT_TRUE(store->HasDevicePermission(origin, *device_info));
  EXPECT_FALSE(store->HasDevicePermission(origin, *other_device_info));

  std::vector<std::unique_ptr<UsbChooserContext::Object>> objects =
      store->GetGrantedObjects(origin);
  EXPECT_EQ(1u, objects.size());
  EXPECT_EQ(object, objects[0]->value);

  std::vector<std::unique_ptr<UsbChooserContext::Object>> all_origin_objects =
      store->GetAllGrantedObjects();
  EXPECT_EQ(1u, all_origin_objects.size());
  EXPECT_EQ(url, all_origin_objects[0]->origin);
  EXPECT_EQ(object, all_origin_objects[0]->value);
  EXPECT_FALSE(all_origin_objects[0]->incognito);

  EXPECT_CALL(*mock_permission_observers_[profile()],
              OnObjectPermissionChanged(
                  std::make_optional(ContentSettingsType::USB_GUARD),
                  ContentSettingsType::USB_CHOOSER_DATA));
  EXPECT_CALL(*mock_permission_observers_[profile()],
              OnPermissionRevoked(origin));

  store->RevokeObjectPermission(origin, objects[0]->value);
  EXPECT_FALSE(store->HasDevicePermission(origin, *device_info));

  objects = store->GetGrantedObjects(origin);
  EXPECT_EQ(0u, objects.size());
  all_origin_objects = store->GetAllGrantedObjects();
  EXPECT_EQ(0u, all_origin_objects.size());
}

TEST_F(UsbChooserContextTest, DisconnectDeviceWithPermission) {
  GURL url("https://www.google.com");
  const auto origin = url::Origin::Create(url);
  UsbDeviceInfoPtr device_info =
      device_manager_.CreateAndAddDevice(0, 0, "Google", "Gizmo", "123ABC");

  UsbChooserContext* store = GetChooserContext(profile());

  EXPECT_FALSE(store->HasDevicePermission(origin, *device_info));
  EXPECT_CALL(*mock_permission_observers_[profile()],
              OnObjectPermissionChanged(
                  std::make_optional(ContentSettingsType::USB_GUARD),
                  ContentSettingsType::USB_CHOOSER_DATA));

  store->GrantDevicePermission(origin, *device_info);
  EXPECT_TRUE(store->HasDevicePermission(origin, *device_info));

  std::vector<std::unique_ptr<UsbChooserContext::Object>> objects =
      store->GetGrantedObjects(origin);
  EXPECT_EQ(1u, objects.size());

  std::vector<std::unique_ptr<UsbChooserContext::Object>> all_origin_objects =
      store->GetAllGrantedObjects();
  EXPECT_EQ(1u, all_origin_objects.size());

  EXPECT_CALL(*mock_device_observers_[profile()], OnDeviceRemoved(_));
  device_manager_.RemoveDevice(device_info->guid);
  base::RunLoop().RunUntilIdle();

  EXPECT_TRUE(store->HasDevicePermission(origin, *device_info));
  objects = store->GetGrantedObjects(origin);
  EXPECT_EQ(1u, objects.size());
  all_origin_objects = store->GetAllGrantedObjects();
  EXPECT_EQ(1u, all_origin_objects.size());

  UsbDeviceInfoPtr reconnected_device_info =
      device_manager_.CreateAndAddDevice(0, 0, "Google", "Gizmo", "123ABC");

  EXPECT_TRUE(store->HasDevicePermission(origin, *reconnected_device_info));
  objects = store->GetGrantedObjects(origin);
  EXPECT_EQ(1u, objects.size());
  all_origin_objects = store->GetAllGrantedObjects();
  EXPECT_EQ(1u, all_origin_objects.size());
}

TEST_F(UsbChooserContextTest, DisconnectDeviceWithEphemeralPermission) {
  GURL url("https://www.google.com");
  const auto origin = url::Origin::Create(url);
  UsbDeviceInfoPtr device_info =
      device_manager_.CreateAndAddDevice(0, 0, "Google", "Gizmo", "");

  UsbChooserContext* store = GetChooserContext(profile());

  EXPECT_FALSE(store->HasDevicePermission(origin, *device_info));
  EXPECT_CALL(*mock_permission_observers_[profile()],
              OnObjectPermissionChanged(
                  std::make_optional(ContentSettingsType::USB_GUARD),
                  ContentSettingsType::USB_CHOOSER_DATA));

  store->GrantDevicePermission(origin, *device_info);
  EXPECT_TRUE(store->HasDevicePermission(origin, *device_info));

  std::vector<std::unique_ptr<UsbChooserContext::Object>> objects =
      store->GetGrantedObjects(origin);
  EXPECT_EQ(1u, objects.size());

  std::vector<std::unique_ptr<UsbChooserContext::Object>> all_origin_objects =
      store->GetAllGrantedObjects();
  EXPECT_EQ(1u, all_origin_objects.size());

  EXPECT_CALL(*mock_permission_observers_[profile()],
              OnObjectPermissionChanged(
                  std::make_optional(ContentSettingsType::USB_GUARD),
                  ContentSettingsType::USB_CHOOSER_DATA));
  EXPECT_CALL(*mock_device_observers_[profile()], OnDeviceRemoved(_));
  device_manager_.RemoveDevice(device_info->guid);
  base::RunLoop().RunUntilIdle();

  EXPECT_FALSE(store->HasDevicePermission(origin, *device_info));
  objects = store->GetGrantedObjects(origin);
  EXPECT_EQ(0u, objects.size());
  all_origin_objects = store->GetAllGrantedObjects();
  EXPECT_EQ(0u, all_origin_objects.size());

  UsbDeviceInfoPtr reconnected_device_info =
      device_manager_.CreateAndAddDevice(0, 0, "Google", "Gizmo", "");

  EXPECT_FALSE(store->HasDevicePermission(origin, *reconnected_device_info));
  objects = store->GetGrantedObjects(origin);
  EXPECT_EQ(0u, objects.size());
  all_origin_objects = store->GetAllGrantedObjects();
  EXPECT_EQ(0u, all_origin_objects.size());
}

TEST_F(UsbChooserContextTest, GrantPermissionInIncognito) {
  GURL url("https://www.google.com");
  const auto origin = url::Origin::Create(url);
  UsbDeviceInfoPtr device_info_1 =
      device_manager_.CreateAndAddDevice(0, 0, "Google", "Gizmo", "");
  UsbDeviceInfoPtr device_info_2 =
      device_manager_.CreateAndAddDevice(0, 0, "Google", "Gizmo", "");
  UsbChooserContext* store = GetChooserContext(profile());
  auto* otr_profile =
      profile()->GetPrimaryOTRProfile(/*create_if_needed=*/true);
  UsbChooserContext* incognito_store = GetChooserContext(otr_profile);

  EXPECT_CALL(*mock_permission_observers_[profile()],
              OnObjectPermissionChanged(
                  std::make_optional(ContentSettingsType::USB_GUARD),
                  ContentSettingsType::USB_CHOOSER_DATA));

  store->GrantDevicePermission(origin, *device_info_1);
  EXPECT_TRUE(store->HasDevicePermission(origin, *device_info_1));
  EXPECT_FALSE(incognito_store->HasDevicePermission(origin, *device_info_1));

  EXPECT_CALL(*mock_permission_observers_[otr_profile],
              OnObjectPermissionChanged(
                  std::make_optional(ContentSettingsType::USB_GUARD),
                  ContentSettingsType::USB_CHOOSER_DATA));

  incognito_store->GrantDevicePermission(origin, *device_info_2);
  EXPECT_TRUE(store->HasDevicePermission(origin, *device_info_1));
  EXPECT_FALSE(store->HasDevicePermission(origin, *device_info_2));
  EXPECT_FALSE(incognito_store->HasDevicePermission(origin, *device_info_1));
  EXPECT_TRUE(incognito_store->HasDevicePermission(origin, *device_info_2));

  {
    std::vector<std::unique_ptr<UsbChooserContext::Object>> objects =
        store->GetGrantedObjects(origin);
    EXPECT_EQ(1u, objects.size());
    std::vector<std::unique_ptr<UsbChooserContext::Object>> all_origin_objects =
        store->GetAllGrantedObjects();
    ASSERT_EQ(1u, all_origin_objects.size());
    EXPECT_FALSE(all_origin_objects[0]->incognito);
  }
  {
    std::vector<std::unique_ptr<UsbChooserContext::Object>> objects =
        incognito_store->GetGrantedObjects(origin);
    EXPECT_EQ(1u, objects.size());
    std::vector<std::unique_ptr<UsbChooserContext::Object>> all_origin_objects =
        incognito_store->GetAllGrantedObjects();
    ASSERT_EQ(1u, all_origin_objects.size());
    EXPECT_TRUE(all_origin_objects[0]->incognito);
  }
}

TEST_F(UsbChooserContextTest, UsbGuardPermission) {
  const GURL kFooUrl("https://foo.com");
  const auto kFooOrigin = url::Origin::Create(kFooUrl);
  const GURL kBarUrl("https://bar.com");
  const auto kBarOrigin = url::Origin::Create(kBarUrl);
  UsbDeviceInfoPtr device_info =
      device_manager_.CreateAndAddDevice(0, 0, "Google", "Gizmo", "ABC123");
  UsbDeviceInfoPtr ephemeral_device_info =
      device_manager_.CreateAndAddDevice(0, 0, "Google", "Gizmo", "");

  auto* map = HostContentSettingsMapFactory::GetForProfile(profile());
  map->SetContentSettingDefaultScope(
      kFooUrl, kFooUrl, ContentSettingsType::USB_GUARD, CONTENT_SETTING_BLOCK);

  auto* store = GetChooserContext(profile());
  EXPECT_CALL(*mock_permission_observers_[profile()],
              OnObjectPermissionChanged(
                  std::make_optional(ContentSettingsType::USB_GUARD),
                  ContentSettingsType::USB_CHOOSER_DATA))
      .Times(4);
  store->GrantDevicePermission(kFooOrigin, *device_info);
  store->GrantDevicePermission(kFooOrigin, *ephemeral_device_info);
  store->GrantDevicePermission(kBarOrigin, *device_info);
  store->GrantDevicePermission(kBarOrigin, *ephemeral_device_info);

  std::vector<std::unique_ptr<UsbChooserContext::Object>> objects =
      store->GetGrantedObjects(kFooOrigin);
  EXPECT_EQ(0u, objects.size());

  objects = store->GetGrantedObjects(kBarOrigin);
  EXPECT_EQ(2u, objects.size());

  std::vector<std::unique_ptr<UsbChooserContext::Object>> all_origin_objects =
      store->GetAllGrantedObjects();
  for (const auto& object : all_origin_objects) {
    EXPECT_EQ(object->origin, kBarUrl);
  }
  EXPECT_EQ(2u, all_origin_objects.size());

  EXPECT_FALSE(store->HasDevicePermission(kFooOrigin, *device_info));
  EXPECT_FALSE(store->HasDevicePermission(kFooOrigin, *ephemeral_device_info));
  EXPECT_TRUE(store->HasDevicePermission(kBarOrigin, *device_info));
  EXPECT_TRUE(store->HasDevicePermission(kBarOrigin, *ephemeral_device_info));
}

TEST_F(UsbChooserContextTest, GetObjectDisplayNameForNamelessDevice) {
  const GURL kGoogleUrl("https://www.google.com");
  const auto kGoogleOrigin = url::Origin::Create(kGoogleUrl);
  UsbDeviceInfoPtr device_info =
      device_manager_.CreateAndAddDevice(6353, 5678, "", "", "");

  auto* store = GetChooserContext(profile());
  store->GrantDevicePermission(kGoogleOrigin, *device_info);

  auto objects = store->GetAllGrantedObjects();
  ASSERT_EQ(objects.size(), 1u);
  EXPECT_EQ(store->GetObjectDisplayName(objects[0]->value),
            u"Unknown product 0x162E from Google Inc.");
}

TEST_F(UsbChooserContextTest, PolicyGuardPermission) {
  const auto origin = url::Origin::Create(GURL("https://google.com"));

  UsbDeviceInfoPtr device =
      device_manager_.CreateAndAddDevice(0, 0, "", "", "");
  auto* store = GetChooserContext(profile());
  store->GrantDevicePermission(origin, *device);

  auto* prefs = profile()->GetTestingPrefService();
  prefs->SetManagedPref(prefs::kManagedDefaultWebUsbGuardSetting,
                        std::make_unique<base::Value>(CONTENT_SETTING_BLOCK));
  EXPECT_FALSE(store->CanRequestObjectPermission(origin));
  EXPECT_FALSE(store->HasDevicePermission(origin, *device));

  std::vector<std::unique_ptr<UsbChooserContext::Object>> objects =
      store->GetGrantedObjects(origin);
  EXPECT_EQ(0u, objects.size());

  std::vector<std::unique_ptr<UsbChooserContext::Object>> all_origin_objects =
      store->GetAllGrantedObjects();
  EXPECT_EQ(0u, all_origin_objects.size());
}

TEST_F(UsbChooserContextTest, PolicyAskForUrls) {
  const auto kFooOrigin = url::Origin::Create(GURL("https://foo.origin"));
  const auto kBarOrigin = url::Origin::Create(GURL("https://bar.origin"));

  UsbDeviceInfoPtr device =
      device_manager_.CreateAndAddDevice(0, 0, "", "", "");
  auto* store = GetChooserContext(profile());
  store->GrantDevicePermission(kFooOrigin, *device);
  store->GrantDevicePermission(kBarOrigin, *device);

  // Set the default to "ask" so that the policy being tested overrides it.
  auto* prefs = profile()->GetTestingPrefService();
  prefs->SetManagedPref(prefs::kManagedDefaultWebUsbGuardSetting,
                        std::make_unique<base::Value>(CONTENT_SETTING_BLOCK));
  prefs->SetManagedPref(prefs::kManagedWebUsbAskForUrls,
                        base::test::ParseJsonList(R"(
    [ "https://foo.origin" ]
  )"));

  EXPECT_TRUE(store->CanRequestObjectPermission(kFooOrigin));
  EXPECT_TRUE(store->HasDevicePermission(kFooOrigin, *device));
  EXPECT_FALSE(store->CanRequestObjectPermission(kBarOrigin));
  EXPECT_FALSE(store->HasDevicePermission(kBarOrigin, *device));

  std::vector<std::unique_ptr<UsbChooserContext::Object>> objects =
      store->GetGrantedObjects(kFooOrigin);
  EXPECT_EQ(1u, objects.size());
  objects = store->GetGrantedObjects(kBarOrigin);
  EXPECT_EQ(0u, objects.size());

  std::vector<std::unique_ptr<UsbChooserContext::Object>> all_origin_objects =
      store->GetAllGrantedObjects();
  EXPECT_EQ(1u, all_origin_objects.size());
}

TEST_F(UsbChooserContextTest, PolicyBlockedForUrls) {
  const auto kFooOrigin = url::Origin::Create(GURL("https://foo.origin"));
  const auto kBarOrigin = url::Origin::Create(GURL("https://bar.origin"));

  UsbDeviceInfoPtr device =
      device_manager_.CreateAndAddDevice(0, 0, "", "", "");
  auto* store = GetChooserContext(profile());
  store->GrantDevicePermission(kFooOrigin, *device);
  store->GrantDevicePermission(kBarOrigin, *device);

  auto* prefs = profile()->GetTestingPrefService();
  prefs->SetManagedPref(prefs::kManagedWebUsbBlockedForUrls,
                        base::test::ParseJsonList(R"(
    [ "https://foo.origin" ]
  )"));

  EXPECT_FALSE(store->CanRequestObjectPermission(kFooOrigin));
  EXPECT_FALSE(store->HasDevicePermission(kFooOrigin, *device));
  EXPECT_TRUE(store->CanRequestObjectPermission(kBarOrigin));
  EXPECT_TRUE(store->HasDevicePermission(kBarOrigin, *device));

  std::vector<std::unique_ptr<UsbChooserContext::Object>> objects =
      store->GetGrantedObjects(kFooOrigin);
  EXPECT_EQ(0u, objects.size());
  objects = store->GetGrantedObjects(kBarOrigin);
  EXPECT_EQ(1u, objects.size());

  std::vector<std::unique_ptr<UsbChooserContext::Object>> all_origin_objects =
      store->GetAllGrantedObjects();
  EXPECT_EQ(1u, all_origin_objects.size());
}

namespace {

constexpr char kPolicySetting[] = R"(
    [
      {
        "devices": [{ "vendor_id": 6353, "product_id": 5678 }],
        "urls": ["https://product.vendor.com"]
      }, {
        "devices": [{ "vendor_id": 6353 }],
        "urls": ["https://vendor.com"]
      }, {
        "devices": [{}],
        "urls": ["https://anydevice.com"]
      }, {
        "devices": [{ "vendor_id": 6354, "product_id": 1357 }],
        "urls": ["https://gadget.com,https://cool.com"]
      }
    ])";

// Test URLs
constexpr char kAnyDeviceUrl[] = "https://anydevice.com/";
constexpr char kVendorUrl[] = "https://vendor.com/";
constexpr char kProductVendorUrl[] = "https://product.vendor.com/";
constexpr char kGadgetUrl[] = "https://gadget.com/";
constexpr char kCoolUrl[] = "https://cool.com/";

const std::vector<GURL>& PolicyOrigins() {
  static base::NoDestructor<std::vector<GURL>> origins{
      {GURL(kProductVendorUrl), GURL(kVendorUrl), GURL(kAnyDeviceUrl),
       GURL(kGadgetUrl), GURL(kCoolUrl)}};
  return *origins;
}

void ExpectNoPermissions(UsbChooserContext* store,
                         const device::mojom::UsbDeviceInfo& device_info) {
  for (const auto& origin_url : PolicyOrigins()) {
    const auto origin = url::Origin::Create(origin_url);
    EXPECT_FALSE(store->HasDevicePermission(origin, device_info));
  }
}

void ExpectCorrectPermissions(UsbChooserContext* store,
                              const std::vector<GURL>& kValidOrigins,
                              const std::vector<GURL>& kInvalidOrigins,
                              const device::mojom::UsbDeviceInfo& device_info) {
  // Ensure that only |kValidOrigin| as the top-level origin has
  // permission to access the device described by |device_info|.
  for (const auto& valid_origin : kValidOrigins) {
    EXPECT_TRUE(store->HasDevicePermission(url::Origin::Create(valid_origin),
                                           device_info));
  }

  for (const auto& invalid_origin : kInvalidOrigins) {
    EXPECT_FALSE(store->HasDevicePermission(url::Origin::Create(invalid_origin),
                                            device_info));
  }
}

}  // namespace

TEST_F(UsbChooserContextTest,
       UsbAllowDevicesForUrlsPermissionForSpecificDevice) {
  const std::vector<GURL> kValidOrigins = {
      GURL(kProductVendorUrl), GURL(kVendorUrl), GURL(kAnyDeviceUrl)};
  const std::vector<GURL> kInvalidOrigins = {GURL(kGadgetUrl), GURL(kCoolUrl)};

  UsbDeviceInfoPtr specific_device_info = device_manager_.CreateAndAddDevice(
      6353, 5678, "Google", "Gizmo", "ABC123");

  auto* store = GetChooserContext(profile());

  ExpectNoPermissions(store, *specific_device_info);

  profile()->GetPrefs()->SetList(prefs::kManagedWebUsbAllowDevicesForUrls,
                                 base::test::ParseJsonList(kPolicySetting));

  ExpectCorrectPermissions(store, kValidOrigins, kInvalidOrigins,
                           *specific_device_info);
}

TEST_F(UsbChooserContextTest,
       UsbAllowDevicesForUrlsPermissionForVendorRelatedDevice) {
  const std::vector<GURL> kValidOrigins = {GURL(kVendorUrl),
                                           GURL(kAnyDeviceUrl)};
  const std::vector<GURL> kInvalidOrigins = {GURL(kProductVendorUrl),
                                             GURL(kGadgetUrl), GURL(kCoolUrl)};

  UsbDeviceInfoPtr vendor_related_device_info =
      device_manager_.CreateAndAddDevice(6353, 8765, "Google", "Widget",
                                         "XYZ987");

  auto* store = GetChooserContext(profile());

  ExpectNoPermissions(store, *vendor_related_device_info);

  profile()->GetPrefs()->SetList(prefs::kManagedWebUsbAllowDevicesForUrls,
                                 base::test::ParseJsonList(kPolicySetting));

  ExpectCorrectPermissions(store, kValidOrigins, kInvalidOrigins,
                           *vendor_related_device_info);
}

TEST_F(UsbChooserContextTest,
       UsbAllowDevicesForUrlsPermissionForUnrelatedDevice) {
  const std::vector<GURL> kValidOrigins = {GURL(kAnyDeviceUrl)};
  const std::vector<GURL> kInvalidOrigins = {
      GURL(kProductVendorUrl), GURL(kVendorUrl), GURL(kGadgetUrl)};
  const auto kCoolOrigin = url::Origin::Create(GURL(kCoolUrl));

  UsbDeviceInfoPtr unrelated_device_info = device_manager_.CreateAndAddDevice(
      6354, 1357, "Cool", "Gadget", "4W350M3");

  auto* store = GetChooserContext(profile());

  ExpectNoPermissions(store, *unrelated_device_info);

  profile()->GetPrefs()->SetList(prefs::kManagedWebUsbAllowDevicesForUrls,
                                 base::test::ParseJsonList(kPolicySetting));

  EXPECT_TRUE(store->HasDevicePermission(kCoolOrigin, *unrelated_device_info));
  for (const auto& origin_url : PolicyOrigins()) {
    const auto origin = url::Origin::Create(origin_url);
    if (origin_url != GURL(kCoolUrl) && origin_url != GURL(kAnyDeviceUrl)) {
      EXPECT_FALSE(store->HasDevicePermission(origin, *unrelated_device_info));
    }
  }
  ExpectCorrectPermissions(store, kValidOrigins, kInvalidOrigins,
                           *unrelated_device_info);
}

TEST_F(UsbChooserContextTest,
       UsbAllowDevicesForUrlsPermissionOverrulesUsbGuardPermission) {
  const auto kProductVendorOrigin =
      url::Origin::Create(GURL(kProductVendorUrl));
  const auto kGadgetOrigin = url::Origin::Create(GURL(kGadgetUrl));
  const auto kCoolOrigin = url::Origin::Create(GURL(kCoolUrl));

  UsbDeviceInfoPtr specific_device_info = device_manager_.CreateAndAddDevice(
      6353, 5678, "Google", "Gizmo", "ABC123");
  UsbDeviceInfoPtr unrelated_device_info = device_manager_.CreateAndAddDevice(
      6354, 1357, "Cool", "Gadget", "4W350M3");

  auto* store = GetChooserContext(profile());

  ExpectNoPermissions(store, *specific_device_info);
  ExpectNoPermissions(store, *unrelated_device_info);

  auto* map = HostContentSettingsMapFactory::GetForProfile(profile());
  map->SetContentSettingDefaultScope(
      GURL(kProductVendorUrl), GURL(kProductVendorUrl),
      ContentSettingsType::USB_GUARD, CONTENT_SETTING_BLOCK);
  map->SetContentSettingDefaultScope(GURL(kGadgetUrl), GURL(kCoolUrl),
                                     ContentSettingsType::USB_GUARD,
                                     CONTENT_SETTING_BLOCK);
  EXPECT_FALSE(
      store->HasDevicePermission(kProductVendorOrigin, *specific_device_info));
  EXPECT_FALSE(
      store->HasDevicePermission(kProductVendorOrigin, *unrelated_device_info));
  EXPECT_FALSE(store->HasDevicePermission(kCoolOrigin, *specific_device_info));
  EXPECT_FALSE(store->HasDevicePermission(kCoolOrigin, *unrelated_device_info));

  profile()->GetPrefs()->SetList(prefs::kManagedWebUsbAllowDevicesForUrls,
                                 base::test::ParseJsonList(kPolicySetting));

  EXPECT_TRUE(
      store->HasDevicePermission(kProductVendorOrigin, *specific_device_info));
  EXPECT_FALSE(
      store->HasDevicePermission(kProductVendorOrigin, *unrelated_device_info));
  EXPECT_FALSE(store->HasDevicePermission(kCoolOrigin, *specific_device_info));
  EXPECT_TRUE(store->HasDevicePermission(kCoolOrigin, *unrelated_device_info));
}

#if BUILDFLAG(IS_CHROMEOS_ASH)

class DeviceLoginScreenWebUsbChooserContextTest : public UsbChooserContextTest {
 public:
  DeviceLoginScreenWebUsbChooserContextTest() {
    TestingProfile::Builder builder;
    builder.SetPath(base::FilePath(FILE_PATH_LITERAL(chrome::kInitialProfile)));
    signin_profile_ = builder.Build();
  }
  ~DeviceLoginScreenWebUsbChooserContextTest() override = default;

 protected:
  Profile* GetSigninProfile() { return signin_profile_.get(); }

 private:
  std::unique_ptr<Profile> signin_profile_;
};

TEST_F(DeviceLoginScreenWebUsbChooserContextTest,
       UserUsbChooserContextOnlyUsesUserPolicy) {
  const std::vector<GURL> kValidOrigins = {
      GURL(kProductVendorUrl), GURL(kVendorUrl), GURL(kAnyDeviceUrl)};
  const std::vector<GURL> kInvalidOrigins = {GURL(kGadgetUrl), GURL(kCoolUrl)};

  UsbDeviceInfoPtr specific_device_info = device_manager_.CreateAndAddDevice(
      6353, 5678, "Google", "Gizmo", "ABC123");

  Profile* user_profile = profile();
  Profile* signin_profile = GetSigninProfile();

  auto* user_store = GetChooserContext(user_profile);
  auto* signin_store = GetChooserContext(signin_profile);

  ExpectNoPermissions(user_store, *specific_device_info);
  ExpectNoPermissions(signin_store, *specific_device_info);

  user_profile->GetPrefs()->SetList(prefs::kManagedWebUsbAllowDevicesForUrls,
                                    base::test::ParseJsonList(kPolicySetting));

  ExpectCorrectPermissions(user_store, kValidOrigins, kInvalidOrigins,
                           *specific_device_info);
  ExpectNoPermissions(signin_store, *specific_device_info);
}

TEST_F(DeviceLoginScreenWebUsbChooserContextTest,
       SigninUsbChooserContextOnlyUsesDevicePolicy) {
  const std::vector<GURL> kValidOrigins = {
      GURL(kProductVendorUrl), GURL(kVendorUrl), GURL(kAnyDeviceUrl)};
  const std::vector<GURL> kInvalidOrigins = {GURL(kGadgetUrl), GURL(kCoolUrl)};

  UsbDeviceInfoPtr specific_device_info = device_manager_.CreateAndAddDevice(
      6353, 5678, "Google", "Gizmo", "ABC123");

  Profile* user_profile = profile();
  Profile* signin_profile = GetSigninProfile();

  auto* user_store = GetChooserContext(user_profile);
  auto* signin_store = GetChooserContext(signin_profile);

  ExpectNoPermissions(user_store, *specific_device_info);
  ExpectNoPermissions(signin_store, *specific_device_info);

  signin_profile->GetPrefs()->SetList(
      prefs::kManagedWebUsbAllowDevicesForUrls,
      base::test::ParseJsonList(kPolicySetting));

  ExpectNoPermissions(user_store, *specific_device_info);
  ExpectCorrectPermissions(signin_store, kValidOrigins, kInvalidOrigins,
                           *specific_device_info);
}

#endif  // BUILDFLAG(IS_CHROMEOS_ASH)

namespace {

void ExpectDeviceObjectInfo(const base::Value::Dict& actual,
                            int vendor_id,
                            int product_id,
                            const std::string& name) {
  const std::optional<int> actual_vendor_id = actual.FindInt(kVendorIdKey);
  ASSERT_TRUE(actual_vendor_id);
  EXPECT_EQ(*actual_vendor_id, vendor_id);

  const std::optional<int> actual_product_id = actual.FindInt(kProductIdKey);
  ASSERT_TRUE(actual_product_id);
  EXPECT_EQ(*actual_product_id, product_id);

  const std::string* actual_device_name = actual.FindString(kDeviceNameKey);
  ASSERT_TRUE(actual_device_name);
  EXPECT_EQ(*actual_device_name, name);
}

void ExpectChooserObjectInfo(const UsbChooserContext::Object* actual,
                             const GURL& origin,
                             content_settings::SettingSource source,
                             bool incognito,
                             int vendor_id,
                             int product_id,
                             const std::string& name) {
  ASSERT_TRUE(actual);
  EXPECT_EQ(actual->origin, origin);
  EXPECT_EQ(actual->source, source);
  EXPECT_EQ(actual->incognito, incognito);
  ExpectDeviceObjectInfo(actual->value, vendor_id, product_id, name);
}

}  // namespace

TEST_F(UsbChooserContextTest, GetGrantedObjectsWithOnlyPolicyAllowedDevices) {
  auto* store = GetChooserContext(profile());
  profile()->GetPrefs()->SetList(prefs::kManagedWebUsbAllowDevicesForUrls,
                                 base::test::ParseJsonList(kPolicySetting));

  const auto kVendorOrigin = url::Origin::Create(GURL(kVendorUrl));
  auto objects = store->GetGrantedObjects(kVendorOrigin);
  ASSERT_EQ(objects.size(), 1u);

  ExpectChooserObjectInfo(objects[0].get(),
                          /*origin=*/GURL(kVendorUrl),
                          /*source=*/content_settings::SETTING_SOURCE_POLICY,
                          /*incognito=*/false,
                          /*vendor_id=*/6353,
                          /*product_id=*/kDeviceIdWildcard,
                          /*name=*/"Devices from Google Inc.");
}

TEST_F(UsbChooserContextTest,
       GetGrantedObjectsWithUserAndPolicyAllowedDevices) {
  profile()->GetPrefs()->SetList(prefs::kManagedWebUsbAllowDevicesForUrls,
                                 base::test::ParseJsonList(kPolicySetting));

  UsbDeviceInfoPtr persistent_device_info =
      device_manager_.CreateAndAddDevice(1000, 1, "Google", "Gizmo", "123ABC");
  UsbDeviceInfoPtr ephemeral_device_info =
      device_manager_.CreateAndAddDevice(1000, 2, "Google", "Gadget", "");

  auto* store = GetChooserContext(profile());

  const auto kVendorOrigin = url::Origin::Create(GURL(kVendorUrl));
  store->GrantDevicePermission(kVendorOrigin, *persistent_device_info);
  store->GrantDevicePermission(kVendorOrigin, *ephemeral_device_info);

  auto objects = store->GetGrantedObjects(kVendorOrigin);
  ASSERT_EQ(objects.size(), 3u);

  // The user granted permissions appear before the policy granted permissions.
  // Within these user granted permissions, the persistent device permissions
  // appear before ephemeral device permissions. The policy enforced objects
  // that are returned by GetGrantedObjects() are ordered by the tuple
  // (vendor_id, product_id) representing the device IDs.  Wildcard IDs are
  // represented by a value of -1, so they appear first.
  ExpectChooserObjectInfo(objects[0].get(),
                          /*origin=*/GURL(kVendorUrl),
                          /*source=*/content_settings::SETTING_SOURCE_USER,
                          /*incognito=*/false,
                          /*vendor_id=*/1000,
                          /*product_id=*/1,
                          /*name=*/"Gizmo");
  ExpectChooserObjectInfo(objects[1].get(),
                          /*origin=*/GURL(kVendorUrl),
                          /*source=*/content_settings::SETTING_SOURCE_USER,
                          /*incognito=*/false,
                          /*vendor_id=*/1000,
                          /*product_id=*/2,
                          /*name=*/"Gadget");
  ExpectChooserObjectInfo(objects[2].get(),
                          /*origin=*/GURL(kVendorUrl),
                          /*source=*/content_settings::SETTING_SOURCE_POLICY,
                          /*incognito=*/false,
                          /*vendor_id=*/6353,
                          /*product_id=*/kDeviceIdWildcard,
                          /*name=*/"Devices from Google Inc.");
}

TEST_F(UsbChooserContextTest,
       GetGrantedObjectsWithUserGrantedDeviceAllowedBySpecificDevicePolicy) {
  profile()->GetPrefs()->SetList(prefs::kManagedWebUsbAllowDevicesForUrls,
                                 base::test::ParseJsonList(kPolicySetting));

  UsbDeviceInfoPtr persistent_device_info = device_manager_.CreateAndAddDevice(
      6353, 5678, "Google", "Gizmo", "123ABC");

  auto* store = GetChooserContext(profile());
  const auto kProductVendorOrigin =
      url::Origin::Create(GURL(kProductVendorUrl));
  store->GrantDevicePermission(kProductVendorOrigin, *persistent_device_info);

  auto objects = store->GetGrantedObjects(kProductVendorOrigin);
  ASSERT_EQ(objects.size(), 1u);

  // User granted permissions for a device that is also granted by a specific
  // device policy will be replaced by the policy permission. The object should
  // still retain the name of the device.
  ExpectChooserObjectInfo(objects[0].get(),
                          /*origin=*/GURL(kProductVendorUrl),
                          /*source=*/content_settings::SETTING_SOURCE_POLICY,
                          /*incognito=*/false,
                          /*vendor_id=*/6353,
                          /*product_id=*/5678,
                          /*name=*/"Gizmo");
}

TEST_F(UsbChooserContextTest,
       GetGrantedObjectsWithUserGrantedDeviceAllowedByVendorDevicePolicy) {
  UsbDeviceInfoPtr persistent_device_info = device_manager_.CreateAndAddDevice(
      6353, 1000, "Vendor", "Product", "123ABC");

  auto* store = GetChooserContext(profile());
  profile()->GetPrefs()->SetList(prefs::kManagedWebUsbAllowDevicesForUrls,
                                 base::test::ParseJsonList(kPolicySetting));

  const auto kVendorOrigin = url::Origin::Create(GURL(kVendorUrl));
  store->GrantDevicePermission(kVendorOrigin, *persistent_device_info);

  auto objects = store->GetGrantedObjects(kVendorOrigin);
  ASSERT_EQ(objects.size(), 1u);

  // User granted permissions for a device that is also granted by a vendor
  // device policy will be replaced by the policy permission.
  ExpectChooserObjectInfo(objects[0].get(),
                          /*origin=*/GURL(kVendorUrl),
                          /*source=*/content_settings::SETTING_SOURCE_POLICY,
                          /*incognito=*/false,
                          /*vendor_id=*/6353,
                          /*product_id=*/kDeviceIdWildcard,
                          /*name=*/"Devices from Google Inc.");
}

TEST_F(UsbChooserContextTest,
       GetGrantedObjectsWithUserGrantedDeviceAllowedByAnyVendorDevicePolicy) {
  UsbDeviceInfoPtr persistent_device_info = device_manager_.CreateAndAddDevice(
      1123, 5813, "Some", "Product", "123ABC");

  auto* store = GetChooserContext(profile());
  profile()->GetPrefs()->SetList(prefs::kManagedWebUsbAllowDevicesForUrls,
                                 base::test::ParseJsonList(kPolicySetting));

  const auto kAnyDeviceOrigin = url::Origin::Create(GURL(kAnyDeviceUrl));
  store->GrantDevicePermission(kAnyDeviceOrigin, *persistent_device_info);

  auto objects = store->GetGrantedObjects(kAnyDeviceOrigin);
  ASSERT_EQ(objects.size(), 1u);

  // User granted permissions for a device that is also granted by a wildcard
  // vendor policy will be replaced by the policy permission.
  ExpectChooserObjectInfo(objects[0].get(),
                          /*origin=*/GURL(kAnyDeviceUrl),
                          /*source=*/content_settings::SETTING_SOURCE_POLICY,
                          /*incognito=*/false,
                          /*vendor_id=*/kDeviceIdWildcard,
                          /*product_id=*/kDeviceIdWildcard,
                          /*name=*/"Devices from any vendor");
}

TEST_F(UsbChooserContextTest,
       GetAllGrantedObjectsWithOnlyPolicyAllowedDevices) {
  auto* store = GetChooserContext(profile());
  profile()->GetPrefs()->SetList(prefs::kManagedWebUsbAllowDevicesForUrls,
                                 base::test::ParseJsonList(kPolicySetting));

  auto objects = store->GetAllGrantedObjects();
  ASSERT_EQ(objects.size(), 4u);

  // The policy enforced objects that are returned by GetAllGrantedObjects() are
  // ordered by the tuple (vendor_id, product_id) representing the device IDs.
  // Wildcard IDs are represented by a value of -1, so they appear first.
  ExpectChooserObjectInfo(objects[0].get(),
                          /*origin=*/GURL(kAnyDeviceUrl),
                          /*source=*/content_settings::SETTING_SOURCE_POLICY,
                          /*incognito=*/false,
                          /*vendor_id=*/kDeviceIdWildcard,
                          /*product_id=*/kDeviceIdWildcard,
                          /*name=*/"Devices from any vendor");
  ExpectChooserObjectInfo(objects[1].get(),
                          /*origin=*/GURL(kVendorUrl),
                          /*source=*/content_settings::SETTING_SOURCE_POLICY,
                          /*incognito=*/false,
                          /*vendor_id=*/6353,
                          /*product_id=*/kDeviceIdWildcard,
                          /*name=*/"Devices from Google Inc.");
  ExpectChooserObjectInfo(objects[2].get(),
                          /*origin=*/GURL(kProductVendorUrl),
                          /*source=*/content_settings::SETTING_SOURCE_POLICY,
                          /*incognito=*/false,
                          /*vendor_id=*/6353,
                          /*product_id=*/5678,
                          /*name=*/"Unknown product 0x162E from Google Inc.");
  ExpectChooserObjectInfo(objects[3].get(),
                          /*origin=*/GURL(kCoolUrl),
                          /*source=*/content_settings::SETTING_SOURCE_POLICY,
                          /*incognito=*/false,
                          /*vendor_id=*/6354,
                          /*product_id=*/1357,
                          /*name=*/"Unknown product 0x054D from vendor 0x18D2");
}

TEST_F(UsbChooserContextTest,
       GetAllGrantedObjectsWithUserAndPolicyAllowedDevices) {
  profile()->GetPrefs()->SetList(prefs::kManagedWebUsbAllowDevicesForUrls,
                                 base::test::ParseJsonList(kPolicySetting));

  const GURL kGoogleUrl("https://www.google.com");
  const auto kGoogleOrigin = url::Origin::Create(kGoogleUrl);
  UsbDeviceInfoPtr persistent_device_info =
      device_manager_.CreateAndAddDevice(1000, 1, "Google", "Gizmo", "123ABC");
  UsbDeviceInfoPtr ephemeral_device_info =
      device_manager_.CreateAndAddDevice(1000, 2, "Google", "Gadget", "");

  auto* store = GetChooserContext(profile());

  EXPECT_CALL(*mock_permission_observers_[profile()],
              OnObjectPermissionChanged(
                  std::make_optional(ContentSettingsType::USB_GUARD),
                  ContentSettingsType::USB_CHOOSER_DATA))
      .Times(2);
  store->GrantDevicePermission(kGoogleOrigin, *persistent_device_info);
  store->GrantDevicePermission(kGoogleOrigin, *ephemeral_device_info);

  auto objects = store->GetAllGrantedObjects();
  ASSERT_EQ(objects.size(), 6u);

  for (const auto& object : objects) {
    EXPECT_TRUE(store->IsValidObject(object->value));
  }

  // The user granted permissions appear before the policy granted permissions.
  // Within the user granted permissions, the persistent device permissions
  // are added to the vector before ephemeral device permissions.
  ExpectChooserObjectInfo(objects[0].get(),
                          /*origin=*/kGoogleUrl,
                          /*source=*/content_settings::SETTING_SOURCE_USER,
                          /*incognito=*/false,
                          /*vendor_id=*/1000,
                          /*product_id=*/1,
                          /*name=*/"Gizmo");
  ExpectChooserObjectInfo(objects[1].get(),
                          /*origin=*/kGoogleUrl,
                          /*source=*/content_settings::SETTING_SOURCE_USER,
                          /*incognito=*/false,
                          /*vendor_id=*/1000,
                          /*product_id=*/2,
                          /*name=*/"Gadget");
  ExpectChooserObjectInfo(objects[2].get(),
                          /*origin=*/GURL(kAnyDeviceUrl),
                          /*source=*/content_settings::SETTING_SOURCE_POLICY,
                          /*incognito=*/false,
                          /*vendor_id=*/kDeviceIdWildcard,
                          /*product_id=*/kDeviceIdWildcard,
                          /*name=*/"Devices from any vendor");
  ExpectChooserObjectInfo(objects[3].get(),
                          /*origin=*/GURL(kVendorUrl),
                          /*source=*/content_settings::SETTING_SOURCE_POLICY,
                          /*incognito=*/false,
                          /*vendor_id=*/6353,
                          /*product_id=*/kDeviceIdWildcard,
                          /*name=*/"Devices from Google Inc.");
  ExpectChooserObjectInfo(objects[4].get(),
                          /*origin=*/GURL(kProductVendorUrl),
                          /*source=*/content_settings::SETTING_SOURCE_POLICY,
                          /*incognito=*/false,
                          /*vendor_id=*/6353,
                          /*product_id=*/5678,
                          /*name=*/"Unknown product 0x162E from Google Inc.");
  ExpectChooserObjectInfo(objects[5].get(),
                          /*origin=*/GURL(kCoolUrl),
                          /*source=*/content_settings::SETTING_SOURCE_POLICY,
                          /*incognito=*/false,
                          /*vendor_id=*/6354,
                          /*product_id=*/1357,
                          /*name=*/"Unknown product 0x054D from vendor 0x18D2");
}

TEST_F(UsbChooserContextTest,
       GetAllGrantedObjectsWithSpecificPolicyAndUserGrantedDevice) {
  auto* store = GetChooserContext(profile());
  profile()->GetPrefs()->SetList(prefs::kManagedWebUsbAllowDevicesForUrls,
                                 base::test::ParseJsonList(kPolicySetting));

  UsbDeviceInfoPtr persistent_device_info = device_manager_.CreateAndAddDevice(
      6353, 5678, "Specific", "Product", "123ABC");

  EXPECT_CALL(*mock_permission_observers_[profile()],
              OnObjectPermissionChanged(
                  std::make_optional(ContentSettingsType::USB_GUARD),
                  ContentSettingsType::USB_CHOOSER_DATA));
  const auto kProductVendorOrigin =
      url::Origin::Create(GURL(kProductVendorUrl));
  store->GrantDevicePermission(kProductVendorOrigin, *persistent_device_info);

  auto objects = store->GetAllGrantedObjects();
  ASSERT_EQ(objects.size(), 4u);

  for (const auto& object : objects) {
    EXPECT_TRUE(store->IsValidObject(object->value));
  }

  ExpectChooserObjectInfo(objects[0].get(),
                          /*origin=*/GURL(kAnyDeviceUrl),
                          /*source=*/content_settings::SETTING_SOURCE_POLICY,
                          /*incognito=*/false,
                          /*vendor_id=*/kDeviceIdWildcard,
                          /*product_id=*/kDeviceIdWildcard,
                          /*name=*/"Devices from any vendor");
  ExpectChooserObjectInfo(objects[1].get(),
                          /*origin=*/GURL(kVendorUrl),
                          /*source=*/content_settings::SETTING_SOURCE_POLICY,
                          /*incognito=*/false,
                          /*vendor_id=*/6353,
                          /*product_id=*/kDeviceIdWildcard,
                          /*name=*/"Devices from Google Inc.");
  ExpectChooserObjectInfo(objects[2].get(),
                          /*origin=*/GURL(kProductVendorUrl),
                          /*source=*/content_settings::SETTING_SOURCE_POLICY,
                          /*incognito=*/false,
                          /*vendor_id=*/6353,
                          /*product_id=*/5678,
                          /*name=*/"Product");
  ExpectChooserObjectInfo(objects[3].get(),
                          /*origin=*/GURL(kCoolUrl),
                          /*source=*/content_settings::SETTING_SOURCE_POLICY,
                          /*incognito=*/false,
                          /*vendor_id=*/6354,
                          /*product_id=*/1357,
                          /*name=*/"Unknown product 0x054D from vendor 0x18D2");
  ASSERT_TRUE(persistent_device_info->product_name);
  EXPECT_EQ(store->GetObjectDisplayName(objects[2]->value),
            persistent_device_info->product_name.value());
}

TEST_F(UsbChooserContextTest,
       GetAllGrantedObjectsWithVendorPolicyAndUserGrantedDevice) {
  UsbDeviceInfoPtr persistent_device_info = device_manager_.CreateAndAddDevice(
      6353, 1000, "Vendor", "Product", "123ABC");

  auto* store = GetChooserContext(profile());
  profile()->GetPrefs()->SetList(prefs::kManagedWebUsbAllowDevicesForUrls,
                                 base::test::ParseJsonList(kPolicySetting));

  EXPECT_CALL(*mock_permission_observers_[profile()],
              OnObjectPermissionChanged(
                  std::make_optional(ContentSettingsType::USB_GUARD),
                  ContentSettingsType::USB_CHOOSER_DATA));
  const auto kVendorOrigin = url::Origin::Create(GURL(kVendorUrl));
  store->GrantDevicePermission(kVendorOrigin, *persistent_device_info);

  auto objects = store->GetAllGrantedObjects();
  ASSERT_EQ(objects.size(), 4u);

  for (const auto& object : objects) {
    EXPECT_TRUE(store->IsValidObject(object->value));
  }

  ExpectChooserObjectInfo(objects[0].get(),
                          /*origin=*/GURL(kAnyDeviceUrl),
                          /*source=*/content_settings::SETTING_SOURCE_POLICY,
                          /*incognito=*/false,
                          /*vendor_id=*/kDeviceIdWildcard,
                          /*product_id=*/kDeviceIdWildcard,
                          /*name=*/"Devices from any vendor");
  ExpectChooserObjectInfo(objects[1].get(),
                          /*origin=*/GURL(kVendorUrl),
                          /*source=*/content_settings::SETTING_SOURCE_POLICY,
                          /*incognito=*/false,
                          /*vendor_id=*/6353,
                          /*product_id=*/kDeviceIdWildcard,
                          /*name=*/"Devices from Google Inc.");
  ExpectChooserObjectInfo(objects[2].get(),
                          /*origin=*/GURL(kProductVendorUrl),
                          /*source=*/content_settings::SETTING_SOURCE_POLICY,
                          /*incognito=*/false,
                          /*vendor_id=*/6353,
                          /*product_id=*/5678,
                          /*name=*/"Unknown product 0x162E from Google Inc.");
  ExpectChooserObjectInfo(objects[3].get(),
                          /*origin=*/GURL(kCoolUrl),
                          /*source=*/content_settings::SETTING_SOURCE_POLICY,
                          /*incognito=*/false,
                          /*vendor_id=*/6354,
                          /*product_id=*/1357,
                          /*name=*/"Unknown product 0x054D from vendor 0x18D2");
}

TEST_F(UsbChooserContextTest,
       GetAllGrantedObjectsWithAnyPolicyAndUserGrantedDevice) {
  UsbDeviceInfoPtr persistent_device_info = device_manager_.CreateAndAddDevice(
      1123, 5813, "Some", "Product", "123ABC");

  auto* store = GetChooserContext(profile());
  profile()->GetPrefs()->SetList(prefs::kManagedWebUsbAllowDevicesForUrls,
                                 base::test::ParseJsonList(kPolicySetting));

  EXPECT_CALL(*mock_permission_observers_[profile()],
              OnObjectPermissionChanged(
                  std::make_optional(ContentSettingsType::USB_GUARD),
                  ContentSettingsType::USB_CHOOSER_DATA));
  const auto kAnyDeviceOrigin = url::Origin::Create(GURL(kAnyDeviceUrl));
  store->GrantDevicePermission(kAnyDeviceOrigin, *persistent_device_info);

  auto objects = store->GetAllGrantedObjects();
  ASSERT_EQ(objects.size(), 4u);

  for (const auto& object : objects) {
    EXPECT_TRUE(store->IsValidObject(object->value));
  }

  ExpectChooserObjectInfo(objects[0].get(),
                          /*origin=*/GURL(kAnyDeviceUrl),
                          /*source=*/content_settings::SETTING_SOURCE_POLICY,
                          /*incognito=*/false,
                          /*vendor_id=*/kDeviceIdWildcard,
                          /*product_id=*/kDeviceIdWildcard,
                          /*name=*/"Devices from any vendor");
  ExpectChooserObjectInfo(objects[1].get(),
                          /*origin=*/GURL(kVendorUrl),
                          /*source=*/content_settings::SETTING_SOURCE_POLICY,
                          /*incognito=*/false,
                          /*vendor_id=*/6353,
                          /*product_id=*/kDeviceIdWildcard,
                          /*name=*/"Devices from Google Inc.");
  ExpectChooserObjectInfo(objects[2].get(),
                          /*origin=*/GURL(kProductVendorUrl),
                          /*source=*/content_settings::SETTING_SOURCE_POLICY,
                          /*incognito=*/false,
                          /*vendor_id=*/6353,
                          /*product_id=*/5678,
                          /*name=*/"Unknown product 0x162E from Google Inc.");
  ExpectChooserObjectInfo(objects[3].get(),
                          /*origin=*/GURL(kCoolUrl),
                          /*source=*/content_settings::SETTING_SOURCE_POLICY,
                          /*incognito=*/false,
                          /*vendor_id=*/6354,
                          /*product_id=*/1357,
                          /*name=*/"Unknown product 0x054D from vendor 0x18D2");
}

TEST_F(UsbChooserContextTest, MassStorageHidden) {
  GURL url("https://www.google.com");
  const auto origin = url::Origin::Create(url);

  // Mass storage devices should be hidden.
  std::vector<device::mojom::UsbConfigurationInfoPtr> storage_configs;
  storage_configs.push_back(
      device::FakeUsbDeviceInfo::CreateConfiguration(0x08, 0x06, 0x50));
  UsbDeviceInfoPtr storage_device_info = device_manager_.CreateAndAddDevice(
      0, 0, "vendor1", "storage", "123ABC", std::move(storage_configs));

  // Composite devices with both mass storage and allowed interfaces should be
  // shown.
  std::vector<device::mojom::UsbConfigurationInfoPtr> complex_configs;
  complex_configs.push_back(
      device::FakeUsbDeviceInfo::CreateConfiguration(0x08, 0x06, 0x50, 1));
  complex_configs.push_back(
      device::FakeUsbDeviceInfo::CreateConfiguration(0xff, 0x42, 0x1, 2));
  UsbDeviceInfoPtr complex_device_info = device_manager_.CreateAndAddDevice(
      0, 0, "vendor2", "complex", "456DEF", std::move(complex_configs));

  UsbChooserContext* chooser_context = GetChooserContext(profile());

  base::RunLoop loop;
  chooser_context->GetDevices(
      base::BindLambdaForTesting([&](std::vector<UsbDeviceInfoPtr> devices) {
        EXPECT_EQ(1u, devices.size());
        EXPECT_EQ(complex_device_info->product_name, devices[0]->product_name);
        loop.Quit();
      }));
  loop.Run();
}

#if BUILDFLAG(IS_CHROMEOS)
TEST_F(UsbChooserContextTest, MassStorageShownWhenDetachable) {
#if BUILDFLAG(IS_CHROMEOS_ASH)
  base::Value::List allowlist;
  base::Value::Dict ids;
  ids.Set(ash::kUsbDetachableAllowlistKeyVid, 1234);
  ids.Set(ash::kUsbDetachableAllowlistKeyPid, 1);
  allowlist.Append(std::move(ids));

  profile()->ScopedCrosSettingsTestHelper()->GetStubbedProvider()->Set(
      ash::kUsbDetachableAllowlist, base::Value(std::move(allowlist)));
#endif  // BUILDFLAG(IS_CHROMEOS_ASH)

#if BUILDFLAG(IS_CHROMEOS_LACROS)
  auto allowlist = crosapi::mojom::UsbDetachableAllowlist::New();
  auto device_id = crosapi::mojom::UsbDeviceId::New();
  device_id->has_vendor_id = true;
  device_id->vendor_id = 1234;
  device_id->has_product_id = true;
  device_id->product_id = 1;
  allowlist->usb_device_ids.push_back(std::move(device_id));

  auto params = crosapi::mojom::BrowserInitParams::New();
  params->device_settings = crosapi::mojom::DeviceSettings::New();
  params->device_settings->usb_detachable_allow_list = std::move(allowlist);
  chromeos::BrowserInitParams::SetInitParamsForTests(std::move(params));
#endif  // BUILDFLAG(IS_CHROMEOS_LACROS)

  GURL kUrl("https://www.google.com");
  const auto origin = url::Origin::Create(kUrl);

  // Mass storage devices should be hidden unless they are listed in the
  // UsbDetachableAllowlist policy.
  std::vector<device::mojom::UsbConfigurationInfoPtr> storage_configs;
  storage_configs.push_back(
      device::FakeUsbDeviceInfo::CreateConfiguration(0x08, 0x06, 0x50));
  UsbDeviceInfoPtr detachable_storage_device_info =
      device_manager_.CreateAndAddDevice(1234, 1, "vendor1",
                                         "detachable storage", "123ABC",
                                         std::move(storage_configs));

  storage_configs.clear();
  storage_configs.push_back(
      device::FakeUsbDeviceInfo::CreateConfiguration(0x08, 0x06, 0x50));
  UsbDeviceInfoPtr storage_device_info = device_manager_.CreateAndAddDevice(
      1234, 2, "vendor1", "storage", "456DEF", std::move(storage_configs));

  UsbChooserContext* chooser_context = GetChooserContext(profile());

  base::RunLoop loop;
  chooser_context->GetDevices(
      base::BindLambdaForTesting([&](std::vector<UsbDeviceInfoPtr> devices) {
        EXPECT_EQ(1u, devices.size());
        EXPECT_EQ(detachable_storage_device_info->product_name,
                  devices[0]->product_name);
        loop.Quit();
      }));
  loop.Run();
}
#endif  // BUILDFLAG(IS_CHROMEOS_ASH)

TEST_F(UsbChooserContextTest, DeviceWithNoInterfaceVisible) {
  GURL url("https://www.google.com");
  const auto origin = url::Origin::Create(url);

  std::vector<device::mojom::UsbConfigurationInfoPtr> configs;
  configs.push_back(
      device::FakeUsbDeviceInfo::CreateConfiguration(0x08, 0x06, 0x50));
  configs[0]->interfaces.clear();

  UsbDeviceInfoPtr device_info = device_manager_.CreateAndAddDevice(
      0, 0, "vendor1", "no_interface", "123ABC", std::move(configs));

  UsbChooserContext* chooser_context = GetChooserContext(profile());

  base::RunLoop loop;
  chooser_context->GetDevices(
      base::BindLambdaForTesting([&](std::vector<UsbDeviceInfoPtr> devices) {
        EXPECT_EQ(1u, devices.size());
        EXPECT_EQ(device_info->product_name, devices[0]->product_name);
        loop.Quit();
      }));
  loop.Run();
}
