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

#include "chrome/browser/usb/usb_policy_allowed_devices.h"

#include <string>
#include <utility>

#include "base/json/json_reader.h"
#include "chrome/test/base/testing_profile.h"
#include "components/content_settings/core/common/pref_names.h"
#include "components/prefs/pref_service.h"
#include "content/public/test/test_browser_thread_bundle.h"
#include "device/usb/public/cpp/fake_usb_device_manager.h"
#include "device/usb/public/mojom/device.mojom.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "url/gurl.h"

namespace {

class UsbPolicyAllowedDevicesTest : public testing::Test {
 public:
  UsbPolicyAllowedDevicesTest() {}
  ~UsbPolicyAllowedDevicesTest() override {}

  void SetWebUsbAllowDevicesForUrlsPrefValue(const base::Value& value) {
    profile_.GetPrefs()->Set(prefs::kManagedWebUsbAllowDevicesForUrls, value);
  }

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

  device::FakeUsbDeviceManager device_manager_;

 private:
  content::TestBrowserThreadBundle thread_bundle_;
  TestingProfile profile_;
};

}  // namespace

TEST_F(UsbPolicyAllowedDevicesTest, InitializeWithMissingPrefValue) {
  auto usb_policy_allowed_devices =
      std::make_unique<UsbPolicyAllowedDevices>(profile()->GetPrefs());

  EXPECT_TRUE(usb_policy_allowed_devices->map().empty());
}

TEST_F(UsbPolicyAllowedDevicesTest, InitializeWithExistingEmptyPrefValue) {
  base::Value pref_value(base::Value::Type::LIST);

  SetWebUsbAllowDevicesForUrlsPrefValue(pref_value);

  auto usb_policy_allowed_devices =
      std::make_unique<UsbPolicyAllowedDevices>(profile()->GetPrefs());

  EXPECT_TRUE(usb_policy_allowed_devices->map().empty());
}

namespace {

constexpr char kPolicySetting[] = R"(
    [
      {
        "devices": [
          { "vendor_id": 1234, "product_id": 5678 },
          { "vendor_id": 4321 }
        ],
        "urls": [
          "https://google.com,https://google.com",
          "https://crbug.com"
        ]
      }, {
        "devices": [{}],
        "urls": ["https://www.youtube.com"]
      }
    ])";

std::pair<GURL, GURL> MakeGURLPair(std::string requesting_url) {
  return std::make_pair(GURL(requesting_url), GURL::EmptyGURL());
}

std::pair<GURL, GURL> MakeGURLPair(std::string requesting_url,
                                   std::string embedding_url) {
  return std::make_pair(GURL(requesting_url), GURL(embedding_url));
}

}  // namespace

TEST_F(UsbPolicyAllowedDevicesTest, InitializeWithExistingPrefValue) {
  std::unique_ptr<base::Value> pref_value =
      base::JSONReader::Read(kPolicySetting);

  SetWebUsbAllowDevicesForUrlsPrefValue(*pref_value);

  auto usb_policy_allowed_devices =
      std::make_unique<UsbPolicyAllowedDevices>(profile()->GetPrefs());

  const UsbPolicyAllowedDevices::UsbDeviceIdsToUrlsMap& map =
      usb_policy_allowed_devices->map();
  EXPECT_EQ(map.size(), 3ul);

  auto device_key = std::make_pair(1234, 5678);
  ASSERT_TRUE(base::ContainsKey(map, device_key));

  const auto& first_urls = map.at(device_key);
  EXPECT_TRUE(base::ContainsKey(
      first_urls, MakeGURLPair("https://google.com", "https://google.com")));
  EXPECT_TRUE(base::ContainsKey(first_urls, MakeGURLPair("https://crbug.com")));

  device_key = std::make_pair(4321, -1);
  ASSERT_TRUE(base::ContainsKey(map, device_key));

  const auto& second_urls = map.at(device_key);
  EXPECT_TRUE(base::ContainsKey(
      second_urls, MakeGURLPair("https://google.com", "https://google.com")));
  EXPECT_TRUE(
      base::ContainsKey(second_urls, MakeGURLPair("https://crbug.com")));

  device_key = std::make_pair(-1, -1);
  ASSERT_TRUE(base::ContainsKey(map, device_key));

  const auto& third_urls = map.at(device_key);
  EXPECT_TRUE(
      base::ContainsKey(third_urls, MakeGURLPair("https://www.youtube.com")));
}

