blob: 591d8fdf353df18924aedfc913997d7f51d2779d [file] [log] [blame]
// 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::ReadDeprecated(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::ReadDeprecated(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::ReadDeprecated(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::ReadDeprecated(
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::ReadDeprecated(
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::ReadDeprecated(
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::ReadDeprecated(
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::ReadDeprecated(
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));
}