blob: d2b14a4f9d3a2dc1b0e6908cbabf0aa065493d69 [file] [log] [blame]
// Copyright 2021 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "chrome/browser/serial/serial_policy_allowed_ports.h"
#include "base/containers/contains.h"
#include "base/test/values_test_util.h"
#include "chrome/browser/prefs/browser_prefs.h"
#include "chrome/common/pref_names.h"
#include "components/prefs/testing_pref_service.h"
#include "content/public/test/browser_task_environment.h"
#include "services/device/public/mojom/serial.mojom.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "url/gurl.h"
#include "url/origin.h"
namespace {
using ::base::test::ParseJson;
using ::testing::UnorderedElementsAre;
device::mojom::SerialPortInfoPtr CreateUsbDevice(uint16_t vendor_id,
uint16_t product_id) {
auto port = device::mojom::SerialPortInfo::New();
port->token = base::UnguessableToken::Create();
port->has_vendor_id = true;
port->vendor_id = vendor_id;
port->has_product_id = true;
port->product_id = product_id;
return port;
}
device::mojom::SerialPortInfoPtr CreatePlatformPort() {
auto port = device::mojom::SerialPortInfo::New();
port->token = base::UnguessableToken::Create();
return port;
}
} // namespace
class SerialPolicyAllowedPortsTest : public testing::Test {
public:
SerialPolicyAllowedPortsTest() {
RegisterLocalState(local_state_.registry());
}
~SerialPolicyAllowedPortsTest() override = default;
void SetAllowAllPortsForUrlsPrefValue(const base::Value& value) {
local_state_.Set(prefs::kManagedSerialAllowAllPortsForUrls, value);
}
void SetAllowUsbDevicesForUrlsPrefValue(const base::Value& value) {
local_state_.Set(prefs::kManagedSerialAllowUsbDevicesForUrls, value);
}
void InitializePolicy() {
EXPECT_FALSE(policy_);
policy_ = std::make_unique<SerialPolicyAllowedPorts>(&local_state_);
}
protected:
SerialPolicyAllowedPorts* policy() { return policy_.get(); }
private:
content::BrowserTaskEnvironment task_environment_;
TestingPrefServiceSimple local_state_;
std::unique_ptr<SerialPolicyAllowedPorts> policy_;
};
TEST_F(SerialPolicyAllowedPortsTest, InitializeWithMissingPrefValue) {
InitializePolicy();
EXPECT_TRUE(policy()->usb_device_policy().empty());
EXPECT_TRUE(policy()->usb_vendor_policy().empty());
EXPECT_TRUE(policy()->all_ports_policy().empty());
}
TEST_F(SerialPolicyAllowedPortsTest, InitializeWithEmptyPrefValues) {
SetAllowAllPortsForUrlsPrefValue(base::Value(base::Value::Type::LIST));
SetAllowUsbDevicesForUrlsPrefValue(base::Value(base::Value::Type::LIST));
InitializePolicy();
EXPECT_TRUE(policy()->usb_device_policy().empty());
EXPECT_TRUE(policy()->usb_vendor_policy().empty());
EXPECT_TRUE(policy()->all_ports_policy().empty());
}
TEST_F(SerialPolicyAllowedPortsTest, InitializeWithPrefValues) {
constexpr char kAllPortsPolicySetting[] = R"(["https://www.youtube.com"])";
constexpr char kUsbDevicesPolicySetting[] = R"(
[
{
"devices": [
{ "vendor_id": 1234, "product_id": 5678 },
{ "vendor_id": 4321 }
],
"urls": [
"https://google.com",
"https://crbug.com"
]
}
])";
const auto kYoutubeOrigin =
url::Origin::Create(GURL("https://www.youtube.com"));
const auto kGoogleOrigin = url::Origin::Create(GURL("https://google.com"));
const auto kCrbugOrigin = url::Origin::Create(GURL("https://crbug.com"));
SetAllowAllPortsForUrlsPrefValue(ParseJson(kAllPortsPolicySetting));
SetAllowUsbDevicesForUrlsPrefValue(ParseJson(kUsbDevicesPolicySetting));
InitializePolicy();
EXPECT_EQ(1u, policy()->usb_device_policy().size());
EXPECT_EQ(1u, policy()->usb_vendor_policy().size());
EXPECT_EQ(1u, policy()->all_ports_policy().size());
EXPECT_THAT(policy()->all_ports_policy(),
UnorderedElementsAre(kYoutubeOrigin));
const auto device_key = std::make_pair(1234, 5678);
ASSERT_TRUE(base::Contains(policy()->usb_device_policy(), device_key));
EXPECT_THAT(policy()->usb_device_policy().at(device_key),
UnorderedElementsAre(kGoogleOrigin, kCrbugOrigin));
ASSERT_TRUE(base::Contains(policy()->usb_vendor_policy(), 4321));
EXPECT_THAT(policy()->usb_vendor_policy().at(4321),
UnorderedElementsAre(kGoogleOrigin, kCrbugOrigin));
auto vendor1_device = CreateUsbDevice(1234, 5678);
EXPECT_TRUE(policy()->HasPortPermission(kYoutubeOrigin, *vendor1_device));
EXPECT_TRUE(policy()->HasPortPermission(kGoogleOrigin, *vendor1_device));
EXPECT_TRUE(policy()->HasPortPermission(kCrbugOrigin, *vendor1_device));
auto vendor1_alternate_device = CreateUsbDevice(1234, 1234);
EXPECT_TRUE(
policy()->HasPortPermission(kYoutubeOrigin, *vendor1_alternate_device));
EXPECT_FALSE(
policy()->HasPortPermission(kGoogleOrigin, *vendor1_alternate_device));
EXPECT_FALSE(
policy()->HasPortPermission(kCrbugOrigin, *vendor1_alternate_device));
auto vendor2_device = CreateUsbDevice(4321, 1234);
EXPECT_TRUE(policy()->HasPortPermission(kYoutubeOrigin, *vendor2_device));
EXPECT_TRUE(policy()->HasPortPermission(kGoogleOrigin, *vendor2_device));
EXPECT_TRUE(policy()->HasPortPermission(kCrbugOrigin, *vendor2_device));
auto platform_port = CreatePlatformPort();
EXPECT_TRUE(policy()->HasPortPermission(kYoutubeOrigin, *platform_port));
EXPECT_FALSE(policy()->HasPortPermission(kGoogleOrigin, *platform_port));
EXPECT_FALSE(policy()->HasPortPermission(kCrbugOrigin, *platform_port));
}
TEST_F(SerialPolicyAllowedPortsTest,
InitializeWithMissingPrefValuesThenUpdate) {
InitializePolicy();
constexpr char kAllPortsPolicySetting[] = R"(["https://www.youtube.com"])";
constexpr char kUsbDevicesPolicySetting[] = R"(
[
{
"devices": [
{ "vendor_id": 1234, "product_id": 5678 },
{ "vendor_id": 4321 }
],
"urls": [
"https://google.com",
"https://crbug.com"
]
}
])";
const auto kYoutubeOrigin =
url::Origin::Create(GURL("https://www.youtube.com"));
const auto kGoogleOrigin = url::Origin::Create(GURL("https://google.com"));
const auto kCrbugOrigin = url::Origin::Create(GURL("https://crbug.com"));
SetAllowAllPortsForUrlsPrefValue(ParseJson(kAllPortsPolicySetting));
SetAllowUsbDevicesForUrlsPrefValue(ParseJson(kUsbDevicesPolicySetting));
EXPECT_EQ(1u, policy()->usb_device_policy().size());
EXPECT_EQ(1u, policy()->usb_vendor_policy().size());
EXPECT_EQ(1u, policy()->all_ports_policy().size());
EXPECT_THAT(policy()->all_ports_policy(),
UnorderedElementsAre(kYoutubeOrigin));
const auto device_key = std::make_pair(1234, 5678);
ASSERT_TRUE(base::Contains(policy()->usb_device_policy(), device_key));
EXPECT_THAT(policy()->usb_device_policy().at(device_key),
UnorderedElementsAre(kGoogleOrigin, kCrbugOrigin));
ASSERT_TRUE(base::Contains(policy()->usb_vendor_policy(), 4321));
EXPECT_THAT(policy()->usb_vendor_policy().at(4321),
UnorderedElementsAre(kGoogleOrigin, kCrbugOrigin));
auto vendor1_device = CreateUsbDevice(1234, 5678);
EXPECT_TRUE(policy()->HasPortPermission(kYoutubeOrigin, *vendor1_device));
EXPECT_TRUE(policy()->HasPortPermission(kGoogleOrigin, *vendor1_device));
EXPECT_TRUE(policy()->HasPortPermission(kCrbugOrigin, *vendor1_device));
auto vendor1_alternate_device = CreateUsbDevice(1234, 1234);
EXPECT_TRUE(
policy()->HasPortPermission(kYoutubeOrigin, *vendor1_alternate_device));
EXPECT_FALSE(
policy()->HasPortPermission(kGoogleOrigin, *vendor1_alternate_device));
EXPECT_FALSE(
policy()->HasPortPermission(kCrbugOrigin, *vendor1_alternate_device));
auto vendor2_device = CreateUsbDevice(4321, 1234);
EXPECT_TRUE(policy()->HasPortPermission(kYoutubeOrigin, *vendor2_device));
EXPECT_TRUE(policy()->HasPortPermission(kGoogleOrigin, *vendor2_device));
EXPECT_TRUE(policy()->HasPortPermission(kCrbugOrigin, *vendor2_device));
auto platform_port = CreatePlatformPort();
EXPECT_TRUE(policy()->HasPortPermission(kYoutubeOrigin, *platform_port));
EXPECT_FALSE(policy()->HasPortPermission(kGoogleOrigin, *platform_port));
EXPECT_FALSE(policy()->HasPortPermission(kCrbugOrigin, *platform_port));
}
TEST_F(SerialPolicyAllowedPortsTest, InitializeWithPrefValuesThenRemovePolicy) {
constexpr char kAllPortsPolicySetting[] = R"(["https://www.youtube.com"])";
constexpr char kUsbDevicesPolicySetting[] = R"(
[
{
"devices": [
{ "vendor_id": 1234, "product_id": 5678 },
{ "vendor_id": 4321 }
],
"urls": [
"https://google.com",
"https://crbug.com"
]
}
])";
SetAllowAllPortsForUrlsPrefValue(ParseJson(kAllPortsPolicySetting));
SetAllowUsbDevicesForUrlsPrefValue(ParseJson(kUsbDevicesPolicySetting));
InitializePolicy();
SetAllowAllPortsForUrlsPrefValue(base::Value(base::Value::Type::LIST));
SetAllowUsbDevicesForUrlsPrefValue(base::Value(base::Value::Type::LIST));
EXPECT_TRUE(policy()->usb_device_policy().empty());
EXPECT_TRUE(policy()->usb_vendor_policy().empty());
EXPECT_TRUE(policy()->all_ports_policy().empty());
}
TEST_F(SerialPolicyAllowedPortsTest, MultipleItemsWithOverlap) {
constexpr char kUsbDevicesPolicySetting[] = R"(
[
{
"devices": [
{ "vendor_id": 1234, "product_id": 5678 },
{ "vendor_id": 4321 }
],
"urls": [
"https://google.com",
"https://crbug.com"
]
},
{
"devices": [
{ "vendor_id": 1234 },
{ "vendor_id": 4321, "product_id": 8765 }
],
"urls": [
"https://crbug.com",
"https://www.youtube.com"
]
}
])";
const auto kGoogleOrigin = url::Origin::Create(GURL("https://google.com"));
const auto kCrbugOrigin = url::Origin::Create(GURL("https://crbug.com"));
const auto kYoutubeOrigin =
url::Origin::Create(GURL("https://www.youtube.com"));
SetAllowUsbDevicesForUrlsPrefValue(ParseJson(kUsbDevicesPolicySetting));
InitializePolicy();
EXPECT_EQ(2u, policy()->usb_device_policy().size());
EXPECT_EQ(2u, policy()->usb_vendor_policy().size());
EXPECT_EQ(0u, policy()->all_ports_policy().size());
const auto device1_key = std::make_pair(1234, 5678);
ASSERT_TRUE(base::Contains(policy()->usb_device_policy(), device1_key));
EXPECT_THAT(policy()->usb_device_policy().at(device1_key),
UnorderedElementsAre(kGoogleOrigin, kCrbugOrigin));
const auto device2_key = std::make_pair(4321, 8765);
ASSERT_TRUE(base::Contains(policy()->usb_device_policy(), device2_key));
EXPECT_THAT(policy()->usb_device_policy().at(device2_key),
UnorderedElementsAre(kCrbugOrigin, kYoutubeOrigin));
ASSERT_TRUE(base::Contains(policy()->usb_vendor_policy(), 1234));
EXPECT_THAT(policy()->usb_vendor_policy().at(1234),
UnorderedElementsAre(kCrbugOrigin, kYoutubeOrigin));
ASSERT_TRUE(base::Contains(policy()->usb_vendor_policy(), 4321));
EXPECT_THAT(policy()->usb_vendor_policy().at(4321),
UnorderedElementsAre(kGoogleOrigin, kCrbugOrigin));
auto vendor1_device1 = CreateUsbDevice(1234, 5678);
EXPECT_TRUE(policy()->HasPortPermission(kGoogleOrigin, *vendor1_device1));
EXPECT_TRUE(policy()->HasPortPermission(kCrbugOrigin, *vendor1_device1));
EXPECT_TRUE(policy()->HasPortPermission(kYoutubeOrigin, *vendor1_device1));
auto vendor1_alternate_device = CreateUsbDevice(1234, 1234);
EXPECT_FALSE(
policy()->HasPortPermission(kGoogleOrigin, *vendor1_alternate_device));
EXPECT_TRUE(
policy()->HasPortPermission(kCrbugOrigin, *vendor1_alternate_device));
EXPECT_TRUE(
policy()->HasPortPermission(kYoutubeOrigin, *vendor1_alternate_device));
auto vendor2_device = CreateUsbDevice(4321, 8765);
EXPECT_TRUE(policy()->HasPortPermission(kGoogleOrigin, *vendor2_device));
EXPECT_TRUE(policy()->HasPortPermission(kCrbugOrigin, *vendor2_device));
EXPECT_TRUE(policy()->HasPortPermission(kYoutubeOrigin, *vendor2_device));
auto vendor2_alternate_device = CreateUsbDevice(4321, 1234);
EXPECT_TRUE(
policy()->HasPortPermission(kGoogleOrigin, *vendor2_alternate_device));
EXPECT_TRUE(
policy()->HasPortPermission(kCrbugOrigin, *vendor2_alternate_device));
EXPECT_FALSE(
policy()->HasPortPermission(kYoutubeOrigin, *vendor2_alternate_device));
auto vendor3_device = CreateUsbDevice(9012, 3456);
EXPECT_FALSE(policy()->HasPortPermission(kGoogleOrigin, *vendor3_device));
EXPECT_FALSE(policy()->HasPortPermission(kCrbugOrigin, *vendor3_device));
EXPECT_FALSE(policy()->HasPortPermission(kYoutubeOrigin, *vendor3_device));
auto platform_port = CreatePlatformPort();
EXPECT_FALSE(policy()->HasPortPermission(kGoogleOrigin, *platform_port));
EXPECT_FALSE(policy()->HasPortPermission(kCrbugOrigin, *platform_port));
EXPECT_FALSE(policy()->HasPortPermission(kYoutubeOrigin, *platform_port));
}