TEST_F(UsbPolicyAllowedDevicesTest,
       InitializeWithMissingPolicyThenUpdatePolicy) {
  auto usb_policy_allowed_devices =
      std::make_unique<UsbPolicyAllowedDevices>(profile()->GetPrefs());
  EXPECT_TRUE(usb_policy_allowed_devices->map().empty());

  // Ensure that the allowed devices can be dynamically updated.
  std::unique_ptr<base::Value> pref_value =
      base::JSONReader::Read(kPolicySetting);

  SetWebUsbAllowDevicesForUrlsPrefValue(*pref_value);

  const UsbPolicyAllowedDevices::UsbDeviceIdsToUrlsMap& map =
      usb_policy_allowed_devices->map();
  EXPECT_EQ(map.size(), 3ul);

  auto device_key = std::make_pair(1234, 5678);
  ASSERT_TRUE(base::ContainsKey(map, device_key));

  const auto& first_urls = map.at(device_key);
  EXPECT_TRUE(base::ContainsKey(
      first_urls, MakeGURLPair("https://google.com", "https://google.com")));
  EXPECT_TRUE(base::ContainsKey(first_urls, MakeGURLPair("https://crbug.com")));

  device_key = std::make_pair(4321, -1);
  ASSERT_TRUE(base::ContainsKey(map, device_key));

  const auto& second_urls = map.at(device_key);
  EXPECT_TRUE(base::ContainsKey(
      second_urls, MakeGURLPair("https://google.com", "https://google.com")));
  EXPECT_TRUE(
      base::ContainsKey(second_urls, MakeGURLPair("https://crbug.com")));

  device_key = std::make_pair(-1, -1);
  ASSERT_TRUE(base::ContainsKey(map, device_key));

  const auto& third_urls = map.at(device_key);
  EXPECT_TRUE(
      base::ContainsKey(third_urls, MakeGURLPair("https://www.youtube.com")));
}

TEST_F(UsbPolicyAllowedDevicesTest,
       InitializeWithExistingPolicyThenRemovePolicy) {
  std::unique_ptr<base::Value> pref_value =
      base::JSONReader::Read(kPolicySetting);

  SetWebUsbAllowDevicesForUrlsPrefValue(*pref_value);

  auto usb_policy_allowed_devices =
      std::make_unique<UsbPolicyAllowedDevices>(profile()->GetPrefs());

  const UsbPolicyAllowedDevices::UsbDeviceIdsToUrlsMap& map =
      usb_policy_allowed_devices->map();
  EXPECT_EQ(map.size(), 3ul);

  auto device_key = std::make_pair(1234, 5678);
  ASSERT_TRUE(base::ContainsKey(map, device_key));

  const auto& first_urls = map.at(device_key);
  EXPECT_TRUE(base::ContainsKey(
      first_urls, MakeGURLPair("https://google.com", "https://google.com")));
  EXPECT_TRUE(base::ContainsKey(first_urls, MakeGURLPair("https://crbug.com")));

  device_key = std::make_pair(4321, -1);
  ASSERT_TRUE(base::ContainsKey(map, device_key));

  const auto& second_urls = map.at(device_key);
  EXPECT_TRUE(base::ContainsKey(
      second_urls, MakeGURLPair("https://google.com", "https://google.com")));
  EXPECT_TRUE(
      base::ContainsKey(second_urls, MakeGURLPair("https://crbug.com")));

  device_key = std::make_pair(-1, -1);
  ASSERT_TRUE(base::ContainsKey(map, device_key));

  const auto& third_urls = map.at(device_key);
  EXPECT_TRUE(
      base::ContainsKey(third_urls, MakeGURLPair("https://www.youtube.com")));

  // Ensure that the allowed devices can be removed dynamically.
  pref_value.reset(new base::Value(base::Value::Type::LIST));
  SetWebUsbAllowDevicesForUrlsPrefValue(*pref_value);

  EXPECT_TRUE(usb_policy_allowed_devices->map().empty());
}

namespace {

constexpr char kPolicySettingWithEntriesContainingDuplicateDevices[] = R"(
    [
      {
        "devices": [{ "vendor_id": 1234, "product_id": 5678 }],
        "urls": [
          "https://google.com",
          "https://crbug.com"
        ]
      }, {
        "devices": [{ "vendor_id": 1234, "product_id": 5678 }],
        "urls": ["https://www.youtube.com"]
      }
    ])";

}  // namespace

