webhid: Add policies for granting device permissions
This CL adds enterprise policies to automatically grant access
to HID devices on specific origins.
Three new policies are added. The WebHidAllowAllDevicesForUrls policy
automatically grants access for any device to a list of origins
specified by the policy. The WebHidAllowDevicesForUrls policy grants
access for devices with vendor and product IDs matching the patterns
specified by the policy. The WebHidAllowDevicesWithHidUsagesForUrls
policy grants access for devices containing top-level collections with
HID usages matching the patterns specified by the policy.
Bug: 1049825
Change-Id: Ie2d7987e44bfda06b0c9120a13fc5a7efefcd4b6
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3235159
Reviewed-by: Reilly Grant <[email protected]>
Reviewed-by: Dominic Battré <[email protected]>
Reviewed-by: Pavol Marko <[email protected]>
Commit-Queue: Matt Reynolds <[email protected]>
Cr-Commit-Position: refs/heads/main@{#967146}
diff --git a/chrome/browser/BUILD.gn b/chrome/browser/BUILD.gn
index 21973c8..472168c 100644
--- a/chrome/browser/BUILD.gn
+++ b/chrome/browser/BUILD.gn
@@ -3870,6 +3870,8 @@
"hid/hid_chooser_context.h",
"hid/hid_chooser_context_factory.cc",
"hid/hid_chooser_context_factory.h",
+ "hid/hid_policy_allowed_devices.cc",
+ "hid/hid_policy_allowed_devices.h",
"hid/web_hid_histograms.cc",
"hid/web_hid_histograms.h",
"icon_transcoder/svg_icon_transcoder.cc",
@@ -4074,6 +4076,8 @@
"policy/local_sync_policy_handler.h",
"policy/managed_account_policy_handler.cc",
"policy/managed_account_policy_handler.h",
+ "policy/webhid_device_policy_handler.cc",
+ "policy/webhid_device_policy_handler.h",
"prefetch/zero_suggest_prefetch/zero_suggest_prefetch_tab_helper.cc",
"prefetch/zero_suggest_prefetch/zero_suggest_prefetch_tab_helper.h",
"privacy_sandbox/generated_floc_pref.cc",
diff --git a/chrome/browser/hid/hid_policy_allowed_devices.cc b/chrome/browser/hid/hid_policy_allowed_devices.cc
new file mode 100644
index 0000000..af35e2d
--- /dev/null
+++ b/chrome/browser/hid/hid_policy_allowed_devices.cc
@@ -0,0 +1,17 @@
+// Copyright 2022 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/hid/hid_policy_allowed_devices.h"
+
+#include "chrome/common/pref_names.h"
+#include "components/prefs/pref_registry_simple.h"
+
+// static
+void HidPolicyAllowedDevices::RegisterLocalStatePrefs(
+ PrefRegistrySimple* registry) {
+ registry->RegisterListPref(prefs::kManagedWebHidAllowAllDevicesForUrls);
+ registry->RegisterListPref(prefs::kManagedWebHidAllowDevicesForUrls);
+ registry->RegisterListPref(
+ prefs::kManagedWebHidAllowDevicesWithHidUsagesForUrls);
+}
diff --git a/chrome/browser/hid/hid_policy_allowed_devices.h b/chrome/browser/hid/hid_policy_allowed_devices.h
new file mode 100644
index 0000000..9dba927
--- /dev/null
+++ b/chrome/browser/hid/hid_policy_allowed_devices.h
@@ -0,0 +1,16 @@
+// Copyright 2022 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.
+
+#ifndef CHROME_BROWSER_HID_HID_POLICY_ALLOWED_DEVICES_H_
+#define CHROME_BROWSER_HID_HID_POLICY_ALLOWED_DEVICES_H_
+
+class PrefRegistrySimple;
+
+// TODO(crbug.com/1049825): Implement HidPolicyAllowedDevices
+class HidPolicyAllowedDevices {
+ public:
+ static void RegisterLocalStatePrefs(PrefRegistrySimple* registry);
+};
+
+#endif // CHROME_BROWSER_HID_HID_POLICY_ALLOWED_DEVICES_H_
diff --git a/chrome/browser/policy/configuration_policy_handler_list_factory.cc b/chrome/browser/policy/configuration_policy_handler_list_factory.cc
index 61e52a3..8377e72c 100644
--- a/chrome/browser/policy/configuration_policy_handler_list_factory.cc
+++ b/chrome/browser/policy/configuration_policy_handler_list_factory.cc
@@ -33,6 +33,7 @@
#include "chrome/browser/policy/homepage_location_policy_handler.h"
#include "chrome/browser/policy/javascript_policy_handler.h"
#include "chrome/browser/policy/network_prediction_policy_handler.h"
+#include "chrome/browser/policy/webhid_device_policy_handler.h"
#include "chrome/browser/policy/webusb_allow_devices_for_urls_policy_handler.h"
#include "chrome/browser/profiles/force_safe_search_policy_handler.h"
#include "chrome/browser/profiles/force_youtube_safety_mode_policy_handler.h"
@@ -630,6 +631,9 @@
{ key::kWebHidBlockedForUrls,
prefs::kManagedWebHidBlockedForUrls,
base::Value::Type::LIST },
+ { key::kWebHidAllowAllDevicesForUrls,
+ prefs::kManagedWebHidAllowAllDevicesForUrls,
+ base::Value::Type::LIST },
{ key::kBrowserAddPersonEnabled,
prefs::kBrowserAddPersonEnabled,
base::Value::Type::BOOLEAN },
@@ -1683,6 +1687,12 @@
SCHEMA_ALLOW_UNKNOWN,
SimpleSchemaValidatingPolicyHandler::RECOMMENDED_PROHIBITED,
SimpleSchemaValidatingPolicyHandler::MANDATORY_ALLOWED));
+ handlers->AddHandler(std::make_unique<WebHidDevicePolicyHandler>(
+ key::kWebHidAllowDevicesForUrls, prefs::kManagedWebHidAllowDevicesForUrls,
+ chrome_schema));
+ handlers->AddHandler(std::make_unique<WebHidDevicePolicyHandler>(
+ key::kWebHidAllowDevicesWithHidUsagesForUrls,
+ prefs::kManagedWebHidAllowDevicesWithHidUsagesForUrls, chrome_schema));
handlers->AddHandler(
std::make_unique<ManagedAccountRestrictionsPolicyHandler>(chrome_schema));
#endif // !BUILDFLAG(IS_ANDROID)
diff --git a/chrome/browser/policy/webhid_device_policy_handler.cc b/chrome/browser/policy/webhid_device_policy_handler.cc
new file mode 100644
index 0000000..60c880c
--- /dev/null
+++ b/chrome/browser/policy/webhid_device_policy_handler.cc
@@ -0,0 +1,91 @@
+// Copyright 2022 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/policy/webhid_device_policy_handler.h"
+
+#include <memory>
+#include <string>
+#include <utility>
+#include <vector>
+
+#include "base/strings/stringprintf.h"
+#include "base/values.h"
+#include "chrome/common/pref_names.h"
+#include "components/content_settings/core/common/pref_names.h"
+#include "components/policy/core/browser/policy_error_map.h"
+#include "components/policy/core/common/policy_map.h"
+#include "components/policy/policy_constants.h"
+#include "components/prefs/pref_value_map.h"
+#include "url/gurl.h"
+
+namespace policy {
+
+namespace {
+
+constexpr char kUrlsKey[] = "urls";
+
+} // namespace
+
+WebHidDevicePolicyHandler::WebHidDevicePolicyHandler(
+ const char* policy_key,
+ base::StringPiece pref_name,
+ const Schema& chrome_schema)
+ : SchemaValidatingPolicyHandler(
+ policy_key,
+ chrome_schema.GetKnownProperty(policy_key),
+ SchemaOnErrorStrategy::SCHEMA_ALLOW_UNKNOWN_AND_INVALID_LIST_ENTRY),
+ pref_name_(pref_name) {}
+
+WebHidDevicePolicyHandler::~WebHidDevicePolicyHandler() = default;
+
+bool WebHidDevicePolicyHandler::CheckPolicySettings(const PolicyMap& policies,
+ PolicyErrorMap* errors) {
+ const base::Value* value = policies.GetValue(policy_name());
+ if (!value)
+ return true;
+
+ if (!SchemaValidatingPolicyHandler::CheckPolicySettings(policies, errors))
+ return false;
+
+ int item_index = 0;
+ for (const auto& item : value->GetList()) {
+ int url_index = 0;
+ auto* urls_list = item.FindKeyOfType(kUrlsKey, base::Value::Type::LIST);
+ if (!urls_list)
+ continue;
+
+ for (const auto& url_value : urls_list->GetList()) {
+ DCHECK(url_value.is_string());
+ GURL url(url_value.GetString());
+ // If `url` is invalid, emit an error but do not prevent the policy from
+ // being applied.
+ if (errors && !url.is_valid()) {
+ std::string error_path = base::StringPrintf(
+ "items[%d].%s.items[%d]", item_index, kUrlsKey, url_index);
+ std::string error = base::StringPrintf("Invalid URL: %s",
+ url_value.GetString().c_str());
+ errors->AddError(policy_name(), error_path, error);
+ }
+ ++url_index;
+ }
+ ++item_index;
+ }
+
+ return true;
+}
+
+void WebHidDevicePolicyHandler::ApplyPolicySettings(const PolicyMap& policies,
+ PrefValueMap* prefs) {
+ std::unique_ptr<base::Value> value;
+ if (!CheckAndGetValue(policies, nullptr, &value))
+ return;
+
+ if (!value || !value->is_list())
+ return;
+
+ prefs->SetValue(pref_name_,
+ base::Value::FromUniquePtrValue(std::move(value)));
+}
+
+} // namespace policy
diff --git a/chrome/browser/policy/webhid_device_policy_handler.h b/chrome/browser/policy/webhid_device_policy_handler.h
new file mode 100644
index 0000000..0568709a
--- /dev/null
+++ b/chrome/browser/policy/webhid_device_policy_handler.h
@@ -0,0 +1,40 @@
+// Copyright 2022 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.
+
+#ifndef CHROME_BROWSER_POLICY_WEBHID_DEVICE_POLICY_HANDLER_H_
+#define CHROME_BROWSER_POLICY_WEBHID_DEVICE_POLICY_HANDLER_H_
+
+#include "components/policy/core/browser/configuration_policy_handler.h"
+
+class PrefValueMap;
+
+namespace policy {
+
+class PolicyMap;
+
+// Handles the WebHidAllowDevicesForUrls and
+// WebHidAllowDevicesWithHidUsagesForUrls policies.
+class WebHidDevicePolicyHandler : public SchemaValidatingPolicyHandler {
+ public:
+ explicit WebHidDevicePolicyHandler(const char* policy_key,
+ base::StringPiece pref_name,
+ const Schema& schema);
+ WebHidDevicePolicyHandler(const WebHidDevicePolicyHandler&) = delete;
+ WebHidDevicePolicyHandler& operator=(const WebHidDevicePolicyHandler&) =
+ delete;
+ ~WebHidDevicePolicyHandler() override;
+
+ // ConfigurationPolicyHandler implementation:
+ bool CheckPolicySettings(const PolicyMap& policies,
+ PolicyErrorMap* error) override;
+ void ApplyPolicySettings(const PolicyMap& policies,
+ PrefValueMap* prefs) override;
+
+ private:
+ const std::string pref_name_;
+};
+
+} // namespace policy
+
+#endif // CHROME_BROWSER_POLICY_WEBHID_DEVICE_POLICY_HANDLER_H_
diff --git a/chrome/browser/policy/webhid_device_policy_handler_unittest.cc b/chrome/browser/policy/webhid_device_policy_handler_unittest.cc
new file mode 100644
index 0000000..5d48882
--- /dev/null
+++ b/chrome/browser/policy/webhid_device_policy_handler_unittest.cc
@@ -0,0 +1,883 @@
+// Copyright 2022 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/policy/webhid_device_policy_handler.h"
+
+#include <memory>
+#include <utility>
+
+#include "base/json/json_reader.h"
+#include "base/strings/string_util.h"
+#include "chrome/common/pref_names.h"
+#include "components/policy/core/browser/configuration_policy_pref_store.h"
+#include "components/policy/core/browser/configuration_policy_pref_store_test.h"
+#include "components/policy/core/browser/policy_error_map.h"
+#include "components/policy/core/common/policy_map.h"
+#include "components/policy/core/common/policy_types.h"
+#include "components/policy/core/common/schema.h"
+#include "components/policy/policy_constants.h"
+
+namespace policy {
+
+namespace {
+
+using ::testing::WithParamInterface;
+
+constexpr char kDevicesKey[] = "devices";
+constexpr char kUsagesKey[] = "usages";
+constexpr char kUrlsKey[] = "urls";
+constexpr char kVendorIdKey[] = "vendor_id";
+constexpr char kProductIdKey[] = "product_id";
+constexpr char kUsagePageKey[] = "usage_page";
+constexpr char kUsageKey[] = "usage";
+
+absl::optional<base::Value> ReadJson(base::StringPiece json) {
+ auto result = base::JSONReader::ReadAndReturnValueWithError(json);
+ EXPECT_TRUE(result.value) << result.error_message;
+ return std::move(result.value);
+}
+
+} // namespace
+
+class WebHidDevicePolicyHandlerTest : public ConfigurationPolicyPrefStoreTest {
+ public:
+ WebHidDevicePolicyHandlerTest() = default;
+ WebHidDevicePolicyHandlerTest(const WebHidDevicePolicyHandlerTest&) = delete;
+ WebHidDevicePolicyHandlerTest& operator=(
+ const WebHidDevicePolicyHandlerTest&) = delete;
+ ~WebHidDevicePolicyHandlerTest() override = default;
+
+ protected:
+ SchemaValidatingPolicyHandler* AddHandler(const char* policy_name) {
+ auto handler = CreateHandler(policy_name);
+ EXPECT_TRUE(handler) << "no policy handler for " << policy_name;
+ if (!handler)
+ return nullptr;
+
+ auto* handler_ptr = handler.get();
+ handler_list_.AddHandler(std::move(handler));
+ return handler_ptr;
+ }
+
+ private:
+ // Returns the appropriate handler for `policy_name`, which must be a
+ // `policy::key::` constant.
+ std::unique_ptr<SchemaValidatingPolicyHandler> CreateHandler(
+ const char* policy_name) {
+ Schema chrome_schema = Schema::Wrap(GetChromeSchemaData());
+ if (policy_name == key::kWebHidAllowDevicesForUrls) {
+ return std::make_unique<WebHidDevicePolicyHandler>(
+ key::kWebHidAllowDevicesForUrls,
+ prefs::kManagedWebHidAllowDevicesForUrls, chrome_schema);
+ }
+ if (policy_name == key::kWebHidAllowDevicesWithHidUsagesForUrls) {
+ return std::make_unique<WebHidDevicePolicyHandler>(
+ key::kWebHidAllowDevicesWithHidUsagesForUrls,
+ prefs::kManagedWebHidAllowDevicesWithHidUsagesForUrls, chrome_schema);
+ }
+ return nullptr;
+ }
+};
+
+namespace {
+
+constexpr uint16_t kTestVendorId1 = 1234;
+constexpr uint16_t kTestVendorId2 = 4321;
+constexpr uint16_t kTestVendorId3 = 2000;
+
+constexpr uint16_t kTestProductId = 5678;
+
+constexpr uint16_t kTestUsagePage1 = 1;
+constexpr uint16_t kTestUsagePage2 = 2;
+constexpr uint16_t kTestUsagePage3 = 3;
+
+constexpr uint16_t kTestUsage = 4;
+
+constexpr char kAllowDevicesForUrls[] = R"(
+ [
+ {
+ "devices": [
+ {
+ "vendor_id": 1234,
+ "product_id": 5678
+ },
+ {
+ "vendor_id": 4321
+ }
+ ],
+ "urls": [
+ "https://origin1",
+ "https://origin2"
+ ]
+ }, {
+ "devices": [
+ {
+ "vendor_id": 2000
+ }
+ ],
+ "urls": [
+ "https://origin3"
+ ]
+ }
+ ])";
+
+constexpr char kAllowDevicesWithHidUsagesForUrls[] = R"(
+ [
+ {
+ "usages": [
+ {
+ "usage_page": 1,
+ "usage": 4
+ },
+ {
+ "usage_page": 2
+ }
+ ],
+ "urls": [
+ "https://origin1",
+ "https://origin2"
+ ]
+ }, {
+ "usages": [
+ {
+ "usage_page": 3
+ }
+ ],
+ "urls": [
+ "https://origin3"
+ ]
+ }
+ ])";
+
+} // namespace
+
+TEST_F(WebHidDevicePolicyHandlerTest, CheckPolicySettingsWithDevicePolicy) {
+ auto* handler = AddHandler(key::kWebHidAllowDevicesForUrls);
+
+ PolicyMap policy;
+ PolicyErrorMap errors;
+ policy.Set(
+ key::kWebHidAllowDevicesForUrls, PolicyLevel::POLICY_LEVEL_MANDATORY,
+ PolicyScope::POLICY_SCOPE_MACHINE, PolicySource::POLICY_SOURCE_CLOUD,
+ ReadJson(kAllowDevicesForUrls), /*external_data_fetcher=*/nullptr);
+ ASSERT_TRUE(errors.empty());
+ EXPECT_TRUE(handler->CheckPolicySettings(policy, &errors));
+ EXPECT_TRUE(errors.empty());
+}
+
+TEST_F(WebHidDevicePolicyHandlerTest, CheckPolicySettingsWithUsagePolicy) {
+ auto* handler = AddHandler(key::kWebHidAllowDevicesWithHidUsagesForUrls);
+
+ PolicyMap policy;
+ PolicyErrorMap errors;
+ policy.Set(key::kWebHidAllowDevicesWithHidUsagesForUrls,
+ PolicyLevel::POLICY_LEVEL_MANDATORY,
+ PolicyScope::POLICY_SCOPE_MACHINE,
+ PolicySource::POLICY_SOURCE_CLOUD,
+ ReadJson(kAllowDevicesWithHidUsagesForUrls),
+ /*external_data_fetcher=*/nullptr);
+ ASSERT_TRUE(errors.empty());
+ EXPECT_TRUE(handler->CheckPolicySettings(policy, &errors));
+ EXPECT_TRUE(errors.empty());
+}
+
+TEST_F(WebHidDevicePolicyHandlerTest, ApplyPolicySettingsWithDevicePolicy) {
+ AddHandler(key::kWebHidAllowDevicesForUrls);
+ EXPECT_FALSE(store_->GetValue(prefs::kManagedWebHidAllowDevicesForUrls,
+ /*result=*/nullptr));
+
+ PolicyMap policy;
+ policy.Set(
+ key::kWebHidAllowDevicesForUrls, PolicyLevel::POLICY_LEVEL_MANDATORY,
+ PolicyScope::POLICY_SCOPE_MACHINE, PolicySource::POLICY_SOURCE_CLOUD,
+ ReadJson(kAllowDevicesForUrls), nullptr);
+ UpdateProviderPolicy(policy);
+
+ const base::Value* pref_value = nullptr;
+ EXPECT_TRUE(
+ store_->GetValue(prefs::kManagedWebHidAllowDevicesForUrls, &pref_value));
+ ASSERT_TRUE(pref_value);
+ ASSERT_TRUE(pref_value->is_list());
+
+ // Ensure that the kManagedWebHidAllowDevicesForUrls pref is set correctly.
+ const auto& list = pref_value->GetList();
+ ASSERT_EQ(2ul, list.size());
+
+ // Check the first item's devices list.
+ const base::Value* devices = list[0].FindKey(kDevicesKey);
+ ASSERT_TRUE(devices);
+
+ const auto& first_devices_list = devices->GetList();
+ ASSERT_EQ(2ul, first_devices_list.size());
+
+ const base::Value* vendor_id = first_devices_list[0].FindKey(kVendorIdKey);
+ ASSERT_TRUE(vendor_id);
+ EXPECT_EQ(base::Value(kTestVendorId1), *vendor_id);
+
+ const base::Value* product_id = first_devices_list[0].FindKey(kProductIdKey);
+ ASSERT_TRUE(product_id);
+ EXPECT_EQ(base::Value(kTestProductId), *product_id);
+
+ vendor_id = first_devices_list[1].FindKey(kVendorIdKey);
+ ASSERT_TRUE(vendor_id);
+ EXPECT_EQ(base::Value(kTestVendorId2), *vendor_id);
+
+ product_id = first_devices_list[1].FindKey(kProductIdKey);
+ EXPECT_FALSE(product_id);
+
+ // Check the first item's urls list.
+ const base::Value* urls = list[0].FindKey(kUrlsKey);
+ ASSERT_TRUE(urls);
+ ASSERT_EQ(2ul, urls->GetList().size());
+ EXPECT_EQ(base::Value("https://origin1"), urls->GetList()[0]);
+ EXPECT_EQ(base::Value("https://origin2"), urls->GetList()[1]);
+
+ // Check the second item's devices list.
+ devices = list[1].FindKey(kDevicesKey);
+ ASSERT_TRUE(devices);
+
+ const auto& second_devices_list = devices->GetList();
+ ASSERT_EQ(1ul, second_devices_list.size());
+
+ vendor_id = second_devices_list[0].FindKey(kVendorIdKey);
+ ASSERT_TRUE(vendor_id);
+ EXPECT_EQ(base::Value(kTestVendorId3), *vendor_id);
+
+ product_id = second_devices_list[0].FindKey(kProductIdKey);
+ EXPECT_FALSE(product_id);
+
+ // Check the second item's urls list.
+ urls = list[1].FindKey(kUrlsKey);
+ ASSERT_TRUE(urls);
+ ASSERT_EQ(1ul, urls->GetList().size());
+ EXPECT_EQ(base::Value("https://origin3"), urls->GetList()[0]);
+}
+
+TEST_F(WebHidDevicePolicyHandlerTest, ApplyPolicySettingsWithUsagePolicy) {
+ AddHandler(key::kWebHidAllowDevicesWithHidUsagesForUrls);
+ EXPECT_FALSE(
+ store_->GetValue(prefs::kManagedWebHidAllowDevicesWithHidUsagesForUrls,
+ /*result=*/nullptr));
+
+ PolicyMap policy;
+ policy.Set(key::kWebHidAllowDevicesWithHidUsagesForUrls,
+ PolicyLevel::POLICY_LEVEL_MANDATORY,
+ PolicyScope::POLICY_SCOPE_MACHINE,
+ PolicySource::POLICY_SOURCE_CLOUD,
+ ReadJson(kAllowDevicesWithHidUsagesForUrls), nullptr);
+ UpdateProviderPolicy(policy);
+
+ const base::Value* pref_value = nullptr;
+ EXPECT_TRUE(store_->GetValue(
+ prefs::kManagedWebHidAllowDevicesWithHidUsagesForUrls, &pref_value));
+ ASSERT_TRUE(pref_value);
+ ASSERT_TRUE(pref_value->is_list());
+
+ // Ensure that the kManagedWebHidAllowDevicesWithHidUsagesForUrls pref is set
+ // correctly.
+ const auto& list = pref_value->GetList();
+ ASSERT_EQ(2ul, list.size());
+
+ // Check the first item's usages list.
+ const base::Value* usages = list[0].FindKey(kUsagesKey);
+ ASSERT_TRUE(usages);
+
+ const auto& first_usages_list = usages->GetList();
+ ASSERT_EQ(2ul, first_usages_list.size());
+
+ const base::Value* usage_page = first_usages_list[0].FindKey(kUsagePageKey);
+ ASSERT_TRUE(usage_page);
+ EXPECT_EQ(base::Value(kTestUsagePage1), *usage_page);
+
+ const base::Value* usage = first_usages_list[0].FindKey(kUsageKey);
+ ASSERT_TRUE(usage);
+ EXPECT_EQ(base::Value(kTestUsage), *usage);
+
+ usage_page = first_usages_list[1].FindKey(kUsagePageKey);
+ ASSERT_TRUE(usage_page);
+ EXPECT_EQ(base::Value(kTestUsagePage2), *usage_page);
+
+ usage = first_usages_list[1].FindKey(kUsageKey);
+ EXPECT_FALSE(usage);
+
+ // Check the first item's urls list.
+ const base::Value* urls = list[0].FindKey(kUrlsKey);
+ ASSERT_TRUE(urls);
+ ASSERT_EQ(2ul, urls->GetList().size());
+ EXPECT_EQ(base::Value("https://origin1"), urls->GetList()[0]);
+ EXPECT_EQ(base::Value("https://origin2"), urls->GetList()[1]);
+
+ // Check the second item's usages list.
+ usages = list[1].FindKey(kUsagesKey);
+ ASSERT_TRUE(usages);
+
+ const auto& second_usages_list = usages->GetList();
+ ASSERT_EQ(1ul, second_usages_list.size());
+
+ usage_page = second_usages_list[0].FindKey(kUsagePageKey);
+ ASSERT_TRUE(usage_page);
+ EXPECT_EQ(base::Value(kTestUsagePage3), *usage_page);
+
+ usage = second_usages_list[0].FindKey(kUsageKey);
+ EXPECT_FALSE(usage);
+
+ // Check the second item's urls list.
+ urls = list[1].FindKey(kUrlsKey);
+ ASSERT_TRUE(urls);
+ ASSERT_EQ(1ul, urls->GetList().size());
+ EXPECT_EQ(base::Value("https://origin3"), urls->GetList()[0]);
+}
+
+struct WebHidInvalidPolicyTestData {
+ const char* policy_name;
+ const char* pref_name;
+ const char* policy;
+ const char16_t* expected_errors;
+ const char* expected_pref;
+};
+
+class WebHidInvalidPolicyTest
+ : public WebHidDevicePolicyHandlerTest,
+ public WithParamInterface<WebHidInvalidPolicyTestData> {};
+
+TEST_P(WebHidInvalidPolicyTest, CheckPolicySettingsWithInvalidPolicy) {
+ const auto& test_data = GetParam();
+ auto* handler = AddHandler(test_data.policy_name);
+
+ PolicyMap policy;
+ policy.Set(test_data.policy_name, PolicyLevel::POLICY_LEVEL_MANDATORY,
+ PolicyScope::POLICY_SCOPE_MACHINE,
+ PolicySource::POLICY_SOURCE_CLOUD, ReadJson(test_data.policy),
+ /*external_data_fetcher=*/nullptr);
+
+ // Try CheckPolicySettings with the invalid policy. It returns success if the
+ // policy can be successfully applied, even if there are errors.
+ PolicyErrorMap errors;
+ bool success = handler->CheckPolicySettings(policy, &errors);
+ EXPECT_EQ(success, test_data.expected_pref != nullptr);
+ EXPECT_EQ(test_data.expected_errors, errors.GetErrors(test_data.policy_name));
+
+ EXPECT_FALSE(store_->GetValue(test_data.pref_name, /*result=*/nullptr));
+
+ // Try updating the policy.
+ UpdateProviderPolicy(policy);
+
+ // Check that the preference has the expected value.
+ if (test_data.expected_pref) {
+ const base::Value* pref_value = nullptr;
+ EXPECT_TRUE(store_->GetValue(test_data.pref_name, &pref_value));
+ ASSERT_TRUE(pref_value);
+ absl::optional<base::Value> expected_pref_value =
+ ReadJson(test_data.expected_pref);
+ ASSERT_TRUE(expected_pref_value);
+ EXPECT_EQ(*expected_pref_value, *pref_value);
+ } else {
+ EXPECT_FALSE(store_->GetValue(test_data.pref_name, /*result=*/nullptr));
+ }
+}
+
+WebHidInvalidPolicyTestData kTestData[]{
+ {
+ key::kWebHidAllowDevicesForUrls,
+ prefs::kManagedWebHidAllowDevicesForUrls,
+ R"(
+ [
+ {
+ "urls": [
+ "https://google.com"
+ ]
+ }
+ ])",
+ u"Schema validation error at \"items[0]\": Missing or invalid required "
+ u"property: devices",
+ "[]",
+ },
+ {
+ key::kWebHidAllowDevicesForUrls,
+ prefs::kManagedWebHidAllowDevicesForUrls,
+ R"(
+ [
+ {
+ "devices": [
+ {
+ "vendor_id": 1234
+ }
+ ]
+ }
+ ])",
+ u"Schema validation error at \"items[0]\": Missing or invalid required "
+ u"property: urls",
+ "[]",
+ },
+ {
+ key::kWebHidAllowDevicesForUrls,
+ prefs::kManagedWebHidAllowDevicesForUrls,
+ R"(
+ [
+ {
+ "devices": [
+ {
+ "vendor_id": 1234,
+ "serial_number": "1234ABCD"
+ }
+ ],
+ "urls": [
+ "https://google.com"
+ ]
+ }
+ ])",
+ u"Schema validation error at \"items[0].devices.items[0]\": Unknown "
+ u"property: serial_number",
+ R"(
+ [
+ {
+ "devices": [
+ {
+ "vendor_id": 1234
+ }
+ ],
+ "urls": [
+ "https://google.com"
+ ]
+ }
+ ])",
+ },
+ {
+ key::kWebHidAllowDevicesForUrls,
+ prefs::kManagedWebHidAllowDevicesForUrls,
+ R"(
+ [
+ {
+ "devices": [
+ {
+ "vendor_id": 65536
+ }
+ ],
+ "urls": [
+ "https://google.com"
+ ]
+ }
+ ])",
+ u"Schema validation error at \"items[0].devices.items[0].vendor_id\": "
+ u"Invalid value for integer",
+ R"(
+ [
+ {
+ "devices": [],
+ "urls": [
+ "https://google.com"
+ ]
+ }
+ ])",
+ },
+ {
+ key::kWebHidAllowDevicesForUrls,
+ prefs::kManagedWebHidAllowDevicesForUrls,
+ R"(
+ [
+ {
+ "devices": [
+ {
+ "vendor_id": 1234,
+ "product_id": 65536
+ }
+ ],
+ "urls": [
+ "https://google.com"
+ ]
+ }
+ ])",
+ u"Schema validation error at \"items[0].devices.items[0].product_id\": "
+ u"Invalid value for integer",
+ R"(
+ [
+ {
+ "devices": [],
+ "urls": [
+ "https://google.com"
+ ]
+ }
+ ])",
+ },
+ {
+ key::kWebHidAllowDevicesForUrls,
+ prefs::kManagedWebHidAllowDevicesForUrls,
+ R"(
+ [
+ {
+ "devices": [
+ {
+ "product_id": 1234
+ }
+ ],
+ "urls": [
+ "https://google.com"
+ ]
+ }
+ ])",
+ u"Schema validation error at \"items[0].devices.items[0]\": Missing or "
+ u"invalid required property: vendor_id",
+ R"(
+ [
+ {
+ "devices": [],
+ "urls": [
+ "https://google.com"
+ ]
+ }
+ ])",
+ },
+ {
+ key::kWebHidAllowDevicesForUrls,
+ prefs::kManagedWebHidAllowDevicesForUrls,
+ R"(
+ [
+ {
+ "devices": [
+ {
+ "vendor_id": 1234
+ }
+ ],
+ "urls": [
+ "not-a-valid-url"
+ ]
+ }
+ ])",
+ u"Schema validation error at \"items[0].urls.items[0]\": Invalid URL: "
+ u"not-a-valid-url",
+ R"(
+ [
+ {
+ "devices": [
+ {
+ "vendor_id": 1234
+ }
+ ],
+ "urls": [
+ "not-a-valid-url"
+ ]
+ }
+ ])",
+ },
+ {
+ key::kWebHidAllowDevicesForUrls,
+ prefs::kManagedWebHidAllowDevicesForUrls,
+ R"(
+ [
+ {
+ "devices": [
+ {
+ "vendor_id": 1234
+ }
+ ],
+ "urls": [
+ ""
+ ]
+ }
+ ])",
+ u"Schema validation error at \"items[0].urls.items[0]\": Invalid URL: ",
+ R"(
+ [
+ {
+ "devices": [
+ {
+ "vendor_id": 1234
+ }
+ ],
+ "urls": [
+ ""
+ ]
+ }
+ ])",
+ },
+ {
+ key::kWebHidAllowDevicesForUrls,
+ prefs::kManagedWebHidAllowDevicesForUrls,
+ R"(
+ [
+ {
+ "devices": [
+ {
+ "vendor_id": 1234
+ }
+ ],
+ "urls": [
+ "invalid-url-1",
+ "invalid-url-2"
+ ]
+ }
+ ])",
+ u"Schema validation error at \"items[0].urls.items[0]\": Invalid URL: "
+ u"invalid-url-1\nSchema validation error at "
+ u"\"items[0].urls.items[1]\": Invalid URL: invalid-url-2",
+ R"(
+ [
+ {
+ "devices": [
+ {
+ "vendor_id": 1234
+ }
+ ],
+ "urls": [
+ "invalid-url-1",
+ "invalid-url-2"
+ ]
+ }
+ ])",
+ },
+ {
+ key::kWebHidAllowDevicesWithHidUsagesForUrls,
+ prefs::kManagedWebHidAllowDevicesWithHidUsagesForUrls,
+ R"(
+ [
+ {
+ "urls": [
+ "https://google.com"
+ ]
+ }
+ ])",
+ u"Schema validation error at \"items[0]\": Missing or invalid required "
+ u"property: usages",
+ "[]",
+ },
+ {
+ key::kWebHidAllowDevicesWithHidUsagesForUrls,
+ prefs::kManagedWebHidAllowDevicesWithHidUsagesForUrls,
+ R"(
+ [
+ {
+ "usages": [
+ {
+ "usage_page": 1234
+ }
+ ]
+ }
+ ])",
+ u"Schema validation error at \"items[0]\": Missing or invalid required "
+ u"property: urls",
+ "[]",
+ },
+ {
+ key::kWebHidAllowDevicesWithHidUsagesForUrls,
+ prefs::kManagedWebHidAllowDevicesWithHidUsagesForUrls,
+ R"(
+ [
+ {
+ "usages": [
+ {
+ "usage_page": 1234,
+ "serial_number": "1234ABCD"
+ }
+ ],
+ "urls": [
+ "https://google.com"
+ ]
+ }
+ ])",
+ u"Schema validation error at \"items[0].usages.items[0]\": Unknown "
+ u"property: serial_number",
+ R"(
+ [
+ {
+ "usages": [
+ {
+ "usage_page": 1234
+ }
+ ],
+ "urls": [
+ "https://google.com"
+ ]
+ }
+ ])",
+ },
+ {
+ key::kWebHidAllowDevicesWithHidUsagesForUrls,
+ prefs::kManagedWebHidAllowDevicesWithHidUsagesForUrls,
+ R"(
+ [
+ {
+ "usages": [
+ {
+ "usage_page": 65536
+ }
+ ],
+ "urls": [
+ "https://google.com"
+ ]
+ }
+ ])",
+ u"Schema validation error at \"items[0].usages.items[0].usage_page\": "
+ u"Invalid value for integer",
+ R"(
+ [
+ {
+ "usages": [],
+ "urls": [
+ "https://google.com"
+ ]
+ }
+ ])",
+ },
+ {
+ key::kWebHidAllowDevicesWithHidUsagesForUrls,
+ prefs::kManagedWebHidAllowDevicesWithHidUsagesForUrls,
+ R"(
+ [
+ {
+ "usages": [
+ {
+ "usage_page": 1234,
+ "usage": 65536
+ }
+ ],
+ "urls": [
+ "https://google.com"
+ ]
+ }
+ ])",
+ u"Schema validation error at \"items[0].usages.items[0].usage\": "
+ u"Invalid value for integer",
+ R"(
+ [
+ {
+ "usages": [],
+ "urls": [
+ "https://google.com"
+ ]
+ }
+ ])",
+ },
+ {
+ key::kWebHidAllowDevicesWithHidUsagesForUrls,
+ prefs::kManagedWebHidAllowDevicesWithHidUsagesForUrls,
+ R"(
+ [
+ {
+ "usages": [
+ {
+ "usage": 1234
+ }
+ ],
+ "urls": [
+ "https://google.com"
+ ]
+ }
+ ])",
+ u"Schema validation error at \"items[0].usages.items[0]\": Missing or "
+ u"invalid required property: usage_page",
+ R"(
+ [
+ {
+ "usages": [],
+ "urls": [
+ "https://google.com"
+ ]
+ }
+ ])",
+ },
+ {
+ key::kWebHidAllowDevicesWithHidUsagesForUrls,
+ prefs::kManagedWebHidAllowDevicesWithHidUsagesForUrls,
+ R"(
+ [
+ {
+ "usages": [
+ {
+ "usage_page": 1234
+ }
+ ],
+ "urls": [
+ "not-a-valid-url"
+ ]
+ }
+ ])",
+ u"Schema validation error at \"items[0].urls.items[0]\": Invalid URL: "
+ u"not-a-valid-url",
+ R"(
+ [
+ {
+ "usages": [
+ {
+ "usage_page": 1234
+ }
+ ],
+ "urls": [
+ "not-a-valid-url"
+ ]
+ }
+ ])",
+ },
+ {
+ key::kWebHidAllowDevicesWithHidUsagesForUrls,
+ prefs::kManagedWebHidAllowDevicesWithHidUsagesForUrls,
+ R"(
+ [
+ {
+ "usages": [
+ {
+ "usage_page": 1234
+ }
+ ],
+ "urls": [
+ ""
+ ]
+ }
+ ])",
+ u"Schema validation error at \"items[0].urls.items[0]\": Invalid URL: ",
+ R"(
+ [
+ {
+ "usages": [
+ {
+ "usage_page": 1234
+ }
+ ],
+ "urls": [
+ ""
+ ]
+ }
+ ])",
+ },
+ {
+ key::kWebHidAllowDevicesWithHidUsagesForUrls,
+ prefs::kManagedWebHidAllowDevicesWithHidUsagesForUrls,
+ R"(
+ [
+ {
+ "usages": [
+ {
+ "usage_page": 1234
+ }
+ ],
+ "urls": [
+ "invalid-url-1",
+ "invalid-url-2"
+ ]
+ }
+ ])",
+ u"Schema validation error at \"items[0].urls.items[0]\": Invalid URL: "
+ u"invalid-url-1\nSchema validation error at "
+ u"\"items[0].urls.items[1]\": Invalid URL: invalid-url-2",
+ R"(
+ [
+ {
+ "usages": [
+ {
+ "usage_page": 1234
+ }
+ ],
+ "urls": [
+ "invalid-url-1",
+ "invalid-url-2"
+ ]
+ }
+ ])",
+ },
+};
+
+INSTANTIATE_TEST_SUITE_P(WebHidInvalidPolicyTests,
+ WebHidInvalidPolicyTest,
+ testing::ValuesIn(kTestData));
+
+} // namespace policy
diff --git a/chrome/browser/prefs/browser_prefs.cc b/chrome/browser/prefs/browser_prefs.cc
index 4a2c18c..ff400ec1 100644
--- a/chrome/browser/prefs/browser_prefs.cc
+++ b/chrome/browser/prefs/browser_prefs.cc
@@ -237,6 +237,7 @@
#include "chrome/browser/cart/cart_service.h"
#include "chrome/browser/device_api/device_service_impl.h"
#include "chrome/browser/gcm/gcm_product_util.h"
+#include "chrome/browser/hid/hid_policy_allowed_devices.h"
#include "chrome/browser/intranet_redirect_detector.h"
#include "chrome/browser/media/unified_autoplay_config.h"
#include "chrome/browser/metrics/tab_stats/tab_stats_tracker.h"
@@ -994,6 +995,7 @@
secure_origin_allowlist::RegisterPrefs(registry);
#if !BUILDFLAG(IS_ANDROID)
SerialPolicyAllowedPorts::RegisterPrefs(registry);
+ HidPolicyAllowedDevices::RegisterLocalStatePrefs(registry);
#endif
sessions::SessionIdGenerator::RegisterPrefs(registry);
SSLConfigServiceManager::RegisterPrefs(registry);
diff --git a/chrome/common/pref_names.cc b/chrome/common/pref_names.cc
index a08410d..5fb3a06 100644
--- a/chrome/common/pref_names.cc
+++ b/chrome/common/pref_names.cc
@@ -1683,6 +1683,19 @@
// Used to store the value of the SerialAllowUsbDevicesForUrls policy.
const char kManagedSerialAllowUsbDevicesForUrls[] =
"managed.serial_allow_usb_devices_for_urls";
+
+// Used to store the value of the WebHidAllowAllDevicesForUrls policy.
+const char kManagedWebHidAllowAllDevicesForUrls[] =
+ "managed.web_hid_allow_all_devices_for_urls";
+
+// Used to store the value of the WebHidAllowDevicesForUrls policy.
+const char kManagedWebHidAllowDevicesForUrls[] =
+ "managed.web_hid_allow_devices_for_urls";
+
+// Used to store the value of the WebHidAllowAllDevicesWithHidUsagesForUrls
+// policy.
+const char kManagedWebHidAllowDevicesWithHidUsagesForUrls[] =
+ "managed.web_hid_allow_devices_with_hid_usages_for_urls";
#endif // !BUILDFLAG(IS_ANDROID)
// Directory of the last profile used.
diff --git a/chrome/common/pref_names.h b/chrome/common/pref_names.h
index cf32348..9d0fda3 100644
--- a/chrome/common/pref_names.h
+++ b/chrome/common/pref_names.h
@@ -549,6 +549,9 @@
#if !BUILDFLAG(IS_ANDROID)
extern const char kManagedSerialAllowAllPortsForUrls[];
extern const char kManagedSerialAllowUsbDevicesForUrls[];
+extern const char kManagedWebHidAllowAllDevicesForUrls[];
+extern const char kManagedWebHidAllowDevicesForUrls[];
+extern const char kManagedWebHidAllowDevicesWithHidUsagesForUrls[];
#endif // !BUILDFLAG(IS_ANDROID)
extern const char kProfileLastUsed[];
diff --git a/chrome/test/BUILD.gn b/chrome/test/BUILD.gn
index 9b4458f..5bceba27 100644
--- a/chrome/test/BUILD.gn
+++ b/chrome/test/BUILD.gn
@@ -6025,6 +6025,7 @@
"../browser/performance_manager/policies/background_tab_loading_policy_unittest.cc",
"../browser/platform_util_unittest.cc",
"../browser/policy/policy_path_parser_unittest.cc",
+ "../browser/policy/webhid_device_policy_handler_unittest.cc",
"../browser/profile_resetter/profile_resetter_unittest.cc",
"../browser/profile_resetter/reset_report_uploader_unittest.cc",
"../browser/renderer_context_menu/render_view_context_menu_unittest.cc",
diff --git a/chrome/test/data/policy/policy_test_cases.json b/chrome/test/data/policy/policy_test_cases.json
index d04295ef..6fb2ba71 100644
--- a/chrome/test/data/policy/policy_test_cases.json
+++ b/chrome/test/data/policy/policy_test_cases.json
@@ -5259,6 +5259,173 @@
}
]
},
+ "WebHidAllowAllDevicesForUrls": {
+ "os": [
+ "win",
+ "linux",
+ "mac",
+ "chromeos_ash",
+ "chromeos_lacros"
+ ],
+ "policy_pref_mapping_tests": [
+ {
+ "policies": {
+ "WebHidAllowAllDevicesForUrls": [
+ "https://www.google.com"
+ ]
+ },
+ "prefs": {
+ "managed.web_hid_allow_all_devices_for_urls": {
+ "location": "local_state",
+ "value": [
+ "https://www.google.com"
+ ]
+ }
+ }
+ },
+ {
+ "policies": {},
+ "prefs": {
+ "managed.web_hid_allow_all_devices_for_urls": {
+ "location": "local_state",
+ "default_value": []
+ }
+ }
+ }
+ ]
+ },
+ "WebHidAllowDevicesForUrls": {
+ "os": [
+ "win",
+ "linux",
+ "mac",
+ "chromeos_ash",
+ "chromeos_lacros"
+ ],
+ "policy_pref_mapping_tests": [
+ {
+ "policies": {
+ "WebHidAllowDevicesForUrls": [
+ {
+ "devices": [
+ {
+ "vendor_id": 6353,
+ "product_id": 37888
+ }
+ ],
+ "urls": [
+ "https://stadia.google.com"
+ ]
+ },
+ {
+ "devices": [
+ {
+ "vendor_id": 6353
+ }
+ ],
+ "urls": [
+ "https://www.google.com"
+ ]
+ }
+ ]
+ },
+ "prefs": {
+ "managed.web_hid_allow_devices_for_urls": {
+ "location": "local_state",
+ "value": [
+ {
+ "devices": [
+ {
+ "vendor_id": 6353,
+ "product_id": 37888
+ }
+ ],
+ "urls": [
+ "https://stadia.google.com"
+ ]
+ },
+ {
+ "devices": [
+ {
+ "vendor_id": 6353
+ }
+ ],
+ "urls": [
+ "https://www.google.com"
+ ]
+ }
+ ]
+ }
+ }
+ }
+ ]
+ },
+ "WebHidAllowDevicesWithHidUsagesForUrls": {
+ "os": [
+ "win",
+ "linux",
+ "mac",
+ "chromeos_ash",
+ "chromeos_lacros"
+ ],
+ "policy_pref_mapping_tests": [
+ {
+ "policies": {
+ "WebHidAllowDevicesWithHidUsagesForUrls": [
+ {
+ "usages": [
+ {
+ "usage_page": 1,
+ "usage": 5
+ }
+ ],
+ "urls": [
+ "https://stadia.google.com"
+ ]
+ },
+ {
+ "usages": [
+ {
+ "usage_page": 11
+ }
+ ],
+ "urls": [
+ "https://meet.google.com"
+ ]
+ }
+ ]
+ },
+ "prefs": {
+ "managed.web_hid_allow_devices_with_hid_usages_for_urls": {
+ "location": "local_state",
+ "value": [
+ {
+ "usages": [
+ {
+ "usage_page": 1,
+ "usage": 5
+ }
+ ],
+ "urls": [
+ "https://stadia.google.com"
+ ]
+ },
+ {
+ "usages": [
+ {
+ "usage_page": 11
+ }
+ ],
+ "urls": [
+ "https://meet.google.com"
+ ]
+ }
+ ]
+ }
+ }
+ }
+ ]
+ },
"AutoSelectCertificateForUrls": {
"os": [
"win",
diff --git a/components/policy/resources/policy_templates.json b/components/policy/resources/policy_templates.json
index 2b2b7527..46bceb8 100644
--- a/components/policy/resources/policy_templates.json
+++ b/components/policy/resources/policy_templates.json
@@ -601,6 +601,9 @@
'SerialAllowUsbDevicesForUrls',
'WebHidAskForUrls',
'WebHidBlockedForUrls',
+ 'WebHidAllowAllDevicesForUrls',
+ 'WebHidAllowDevicesForUrls',
+ 'WebHidAllowDevicesWithHidUsagesForUrls',
],
},
{
@@ -7411,6 +7414,139 @@
For detailed information on valid <ph name="URL_LABEL">url</ph> patterns, please see https://cloud.google.com/docs/chrome-enterprise/policies/url-patterns. <ph name="WILDCARD_VALUE">*</ph> is not an accepted value for this policy.''',
},
{
+ 'name': 'WebHidAllowAllDevicesForUrls',
+ 'owners': ['[email protected]', 'file://third_party/blink/renderer/modules/hid/OWNERS'],
+ 'type': 'list',
+ 'schema': {
+ 'type': 'array',
+ 'items': { 'type': 'string' },
+ },
+ 'future_on': ['chrome_os', 'chrome.*'],
+ 'features': {
+ 'dynamic_refresh': True,
+ 'per_profile': False,
+ },
+ 'example_value': ['https://google.com', 'https://chromium.org'],
+ 'id': 953,
+ 'caption': '''Automatically grant permission to sites to connect to any HID device.''',
+ 'tags': ['website-sharing'],
+ 'desc': '''Setting the policy allows you to list sites which are automatically granted permission to access all available devices.
+
+ The URLs must be valid, otherwise the policy is ignored. Only the origin (scheme, host and port) of the URL is considered.
+
+ On Chrome OS, this policy only applies to affiliated users.
+
+ This policy overrides <ph name="DEFAULT_WEB_HID_GUARD_SETTING_POLICY_NAME">DefaultWebHidGuardSetting</ph>, <ph name="WEB_HID_ASK_FOR_URLS_POLICY_NAME">WebHidAskForUrls</ph>, <ph name="WEB_HID_BLOCKED_FOR_URLS_POLICY_NAME">WebHidBlockedForUrls</ph> and the user's preferences.''',
+ },
+ {
+ 'name': 'WebHidAllowDevicesForUrls',
+ 'owners': ['[email protected]', 'file://third_party/blink/renderer/modules/hid/OWNERS'],
+ 'type': 'dict',
+ 'schema': {
+ 'type': 'array',
+ 'items': {
+ 'type': 'object',
+ 'properties': {
+ 'devices': {
+ 'type': 'array',
+ 'items': {
+ 'type': 'object',
+ 'properties': {
+ 'vendor_id': {
+ 'type': 'integer',
+ 'minimum': 0,
+ 'maximum': 65535
+ },
+ 'product_id': {
+ 'type': 'integer',
+ 'minimum': 0,
+ 'maximum': 65535
+ }
+ },
+ 'required': ['vendor_id']
+ }
+ },
+ 'urls': {
+ 'type': 'array',
+ 'items': { 'type': 'string' }
+ }
+ },
+ 'required': ['devices', 'urls']
+ }
+ },
+ 'future_on': ['chrome_os', 'chrome.*'],
+ 'features': {
+ 'dynamic_refresh': True,
+ 'per_profile': False,
+ },
+ 'example_value': [{
+ 'devices': [{'vendor_id': 1234, 'product_id': 5678}],
+ 'urls': ['https://google.com', 'https://chromium.org'],
+ }],
+ 'id': 954,
+ 'caption': '''Automatically grant permission to these sites to connect to HID devices with the given vendor and product IDs.''',
+ 'tags': ['website-sharing'],
+ 'desc': '''Setting the policy lets you list the URLs that specify which sites are automatically granted permission to access a HID device with the given vendor and product IDs. Each item in the list requires both <ph name="DEVICES_FIELD_NAME">devices</ph> and <ph name="URLS_FIELD_NAME">urls</ph> fields for the item to be valid, otherwise the item is ignored. Each item in the <ph name="DEVICES_FIELD_NAME">devices</ph> field must have a <ph name="VENDOR_ID_FIELD_NAME">vendor_id</ph> and may have a <ph name="PRODUCT_ID_FIELD_NAME">product_id</ph> field. Omitting the <ph name="PRODUCT_ID_FIELD_NAME">product_id</ph> field will create a policy matching any device with the specified vendor ID. An item which has a <ph name="PRODUCT_ID_FIELD_NAME">product_id</ph> field without a <ph name="VENDOR_ID_FIELD_NAME">vendor_id</ph> field is invalid and is ignored.
+
+ Leaving the policy unset means <ph name="DEFAULT_WEB_HID_GUARD_SETTING_POLICY_NAME">DefaultWebHidGuardSetting</ph> applies, if it's set. If not, the user's personal setting applies.
+
+ URLs in this policy shouldn't conflict with those configured through <ph name="WEB_HID_BLOCKED_FOR_URLS_POLICY_NAME">WebHidBlockedForUrls</ph>. If they do, this policy takes precedence over <ph name="WEB_HID_BLOCKED_FOR_URLS_POLICY_NAME">WebHidBlockedForUrls</ph>.''',
+ },
+ {
+ 'name': 'WebHidAllowDevicesWithHidUsagesForUrls',
+ 'owners': ['[email protected]', 'file://third_party/blink/renderer/modules/hid/OWNERS'],
+ 'type': 'dict',
+ 'schema': {
+ 'type': 'array',
+ 'items': {
+ 'type': 'object',
+ 'properties': {
+ 'usages': {
+ 'type': 'array',
+ 'items': {
+ 'type': 'object',
+ 'properties': {
+ 'usage_page': {
+ 'type': 'integer',
+ 'minimum': 0,
+ 'maximum': 65535
+ },
+ 'usage': {
+ 'type': 'integer',
+ 'minimum': 0,
+ 'maximum': 65535
+ }
+ },
+ 'required': ['usage_page']
+ }
+ },
+ 'urls': {
+ 'type': 'array',
+ 'items': { 'type': 'string' }
+ }
+ },
+ 'required': ['usages', 'urls']
+ }
+ },
+ 'future_on': ['chrome_os', 'chrome.*'],
+ 'features': {
+ 'dynamic_refresh': True,
+ 'per_profile': False,
+ },
+ 'example_value': [{
+ 'usages': [{'usage_page': 1234, 'usage': 5678}],
+ 'urls': ['https://google.com', 'https://chromium.org'],
+ }],
+ 'id': 955,
+ 'caption': '''Automatically grant permission to these sites to connect to HID devices containing top-level collections with the given HID usage.''',
+ 'tags': ['website-sharing'],
+ 'desc': '''Setting the policy lets you list the URLs that specify which sites are automatically granted permission to access a HID device containing a top-level collection with the given HID usage. Each item in the list requires both <ph name="USAGES_FIELD_NAME">usages</ph> and <ph name="URLS_FIELD_NAME">urls</ph> fields for the policy to be valid. Each item in the <ph name="USAGES_FIELD_NAME">usages</ph> field must have a <ph name="USAGE_PAGE_FIELD_NAME">usage_page</ph> and may have a <ph name="USAGE_FIELD_NAME">usage</ph> field. Omitting the <ph name="USAGE_FIELD_NAME">usage</ph> field will create a policy matching any device containing a top-level collection with a usage from the specified usage page. An item which has a <ph name="USAGE_FIELD_NAME">usage</ph> field without a <ph name="USAGE_PAGE_FIELD_NAME">usage_page</ph> field is invalid and is ignored.
+
+ Leaving the policy unset means <ph name="DEFAULT_WEB_HID_GUARD_SETTING_POLICY_NAME">DefaultWebHidGuardSetting</ph> applies, if it's set. If not, the user's personal setting applies.
+
+ URLs in this policy shouldn't conflict with those configured through <ph name="WEB_HID_BLOCKED_FOR_URLS_POLICY_NAME">WebHidBlockedForUrls</ph>. If they do, this policy takes precedence over <ph name="WEB_HID_BLOCKED_FOR_URLS_POLICY_NAME">WebHidBlockedForUrls</ph>.''',
+ },
+ {
'name': 'DefaultFileHandlingGuardSetting',
'owners': ['[email protected]', '[email protected]'],
'type': 'int-enum',
@@ -30798,6 +30934,6 @@
'placeholders': [],
'deleted_policy_ids': [114, 115, 204, 205, 206, 341, 412, 476, 544, 546, 562, 569, 578, 583, 585, 586, 587, 588, 589, 590, 591, 600, 668, 669, 872],
'deleted_atomic_policy_group_ids': [19],
- 'highest_id_currently_used': 952,
+ 'highest_id_currently_used': 955,
'highest_atomic_group_id_currently_used': 41
}
diff --git a/tools/metrics/histograms/enums.xml b/tools/metrics/histograms/enums.xml
index 5d05f70..58c6858 100644
--- a/tools/metrics/histograms/enums.xml
+++ b/tools/metrics/histograms/enums.xml
@@ -28473,6 +28473,9 @@
<int value="950" label="AllHttpAuthSchemesAllowedForOrigins"/>
<int value="951" label="WindowPlacementAlwaysAllowed"/>
<int value="952" label="ReportDevicePeripherals"/>
+ <int value="953" label="WebHidAllowAllDevicesForUrls"/>
+ <int value="954" label="WebHidAllowDevicesForUrls"/>
+ <int value="955" label="WebHidAllowDevicesWithHidUsagesForUrls"/>
</enum>
<enum name="EnterprisePolicyDeviceIdValidity">