TEST_F(UsbPolicyAllowedDevicesTest,
       InitializeWithExistingPrefValueContainingDuplicateDevices) {
  std::unique_ptr<base::Value> pref_value = base::JSONReader::Read(
      kPolicySettingWithEntriesContainingDuplicateDevices);

  SetWebUsbAllowDevicesForUrlsPrefValue(*pref_value);

  auto usb_policy_allowed_devices =
      std::make_unique<UsbPolicyAllowedDevices>(profile()->GetPrefs());

  const UsbPolicyAllowedDevices::UsbDeviceIdsToUrlsMap& map =
      usb_policy_allowed_devices->map();
  ASSERT_EQ(map.size(), 1ul);

  auto device_key = std::make_pair(1234, 5678);
  ASSERT_TRUE(base::ContainsKey(map, device_key));

  // Ensure a device has all of the URL patterns allowed to access it.
  const auto& urls = map.at(device_key);
  EXPECT_TRUE(base::ContainsKey(urls, MakeGURLPair("https://google.com")));
  EXPECT_TRUE(base::ContainsKey(urls, MakeGURLPair("https://crbug.com")));
  EXPECT_TRUE(base::ContainsKey(urls, MakeGURLPair("https://www.youtube.com")));
}

namespace {

constexpr char kPolicySettingWithEntriesMatchingMultipleDevices[] = R"(
    [
      {
        "devices": [{ "vendor_id": 1234, "product_id": 5678 }],
        "urls": ["https://google.com"]
      }, {
        "devices": [{ "vendor_id": 1234 }],
        "urls": ["https://www.youtube.com"]
      }, {
        "devices": [{}],
        "urls": ["https://chromium.org"]
      }
    ])";

}  // namespace

TEST_F(UsbPolicyAllowedDevicesTest, IsDeviceAllowed) {
  std::unique_ptr<base::Value> pref_value =
      base::JSONReader::Read(kPolicySettingWithEntriesMatchingMultipleDevices);

  SetWebUsbAllowDevicesForUrlsPrefValue(*pref_value);

  auto usb_policy_allowed_devices =
      std::make_unique<UsbPolicyAllowedDevices>(profile()->GetPrefs());

  const GURL kGoogleOrigin("https://google.com");
  const GURL kYoutubeOrigin("https://www.youtube.com");
  const GURL kChromiumOrigin("https://chromium.org");
  const GURL kAndroidOrigin("https://android.com");

  auto specific_device_info = device_manager_.CreateAndAddDevice(
      1234, 5678, "Google", "Gizmo", "123ABC");
  auto vendor_device_info = device_manager_.CreateAndAddDevice(
      1234, 8765, "Google", "Gizmo", "ABC123");
  auto unrelated_device_info = device_manager_.CreateAndAddDevice(
      4321, 8765, "Chrome", "Gizmo", "987ZYX");

  // Check that the specific device is allowed for https://google.com embedded
  // in any origin, but not any other device.
  EXPECT_TRUE(usb_policy_allowed_devices->IsDeviceAllowed(
      kGoogleOrigin, kGoogleOrigin, *specific_device_info));
  EXPECT_TRUE(usb_policy_allowed_devices->IsDeviceAllowed(
      kGoogleOrigin, kAndroidOrigin, *specific_device_info));
  EXPECT_FALSE(usb_policy_allowed_devices->IsDeviceAllowed(
      kGoogleOrigin, kGoogleOrigin, *vendor_device_info));
  EXPECT_FALSE(usb_policy_allowed_devices->IsDeviceAllowed(
      kGoogleOrigin, kAndroidOrigin, *vendor_device_info));
  EXPECT_FALSE(usb_policy_allowed_devices->IsDeviceAllowed(
      kGoogleOrigin, kGoogleOrigin, *unrelated_device_info));
  EXPECT_FALSE(usb_policy_allowed_devices->IsDeviceAllowed(
      kGoogleOrigin, kAndroidOrigin, *unrelated_device_info));

  // Check that devices with a vendor ID of 1234 are allowed for
  // https://www.youtube.com embedded in any origin, but not an unrelated
  // device.
  EXPECT_TRUE(usb_policy_allowed_devices->IsDeviceAllowed(
      kYoutubeOrigin, kYoutubeOrigin, *specific_device_info));
  EXPECT_TRUE(usb_policy_allowed_devices->IsDeviceAllowed(
      kYoutubeOrigin, kAndroidOrigin, *specific_device_info));
  EXPECT_TRUE(usb_policy_allowed_devices->IsDeviceAllowed(
      kYoutubeOrigin, kYoutubeOrigin, *vendor_device_info));
  EXPECT_TRUE(usb_policy_allowed_devices->IsDeviceAllowed(
      kYoutubeOrigin, kAndroidOrigin, *vendor_device_info));
  EXPECT_FALSE(usb_policy_allowed_devices->IsDeviceAllowed(
      kYoutubeOrigin, kYoutubeOrigin, *unrelated_device_info));
  EXPECT_FALSE(usb_policy_allowed_devices->IsDeviceAllowed(
      kYoutubeOrigin, kAndroidOrigin, *unrelated_device_info));

  // Check that any device is allowed for https://chromium.org embedded in any
  // origin.
  EXPECT_TRUE(usb_policy_allowed_devices->IsDeviceAllowed(
      kChromiumOrigin, kChromiumOrigin, *specific_device_info));
  EXPECT_TRUE(usb_policy_allowed_devices->IsDeviceAllowed(
      kChromiumOrigin, kAndroidOrigin, *specific_device_info));
  EXPECT_TRUE(usb_policy_allowed_devices->IsDeviceAllowed(
      kChromiumOrigin, kChromiumOrigin, *vendor_device_info));
  EXPECT_TRUE(usb_policy_allowed_devices->IsDeviceAllowed(
      kChromiumOrigin, kAndroidOrigin, *vendor_device_info));
  EXPECT_TRUE(usb_policy_allowed_devices->IsDeviceAllowed(
      kChromiumOrigin, kChromiumOrigin, *unrelated_device_info));
  EXPECT_TRUE(usb_policy_allowed_devices->IsDeviceAllowed(
      kChromiumOrigin, kAndroidOrigin, *unrelated_device_info));
}

TEST_F(UsbPolicyAllowedDevicesTest, IsDeviceAllowedForUrlsNotInPref) {
  std::unique_ptr<base::Value> pref_value =
      base::JSONReader::Read(kPolicySettingWithEntriesMatchingMultipleDevices);

  SetWebUsbAllowDevicesForUrlsPrefValue(*pref_value);

  auto usb_policy_allowed_devices =
      std::make_unique<UsbPolicyAllowedDevices>(profile()->GetPrefs());

  const GURL origins[] = {GURL("https://evil.com"),
                          GURL("https://very.evil.com"),
                          GURL("https://chromium.deceptive.org")};

  auto device_info = device_manager_.CreateAndAddDevice(1234, 5678, "Google",
                                                        "Gizmo", "123ABC");
  for (const GURL& requesting_origin : origins) {
    for (const GURL& embedding_origin : origins) {
      EXPECT_FALSE(usb_policy_allowed_devices->IsDeviceAllowed(
          requesting_origin, embedding_origin, *device_info));
    }
  }
}

TEST_F(UsbPolicyAllowedDevicesTest, IsDeviceAllowedForDeviceNotInPref) {
  std::unique_ptr<base::Value> pref_value =
      base::JSONReader::Read(kPolicySettingWithEntriesMatchingMultipleDevices);

  SetWebUsbAllowDevicesForUrlsPrefValue(*pref_value);

  auto usb_policy_allowed_devices =
      std::make_unique<UsbPolicyAllowedDevices>(profile()->GetPrefs());

  const GURL origins[] = {GURL("https://google.com"),
                          GURL("https://www.youtube.com")};

  auto device_info = device_manager_.CreateAndAddDevice(4321, 8765, "Google",
                                                        "Gizmo", "123ABC");
  for (const GURL& requesting_origin : origins) {
    for (const GURL& embedding_origin : origins) {
      EXPECT_FALSE(usb_policy_allowed_devices->IsDeviceAllowed(
          requesting_origin, embedding_origin, *device_info));
    }
  }
}

namespace {

constexpr char kPolicySettingWithUrlContainingEmbeddingOrigin[] = R"(
    [
      {
        "devices": [{ "vendor_id": 1234, "product_id": 5678 }],
        "urls": [
          "https://requesting.com,https://embedding.com"
        ]
      }
    ])";

}  // namespace

TEST_F(UsbPolicyAllowedDevicesTest,
       IsDeviceAllowedForUrlContainingEmbeddingOrigin) {
  std::unique_ptr<base::Value> pref_value =
      base::JSONReader::Read(kPolicySettingWithUrlContainingEmbeddingOrigin);

  SetWebUsbAllowDevicesForUrlsPrefValue(*pref_value);

  auto usb_policy_allowed_devices =
      std::make_unique<UsbPolicyAllowedDevices>(profile()->GetPrefs());

  const GURL requesting_origin("https://requesting.com");
  const GURL embedding_origin("https://embedding.com");

  auto device_info = device_manager_.CreateAndAddDevice(1234, 5678, "Google",
                                                        "Gizmo", "123ABC");
  EXPECT_TRUE(usb_policy_allowed_devices->IsDeviceAllowed(
      requesting_origin, embedding_origin, *device_info));
  EXPECT_FALSE(usb_policy_allowed_devices->IsDeviceAllowed(
      embedding_origin, requesting_origin, *device_info));
  EXPECT_FALSE(usb_policy_allowed_devices->IsDeviceAllowed(
      requesting_origin, requesting_origin, *device_info));
  EXPECT_FALSE(usb_policy_allowed_devices->IsDeviceAllowed(
      embedding_origin, embedding_origin, *device_info));
}
