Add DeviceLoginScreenWebUsbAllowDevicesForUrls policy

(reland of https://crrev.com/c/1636350)
This CL adds a new device policy to whitelist certain USB devices for
certain urls in order to be used by the WebUSB API on the login screen.
We already have a user policy for that, so this device policy reuses the
existing user policy's infrastructure, but only affects the login screen
(i.e. does not affect affiliated/non-affiliated user sessions).

Bug: 1000270, 968373, 854329
Change-Id: I5abff8b7cca18650182af2dcfc63009cd9960f0d
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1789392
Commit-Queue: Alexander Hendrich <[email protected]>
Reviewed-by: Ovidio de Jesús Ruiz-Henríquez <[email protected]>
Reviewed-by: Reilly Grant <[email protected]>
Reviewed-by: Sergey Poromov <[email protected]>
Reviewed-by: Dominic Battré <[email protected]>
Cr-Commit-Position: refs/heads/master@{#695572}
diff --git a/chrome/browser/chromeos/policy/device_policy_decoder_chromeos.cc b/chrome/browser/chromeos/policy/device_policy_decoder_chromeos.cc
index d31e2a4..eae4e07 100644
--- a/chrome/browser/chromeos/policy/device_policy_decoder_chromeos.cc
+++ b/chrome/browser/chromeos/policy/device_policy_decoder_chromeos.cc
@@ -417,6 +417,17 @@
                   POLICY_SOURCE_CLOUD, std::move(rules), nullptr);
   }
 
+  if (policy.has_device_login_screen_webusb_allow_devices_for_urls()) {
+    const em::DeviceLoginScreenWebUsbAllowDevicesForUrlsProto& container(
+        policy.device_login_screen_webusb_allow_devices_for_urls());
+    if (container.has_device_login_screen_webusb_allow_devices_for_urls()) {
+      SetJsonDevicePolicy(
+          key::kDeviceLoginScreenWebUsbAllowDevicesForUrls,
+          container.device_login_screen_webusb_allow_devices_for_urls(),
+          policies);
+    }
+  }
+
   if (policy.has_saml_login_authentication_type()) {
     const em::SamlLoginAuthenticationTypeProto& container(
         policy.saml_login_authentication_type());
diff --git a/chrome/browser/policy/configuration_policy_handler_list_factory.cc b/chrome/browser/policy/configuration_policy_handler_list_factory.cc
index c8838494..37f5826 100644
--- a/chrome/browser/policy/configuration_policy_handler_list_factory.cc
+++ b/chrome/browser/policy/configuration_policy_handler_list_factory.cc
@@ -1225,7 +1225,8 @@
       SimpleSchemaValidatingPolicyHandler::RECOMMENDED_PROHIBITED,
       SimpleSchemaValidatingPolicyHandler::MANDATORY_ALLOWED));
   handlers->AddHandler(
-      std::make_unique<WebUsbAllowDevicesForUrlsPolicyHandler>(chrome_schema));
+      WebUsbAllowDevicesForUrlsPolicyHandler::CreateForUserPolicy(
+          chrome_schema));
 
 // On most platforms, there is a legacy policy
 // kUnsafelyTreatInsecureOriginAsSecure which has been replaced by
@@ -1558,6 +1559,9 @@
       SCHEMA_ALLOW_UNKNOWN,
       SimpleSchemaValidatingPolicyHandler::RECOMMENDED_PROHIBITED,
       SimpleSchemaValidatingPolicyHandler::MANDATORY_ALLOWED));
+  handlers->AddHandler(
+      WebUsbAllowDevicesForUrlsPolicyHandler::CreateForDevicePolicy(
+          chrome_schema));
 #endif  // defined(OS_CHROMEOS)
 
 #if BUILDFLAG(ENABLE_PLUGINS)
diff --git a/chrome/browser/policy/webusb_allow_devices_for_urls_policy_handler.cc b/chrome/browser/policy/webusb_allow_devices_for_urls_policy_handler.cc
index 2bc531f..39fc46ab 100644
--- a/chrome/browser/policy/webusb_allow_devices_for_urls_policy_handler.cc
+++ b/chrome/browser/policy/webusb_allow_devices_for_urls_policy_handler.cc
@@ -17,6 +17,7 @@
 #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_registry_simple.h"
 #include "components/prefs/pref_value_map.h"
 #include "url/gurl.h"
 
@@ -38,12 +39,42 @@
 
 }  // namespace
 
+// static
+std::unique_ptr<WebUsbAllowDevicesForUrlsPolicyHandler>
+WebUsbAllowDevicesForUrlsPolicyHandler::CreateForUserPolicy(
+    const Schema& chrome_schema) {
+  return std::make_unique<WebUsbAllowDevicesForUrlsPolicyHandler>(
+      key::kWebUsbAllowDevicesForUrls, prefs::kManagedWebUsbAllowDevicesForUrls,
+      chrome_schema);
+}
+
+#if defined(OS_CHROMEOS)
+// static
+std::unique_ptr<WebUsbAllowDevicesForUrlsPolicyHandler>
+WebUsbAllowDevicesForUrlsPolicyHandler::CreateForDevicePolicy(
+    const Schema& chrome_schema) {
+  return std::make_unique<WebUsbAllowDevicesForUrlsPolicyHandler>(
+      key::kDeviceLoginScreenWebUsbAllowDevicesForUrls,
+      prefs::kDeviceLoginScreenWebUsbAllowDevicesForUrls, chrome_schema);
+}
+
+// static
+void WebUsbAllowDevicesForUrlsPolicyHandler::RegisterPrefs(
+    PrefRegistrySimple* registry) {
+  registry->RegisterListPref(
+      prefs::kDeviceLoginScreenWebUsbAllowDevicesForUrls);
+}
+#endif  // defined(OS_CHROMEOS)
+
 WebUsbAllowDevicesForUrlsPolicyHandler::WebUsbAllowDevicesForUrlsPolicyHandler(
-    Schema schema)
+    const char* policy_name,
+    const char* pref_name,
+    const Schema& chrome_schema)
     : SchemaValidatingPolicyHandler(
-          key::kWebUsbAllowDevicesForUrls,
-          schema.GetKnownProperty(key::kWebUsbAllowDevicesForUrls),
-          SchemaOnErrorStrategy::SCHEMA_ALLOW_UNKNOWN) {}
+          policy_name,
+          chrome_schema.GetKnownProperty(policy_name),
+          SchemaOnErrorStrategy::SCHEMA_ALLOW_UNKNOWN),
+      pref_name_(pref_name) {}
 
 WebUsbAllowDevicesForUrlsPolicyHandler::
     ~WebUsbAllowDevicesForUrlsPolicyHandler() {}
@@ -90,7 +121,7 @@
           device.FindKeyOfType(kProductIdKey, base::Value::Type::INTEGER);
       if (product_id_value) {
         // If a |product_id| is specified, then a |vendor_id| must also be
-        // specified. Otherwise, the device policy is invalid.
+        // specified. Otherwise, the policy is invalid.
         if (vendor_id_value) {
           const int product_id = product_id_value->GetInt();
           if (product_id > 0xFFFF || product_id < 0) {
@@ -181,7 +212,7 @@
   if (!value || !value->is_list())
     return;
 
-  prefs->SetValue(prefs::kManagedWebUsbAllowDevicesForUrls,
+  prefs->SetValue(pref_name_,
                   base::Value::FromUniquePtrValue(std::move(value)));
 }
 
diff --git a/chrome/browser/policy/webusb_allow_devices_for_urls_policy_handler.h b/chrome/browser/policy/webusb_allow_devices_for_urls_policy_handler.h
index 9580c4c..a4a13d2 100644
--- a/chrome/browser/policy/webusb_allow_devices_for_urls_policy_handler.h
+++ b/chrome/browser/policy/webusb_allow_devices_for_urls_policy_handler.h
@@ -5,9 +5,12 @@
 #ifndef CHROME_BROWSER_POLICY_WEBUSB_ALLOW_DEVICES_FOR_URLS_POLICY_HANDLER_H_
 #define CHROME_BROWSER_POLICY_WEBUSB_ALLOW_DEVICES_FOR_URLS_POLICY_HANDLER_H_
 
+#include <memory>
+
 #include "base/macros.h"
 #include "components/policy/core/browser/configuration_policy_handler.h"
 
+class PrefRegistrySimple;
 class PrefValueMap;
 
 namespace policy {
@@ -18,7 +21,19 @@
 class WebUsbAllowDevicesForUrlsPolicyHandler
     : public SchemaValidatingPolicyHandler {
  public:
-  explicit WebUsbAllowDevicesForUrlsPolicyHandler(Schema schema);
+  static std::unique_ptr<WebUsbAllowDevicesForUrlsPolicyHandler>
+  CreateForUserPolicy(const Schema& chrome_schema);
+
+#if defined(OS_CHROMEOS)
+  static std::unique_ptr<WebUsbAllowDevicesForUrlsPolicyHandler>
+  CreateForDevicePolicy(const Schema& chrome_schema);
+
+  static void RegisterPrefs(PrefRegistrySimple* registry);
+#endif  // defined(OS_CHROMEOS)
+
+  WebUsbAllowDevicesForUrlsPolicyHandler(const char* policy_name,
+                                         const char* pref_name,
+                                         const Schema& chrome_schema);
   ~WebUsbAllowDevicesForUrlsPolicyHandler() override;
 
   // ConfigurationPolicyHandler implementation:
@@ -28,6 +43,9 @@
                            PrefValueMap* prefs) override;
 
  private:
+  // The name of the pref to apply the policy to.
+  const char* pref_name_;
+
   DISALLOW_COPY_AND_ASSIGN(WebUsbAllowDevicesForUrlsPolicyHandler);
 };
 
diff --git a/chrome/browser/policy/webusb_allow_devices_for_urls_policy_handler_unittest.cc b/chrome/browser/policy/webusb_allow_devices_for_urls_policy_handler_unittest.cc
index 1c0c1b2..138f1ca 100644
--- a/chrome/browser/policy/webusb_allow_devices_for_urls_policy_handler_unittest.cc
+++ b/chrome/browser/policy/webusb_allow_devices_for_urls_policy_handler_unittest.cc
@@ -10,6 +10,7 @@
 #include "base/json/json_reader.h"
 #include "base/strings/string_util.h"
 #include "base/strings/utf_string_conversions.h"
+#include "chrome/common/pref_names.h"
 #include "components/content_settings/core/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"
@@ -18,11 +19,16 @@
 #include "components/policy/core/common/policy_types.h"
 #include "components/policy/core/common/schema.h"
 #include "components/policy/policy_constants.h"
+#include "testing/gtest/include/gtest/gtest.h"
 
 namespace policy {
 
 namespace {
 
+// For ChromeOS this test is parameterized to test user and device policy. For
+// other operating systems, this test just tests the user policy.
+enum class PolicyType { kUser, kDevice };
+
 constexpr char kDevicesKey[] = "devices";
 constexpr char kUrlsKey[] = "urls";
 constexpr char kVendorIdKey[] = "vendor_id";
@@ -203,6 +209,35 @@
       }
     ])";
 
+std::string GetPolicyName(PolicyType policy_type) {
+#if defined(OS_CHROMEOS)
+  if (policy_type == PolicyType::kDevice)
+    return key::kDeviceLoginScreenWebUsbAllowDevicesForUrls;
+#endif  // defined(OS_CHROMEOS)
+  return key::kWebUsbAllowDevicesForUrls;
+}
+
+std::string GetPrefName(PolicyType policy_type) {
+#if defined(OS_CHROMEOS)
+  if (policy_type == PolicyType::kDevice)
+    return prefs::kDeviceLoginScreenWebUsbAllowDevicesForUrls;
+#endif  // defined(OS_CHROMEOS)
+  return prefs::kManagedWebUsbAllowDevicesForUrls;
+}
+
+std::unique_ptr<WebUsbAllowDevicesForUrlsPolicyHandler> CreateHandler(
+    PolicyType policy_type,
+    const Schema& chrome_schema) {
+#if defined(OS_CHROMEOS)
+  if (policy_type == PolicyType::kDevice) {
+    return WebUsbAllowDevicesForUrlsPolicyHandler::CreateForDevicePolicy(
+        chrome_schema);
+  }
+#endif  // defined(OS_CHROMEOS)
+  return WebUsbAllowDevicesForUrlsPolicyHandler::CreateForUserPolicy(
+      chrome_schema);
+}
+
 std::unique_ptr<base::Value> ReadJson(base::StringPiece json) {
   base::Optional<base::Value> value = base::JSONReader::Read(json);
   EXPECT_TRUE(value);
@@ -212,44 +247,54 @@
 }  // namespace
 
 class WebUsbAllowDevicesForUrlsPolicyHandlerTest
-    : public ConfigurationPolicyPrefStoreTest {
+    : public ConfigurationPolicyPrefStoreTest,
+      public testing::WithParamInterface<PolicyType> {
  public:
+  WebUsbAllowDevicesForUrlsPolicyHandlerTest()
+      : policy_name_(GetPolicyName(GetParam())),
+        pref_name_(GetPrefName(GetParam())) {}
+
   WebUsbAllowDevicesForUrlsPolicyHandler* handler() { return handler_; }
 
+ protected:
+  const std::string policy_name_;
+  const std::string pref_name_;
+
  private:
   void SetUp() override {
     Schema chrome_schema = Schema::Wrap(GetChromeSchemaData());
-    auto handler =
-        std::make_unique<WebUsbAllowDevicesForUrlsPolicyHandler>(chrome_schema);
+    auto handler = CreateHandler(GetParam(), chrome_schema);
     handler_ = handler.get();
     handler_list_.AddHandler(std::move(handler));
   }
 
   WebUsbAllowDevicesForUrlsPolicyHandler* handler_;
+
+  DISALLOW_COPY_AND_ASSIGN(WebUsbAllowDevicesForUrlsPolicyHandlerTest);
 };
 
-TEST_F(WebUsbAllowDevicesForUrlsPolicyHandlerTest, CheckPolicySettings) {
+TEST_P(WebUsbAllowDevicesForUrlsPolicyHandlerTest, CheckPolicySettings) {
   PolicyMap policy;
   PolicyErrorMap errors;
 
-  policy.Set(
-      key::kWebUsbAllowDevicesForUrls, PolicyLevel::POLICY_LEVEL_MANDATORY,
-      PolicyScope::POLICY_SCOPE_MACHINE, PolicySource::POLICY_SOURCE_CLOUD,
-      ReadJson(kValidPolicy), nullptr);
+  policy.Set(policy_name_, PolicyLevel::POLICY_LEVEL_MANDATORY,
+             PolicyScope::POLICY_SCOPE_MACHINE,
+             PolicySource::POLICY_SOURCE_CLOUD, ReadJson(kValidPolicy),
+             nullptr);
   ASSERT_TRUE(errors.empty());
   EXPECT_TRUE(handler()->CheckPolicySettings(policy, &errors));
   EXPECT_TRUE(errors.empty());
 }
 
-TEST_F(WebUsbAllowDevicesForUrlsPolicyHandlerTest,
+TEST_P(WebUsbAllowDevicesForUrlsPolicyHandlerTest,
        CheckPolicySettingsWithInvalidTopLevelEntry) {
   PolicyMap policy;
   PolicyErrorMap errors;
 
-  policy.Set(
-      key::kWebUsbAllowDevicesForUrls, PolicyLevel::POLICY_LEVEL_MANDATORY,
-      PolicyScope::POLICY_SCOPE_MACHINE, PolicySource::POLICY_SOURCE_CLOUD,
-      ReadJson(kInvalidPolicyInvalidTopLevelEntry), nullptr);
+  policy.Set(policy_name_, PolicyLevel::POLICY_LEVEL_MANDATORY,
+             PolicyScope::POLICY_SCOPE_MACHINE,
+             PolicySource::POLICY_SOURCE_CLOUD,
+             ReadJson(kInvalidPolicyInvalidTopLevelEntry), nullptr);
 
   ASSERT_TRUE(errors.empty());
   EXPECT_FALSE(handler()->CheckPolicySettings(policy, &errors));
@@ -258,18 +303,18 @@
   const base::string16 kExpected = base::ASCIIToUTF16(
       "Schema validation error at \"items[1]\": Missing or invalid required "
       "property: devices");
-  EXPECT_EQ(kExpected, errors.GetErrors(key::kWebUsbAllowDevicesForUrls));
+  EXPECT_EQ(kExpected, errors.GetErrors(policy_name_));
 }
 
-TEST_F(WebUsbAllowDevicesForUrlsPolicyHandlerTest,
+TEST_P(WebUsbAllowDevicesForUrlsPolicyHandlerTest,
        CheckPolicySettingsWithMissingDevicesProperty) {
   PolicyMap policy;
   PolicyErrorMap errors;
 
-  policy.Set(
-      key::kWebUsbAllowDevicesForUrls, PolicyLevel::POLICY_LEVEL_MANDATORY,
-      PolicyScope::POLICY_SCOPE_MACHINE, PolicySource::POLICY_SOURCE_CLOUD,
-      ReadJson(kInvalidPolicyMissingDevicesProperty), nullptr);
+  policy.Set(policy_name_, PolicyLevel::POLICY_LEVEL_MANDATORY,
+             PolicyScope::POLICY_SCOPE_MACHINE,
+             PolicySource::POLICY_SOURCE_CLOUD,
+             ReadJson(kInvalidPolicyMissingDevicesProperty), nullptr);
 
   ASSERT_TRUE(errors.empty());
   EXPECT_FALSE(handler()->CheckPolicySettings(policy, &errors));
@@ -278,18 +323,18 @@
   const base::string16 kExpected = base::ASCIIToUTF16(
       "Schema validation error at \"items[0]\": Missing or invalid required "
       "property: devices");
-  EXPECT_EQ(kExpected, errors.GetErrors(key::kWebUsbAllowDevicesForUrls));
+  EXPECT_EQ(kExpected, errors.GetErrors(policy_name_));
 }
 
-TEST_F(WebUsbAllowDevicesForUrlsPolicyHandlerTest,
+TEST_P(WebUsbAllowDevicesForUrlsPolicyHandlerTest,
        CheckPolicySettingsWithMissingUrlsProperty) {
   PolicyMap policy;
   PolicyErrorMap errors;
 
-  policy.Set(
-      key::kWebUsbAllowDevicesForUrls, PolicyLevel::POLICY_LEVEL_MANDATORY,
-      PolicyScope::POLICY_SCOPE_MACHINE, PolicySource::POLICY_SOURCE_CLOUD,
-      ReadJson(kInvalidPolicyMissingUrlsProperty), nullptr);
+  policy.Set(policy_name_, PolicyLevel::POLICY_LEVEL_MANDATORY,
+             PolicyScope::POLICY_SCOPE_MACHINE,
+             PolicySource::POLICY_SOURCE_CLOUD,
+             ReadJson(kInvalidPolicyMissingUrlsProperty), nullptr);
 
   ASSERT_TRUE(errors.empty());
   EXPECT_FALSE(handler()->CheckPolicySettings(policy, &errors));
@@ -298,18 +343,18 @@
   const base::string16 kExpected = base::ASCIIToUTF16(
       "Schema validation error at \"items[0]\": Missing or invalid required "
       "property: urls");
-  EXPECT_EQ(kExpected, errors.GetErrors(key::kWebUsbAllowDevicesForUrls));
+  EXPECT_EQ(kExpected, errors.GetErrors(policy_name_));
 }
 
-TEST_F(WebUsbAllowDevicesForUrlsPolicyHandlerTest,
+TEST_P(WebUsbAllowDevicesForUrlsPolicyHandlerTest,
        CheckPolicySettingsUnknownProperty) {
   PolicyMap policy;
   PolicyErrorMap errors;
 
-  policy.Set(
-      key::kWebUsbAllowDevicesForUrls, PolicyLevel::POLICY_LEVEL_MANDATORY,
-      PolicyScope::POLICY_SCOPE_MACHINE, PolicySource::POLICY_SOURCE_CLOUD,
-      ReadJson(kInvalidPolicyUnknownProperty), nullptr);
+  policy.Set(policy_name_, PolicyLevel::POLICY_LEVEL_MANDATORY,
+             PolicyScope::POLICY_SCOPE_MACHINE,
+             PolicySource::POLICY_SOURCE_CLOUD,
+             ReadJson(kInvalidPolicyUnknownProperty), nullptr);
 
   ASSERT_TRUE(errors.empty());
   EXPECT_TRUE(handler()->CheckPolicySettings(policy, &errors));
@@ -318,38 +363,38 @@
   const base::string16 kExpected = base::ASCIIToUTF16(
       "Schema validation error at \"items[0].devices.items[0]\": Unknown "
       "property: serialNumber");
-  EXPECT_EQ(kExpected, errors.GetErrors(key::kWebUsbAllowDevicesForUrls));
+  EXPECT_EQ(kExpected, errors.GetErrors(policy_name_));
 }
 
-TEST_F(WebUsbAllowDevicesForUrlsPolicyHandlerTest,
+TEST_P(WebUsbAllowDevicesForUrlsPolicyHandlerTest,
        CheckPolicySettingsWithMismatchedVendorIdType) {
   PolicyMap policy;
   PolicyErrorMap errors;
 
-  policy.Set(
-      key::kWebUsbAllowDevicesForUrls, PolicyLevel::POLICY_LEVEL_MANDATORY,
-      PolicyScope::POLICY_SCOPE_MACHINE, PolicySource::POLICY_SOURCE_CLOUD,
-      ReadJson(kInvalidPolicyMismatchedVendorIdType), nullptr);
+  policy.Set(policy_name_, PolicyLevel::POLICY_LEVEL_MANDATORY,
+             PolicyScope::POLICY_SCOPE_MACHINE,
+             PolicySource::POLICY_SOURCE_CLOUD,
+             ReadJson(kInvalidPolicyMismatchedVendorIdType), nullptr);
 
   ASSERT_TRUE(errors.empty());
   EXPECT_FALSE(handler()->CheckPolicySettings(policy, &errors));
   EXPECT_EQ(1ul, errors.size());
 
   const base::string16 kExpected = base::ASCIIToUTF16(
-      "Schema validation error at \"items[0].devices.items[0]\": The vendor_id "
-      "must be an unsigned short integer");
-  EXPECT_EQ(kExpected, errors.GetErrors(key::kWebUsbAllowDevicesForUrls));
+      "Schema validation error at \"items[0].devices.items[0]\": The "
+      "vendor_id must be an unsigned short integer");
+  EXPECT_EQ(kExpected, errors.GetErrors(policy_name_));
 }
 
-TEST_F(WebUsbAllowDevicesForUrlsPolicyHandlerTest,
+TEST_P(WebUsbAllowDevicesForUrlsPolicyHandlerTest,
        CheckPolicySettingsWithMismatchedProductIdType) {
   PolicyMap policy;
   PolicyErrorMap errors;
 
-  policy.Set(
-      key::kWebUsbAllowDevicesForUrls, PolicyLevel::POLICY_LEVEL_MANDATORY,
-      PolicyScope::POLICY_SCOPE_MACHINE, PolicySource::POLICY_SOURCE_CLOUD,
-      ReadJson(kInvalidPolicyMismatchedProductIdType), nullptr);
+  policy.Set(policy_name_, PolicyLevel::POLICY_LEVEL_MANDATORY,
+             PolicyScope::POLICY_SCOPE_MACHINE,
+             PolicySource::POLICY_SOURCE_CLOUD,
+             ReadJson(kInvalidPolicyMismatchedProductIdType), nullptr);
 
   ASSERT_TRUE(errors.empty());
   EXPECT_FALSE(handler()->CheckPolicySettings(policy, &errors));
@@ -358,18 +403,18 @@
   const base::string16 kExpected = base::ASCIIToUTF16(
       "Schema validation error at \"items[0].devices.items[0]\": The "
       "product_id must be an unsigned short integer");
-  EXPECT_EQ(kExpected, errors.GetErrors(key::kWebUsbAllowDevicesForUrls));
+  EXPECT_EQ(kExpected, errors.GetErrors(policy_name_));
 }
 
-TEST_F(WebUsbAllowDevicesForUrlsPolicyHandlerTest,
+TEST_P(WebUsbAllowDevicesForUrlsPolicyHandlerTest,
        CheckPolicySettingsWithProductIdWithoutVendorId) {
   PolicyMap policy;
   PolicyErrorMap errors;
 
-  policy.Set(
-      key::kWebUsbAllowDevicesForUrls, PolicyLevel::POLICY_LEVEL_MANDATORY,
-      PolicyScope::POLICY_SCOPE_MACHINE, PolicySource::POLICY_SOURCE_CLOUD,
-      ReadJson(kInvalidPolicyProductIdWithoutVendorId), nullptr);
+  policy.Set(policy_name_, PolicyLevel::POLICY_LEVEL_MANDATORY,
+             PolicyScope::POLICY_SCOPE_MACHINE,
+             PolicySource::POLICY_SOURCE_CLOUD,
+             ReadJson(kInvalidPolicyProductIdWithoutVendorId), nullptr);
 
   ASSERT_TRUE(errors.empty());
   EXPECT_FALSE(handler()->CheckPolicySettings(policy, &errors));
@@ -378,18 +423,18 @@
   const base::string16 kExpected = base::ASCIIToUTF16(
       "Schema validation error at \"items[0].devices.items[0]\": A vendor_id "
       "must also be specified");
-  EXPECT_EQ(kExpected, errors.GetErrors(key::kWebUsbAllowDevicesForUrls));
+  EXPECT_EQ(kExpected, errors.GetErrors(policy_name_));
 }
 
-TEST_F(WebUsbAllowDevicesForUrlsPolicyHandlerTest,
+TEST_P(WebUsbAllowDevicesForUrlsPolicyHandlerTest,
        CheckPolicySettingsWithInvalidRequestingUrlEntry) {
   PolicyMap policy;
   PolicyErrorMap errors;
 
-  policy.Set(
-      key::kWebUsbAllowDevicesForUrls, PolicyLevel::POLICY_LEVEL_MANDATORY,
-      PolicyScope::POLICY_SCOPE_MACHINE, PolicySource::POLICY_SOURCE_CLOUD,
-      ReadJson(kInvalidPolicyInvalidRequestingUrl), nullptr);
+  policy.Set(policy_name_, PolicyLevel::POLICY_LEVEL_MANDATORY,
+             PolicyScope::POLICY_SCOPE_MACHINE,
+             PolicySource::POLICY_SOURCE_CLOUD,
+             ReadJson(kInvalidPolicyInvalidRequestingUrl), nullptr);
 
   ASSERT_TRUE(errors.empty());
   EXPECT_FALSE(handler()->CheckPolicySettings(policy, &errors));
@@ -398,18 +443,18 @@
   const base::string16 kExpected = base::ASCIIToUTF16(
       "Schema validation error at \"items[0].urls.items[0]\": The urls item "
       "must contain valid URLs");
-  EXPECT_EQ(kExpected, errors.GetErrors(key::kWebUsbAllowDevicesForUrls));
+  EXPECT_EQ(kExpected, errors.GetErrors(policy_name_));
 }
 
-TEST_F(WebUsbAllowDevicesForUrlsPolicyHandlerTest,
+TEST_P(WebUsbAllowDevicesForUrlsPolicyHandlerTest,
        CheckPolicySettingsWithInvalidEmbeddingUrlEntry) {
   PolicyMap policy;
   PolicyErrorMap errors;
 
-  policy.Set(
-      key::kWebUsbAllowDevicesForUrls, PolicyLevel::POLICY_LEVEL_MANDATORY,
-      PolicyScope::POLICY_SCOPE_MACHINE, PolicySource::POLICY_SOURCE_CLOUD,
-      ReadJson(kInvalidPolicyInvalidEmbeddingUrl), nullptr);
+  policy.Set(policy_name_, PolicyLevel::POLICY_LEVEL_MANDATORY,
+             PolicyScope::POLICY_SCOPE_MACHINE,
+             PolicySource::POLICY_SOURCE_CLOUD,
+             ReadJson(kInvalidPolicyInvalidEmbeddingUrl), nullptr);
 
   ASSERT_TRUE(errors.empty());
   EXPECT_FALSE(handler()->CheckPolicySettings(policy, &errors));
@@ -418,18 +463,18 @@
   const base::string16 kExpected = base::ASCIIToUTF16(
       "Schema validation error at \"items[0].urls.items[0]\": The urls item "
       "must contain valid URLs");
-  EXPECT_EQ(kExpected, errors.GetErrors(key::kWebUsbAllowDevicesForUrls));
+  EXPECT_EQ(kExpected, errors.GetErrors(policy_name_));
 }
 
-TEST_F(WebUsbAllowDevicesForUrlsPolicyHandlerTest,
+TEST_P(WebUsbAllowDevicesForUrlsPolicyHandlerTest,
        CheckPolicySettingsWithInvalidUrlsEntry) {
   PolicyMap policy;
   PolicyErrorMap errors;
 
-  policy.Set(
-      key::kWebUsbAllowDevicesForUrls, PolicyLevel::POLICY_LEVEL_MANDATORY,
-      PolicyScope::POLICY_SCOPE_MACHINE, PolicySource::POLICY_SOURCE_CLOUD,
-      ReadJson(kInvalidPolicyInvalidUrlsEntry), nullptr);
+  policy.Set(policy_name_, PolicyLevel::POLICY_LEVEL_MANDATORY,
+             PolicyScope::POLICY_SCOPE_MACHINE,
+             PolicySource::POLICY_SOURCE_CLOUD,
+             ReadJson(kInvalidPolicyInvalidUrlsEntry), nullptr);
 
   ASSERT_TRUE(errors.empty());
   EXPECT_FALSE(handler()->CheckPolicySettings(policy, &errors));
@@ -438,18 +483,18 @@
   const base::string16 kExpected = base::ASCIIToUTF16(
       "Schema validation error at \"items[0].urls.items[0]\": Each urls "
       "string entry must contain between 1 to 2 URLs");
-  EXPECT_EQ(kExpected, errors.GetErrors(key::kWebUsbAllowDevicesForUrls));
+  EXPECT_EQ(kExpected, errors.GetErrors(policy_name_));
 }
 
-TEST_F(WebUsbAllowDevicesForUrlsPolicyHandlerTest,
+TEST_P(WebUsbAllowDevicesForUrlsPolicyHandlerTest,
        CheckPolicySettingsWithNoUrls) {
   PolicyMap policy;
   PolicyErrorMap errors;
 
-  policy.Set(
-      key::kWebUsbAllowDevicesForUrls, PolicyLevel::POLICY_LEVEL_MANDATORY,
-      PolicyScope::POLICY_SCOPE_MACHINE, PolicySource::POLICY_SOURCE_CLOUD,
-      ReadJson(InvalidPolicyNoUrls), nullptr);
+  policy.Set(policy_name_, PolicyLevel::POLICY_LEVEL_MANDATORY,
+             PolicyScope::POLICY_SCOPE_MACHINE,
+             PolicySource::POLICY_SOURCE_CLOUD, ReadJson(InvalidPolicyNoUrls),
+             nullptr);
 
   ASSERT_TRUE(errors.empty());
   EXPECT_FALSE(handler()->CheckPolicySettings(policy, &errors));
@@ -458,23 +503,21 @@
   const base::string16 kExpected = base::ASCIIToUTF16(
       "Schema validation error at \"items[0].urls.items[0]\": Each urls "
       "string entry must contain between 1 to 2 URLs");
-  EXPECT_EQ(kExpected, errors.GetErrors(key::kWebUsbAllowDevicesForUrls));
+  EXPECT_EQ(kExpected, errors.GetErrors(policy_name_));
 }
 
-TEST_F(WebUsbAllowDevicesForUrlsPolicyHandlerTest, ApplyPolicySettings) {
-  EXPECT_FALSE(
-      store_->GetValue(prefs::kManagedWebUsbAllowDevicesForUrls, nullptr));
+TEST_P(WebUsbAllowDevicesForUrlsPolicyHandlerTest, ApplyPolicySettings) {
+  EXPECT_FALSE(store_->GetValue(pref_name_, nullptr));
 
   PolicyMap policy;
-  policy.Set(
-      key::kWebUsbAllowDevicesForUrls, PolicyLevel::POLICY_LEVEL_MANDATORY,
-      PolicyScope::POLICY_SCOPE_MACHINE, PolicySource::POLICY_SOURCE_CLOUD,
-      ReadJson(kValidPolicy), nullptr);
+  policy.Set(policy_name_, PolicyLevel::POLICY_LEVEL_MANDATORY,
+             PolicyScope::POLICY_SCOPE_MACHINE,
+             PolicySource::POLICY_SOURCE_CLOUD, ReadJson(kValidPolicy),
+             nullptr);
   UpdateProviderPolicy(policy);
 
   const base::Value* pref_value = nullptr;
-  EXPECT_TRUE(
-      store_->GetValue(prefs::kManagedWebUsbAllowDevicesForUrls, &pref_value));
+  EXPECT_TRUE(store_->GetValue(pref_name_, &pref_value));
   ASSERT_TRUE(pref_value);
   ASSERT_TRUE(pref_value->is_list());
 
@@ -539,72 +582,64 @@
   EXPECT_EQ("https://chromium.org,", second_urls_list[0].GetString());
 }
 
-TEST_F(WebUsbAllowDevicesForUrlsPolicyHandlerTest,
+TEST_P(WebUsbAllowDevicesForUrlsPolicyHandlerTest,
        ApplyPolicySettingsWithInvalidTopLevelEntry) {
-  EXPECT_FALSE(
-      store_->GetValue(prefs::kManagedWebUsbAllowDevicesForUrls, nullptr));
+  EXPECT_FALSE(store_->GetValue(pref_name_, nullptr));
 
   PolicyMap policy;
-  policy.Set(
-      key::kWebUsbAllowDevicesForUrls, PolicyLevel::POLICY_LEVEL_MANDATORY,
-      PolicyScope::POLICY_SCOPE_MACHINE, PolicySource::POLICY_SOURCE_CLOUD,
-      ReadJson(kInvalidPolicyInvalidTopLevelEntry), nullptr);
+  policy.Set(policy_name_, PolicyLevel::POLICY_LEVEL_MANDATORY,
+             PolicyScope::POLICY_SCOPE_MACHINE,
+             PolicySource::POLICY_SOURCE_CLOUD,
+             ReadJson(kInvalidPolicyInvalidTopLevelEntry), nullptr);
   UpdateProviderPolicy(policy);
 
   const base::Value* pref_value = nullptr;
-  EXPECT_FALSE(
-      store_->GetValue(prefs::kManagedWebUsbAllowDevicesForUrls, &pref_value));
+  EXPECT_FALSE(store_->GetValue(pref_name_, &pref_value));
   EXPECT_FALSE(pref_value);
 }
 
-TEST_F(WebUsbAllowDevicesForUrlsPolicyHandlerTest,
+TEST_P(WebUsbAllowDevicesForUrlsPolicyHandlerTest,
        ApplyPolicySettingsWithMissingDevicesProperty) {
-  EXPECT_FALSE(
-      store_->GetValue(prefs::kManagedWebUsbAllowDevicesForUrls, nullptr));
+  EXPECT_FALSE(store_->GetValue(pref_name_, nullptr));
 
   PolicyMap policy;
-  policy.Set(
-      key::kWebUsbAllowDevicesForUrls, PolicyLevel::POLICY_LEVEL_MANDATORY,
-      PolicyScope::POLICY_SCOPE_MACHINE, PolicySource::POLICY_SOURCE_CLOUD,
-      ReadJson(kInvalidPolicyMissingDevicesProperty), nullptr);
+  policy.Set(policy_name_, PolicyLevel::POLICY_LEVEL_MANDATORY,
+             PolicyScope::POLICY_SCOPE_MACHINE,
+             PolicySource::POLICY_SOURCE_CLOUD,
+             ReadJson(kInvalidPolicyMissingDevicesProperty), nullptr);
   UpdateProviderPolicy(policy);
   const base::Value* pref_value = nullptr;
-  EXPECT_FALSE(
-      store_->GetValue(prefs::kManagedWebUsbAllowDevicesForUrls, &pref_value));
+  EXPECT_FALSE(store_->GetValue(pref_name_, &pref_value));
   EXPECT_FALSE(pref_value);
 }
 
-TEST_F(WebUsbAllowDevicesForUrlsPolicyHandlerTest,
+TEST_P(WebUsbAllowDevicesForUrlsPolicyHandlerTest,
        ApplyPolicySettingsWithMissingUrlsProperty) {
-  EXPECT_FALSE(
-      store_->GetValue(prefs::kManagedWebUsbAllowDevicesForUrls, nullptr));
+  EXPECT_FALSE(store_->GetValue(pref_name_, nullptr));
 
   PolicyMap policy;
-  policy.Set(
-      key::kWebUsbAllowDevicesForUrls, PolicyLevel::POLICY_LEVEL_MANDATORY,
-      PolicyScope::POLICY_SCOPE_MACHINE, PolicySource::POLICY_SOURCE_CLOUD,
-      ReadJson(kInvalidPolicyMissingUrlsProperty), nullptr);
+  policy.Set(policy_name_, PolicyLevel::POLICY_LEVEL_MANDATORY,
+             PolicyScope::POLICY_SCOPE_MACHINE,
+             PolicySource::POLICY_SOURCE_CLOUD,
+             ReadJson(kInvalidPolicyMissingUrlsProperty), nullptr);
   UpdateProviderPolicy(policy);
   const base::Value* pref_value = nullptr;
-  EXPECT_FALSE(
-      store_->GetValue(prefs::kManagedWebUsbAllowDevicesForUrls, &pref_value));
+  EXPECT_FALSE(store_->GetValue(pref_name_, &pref_value));
   EXPECT_FALSE(pref_value);
 }
 
-TEST_F(WebUsbAllowDevicesForUrlsPolicyHandlerTest,
+TEST_P(WebUsbAllowDevicesForUrlsPolicyHandlerTest,
        ApplyPolicySettingsWithUnknownProperty) {
-  EXPECT_FALSE(
-      store_->GetValue(prefs::kManagedWebUsbAllowDevicesForUrls, nullptr));
+  EXPECT_FALSE(store_->GetValue(pref_name_, nullptr));
 
   PolicyMap policy;
-  policy.Set(
-      key::kWebUsbAllowDevicesForUrls, PolicyLevel::POLICY_LEVEL_MANDATORY,
-      PolicyScope::POLICY_SCOPE_MACHINE, PolicySource::POLICY_SOURCE_CLOUD,
-      ReadJson(kInvalidPolicyUnknownProperty), nullptr);
+  policy.Set(policy_name_, PolicyLevel::POLICY_LEVEL_MANDATORY,
+             PolicyScope::POLICY_SCOPE_MACHINE,
+             PolicySource::POLICY_SOURCE_CLOUD,
+             ReadJson(kInvalidPolicyUnknownProperty), nullptr);
   UpdateProviderPolicy(policy);
   const base::Value* pref_value = nullptr;
-  EXPECT_TRUE(
-      store_->GetValue(prefs::kManagedWebUsbAllowDevicesForUrls, &pref_value));
+  EXPECT_TRUE(store_->GetValue(pref_name_, &pref_value));
   EXPECT_TRUE(pref_value);
 
   std::unique_ptr<base::Value> expected_pref_value =
@@ -612,122 +647,119 @@
   EXPECT_EQ(*expected_pref_value, *pref_value);
 }
 
-TEST_F(WebUsbAllowDevicesForUrlsPolicyHandlerTest,
+TEST_P(WebUsbAllowDevicesForUrlsPolicyHandlerTest,
        ApplyPolicySettingsWithMismatchedVendorIdType) {
-  EXPECT_FALSE(
-      store_->GetValue(prefs::kManagedWebUsbAllowDevicesForUrls, nullptr));
+  EXPECT_FALSE(store_->GetValue(pref_name_, nullptr));
 
   PolicyMap policy;
-  policy.Set(
-      key::kWebUsbAllowDevicesForUrls, PolicyLevel::POLICY_LEVEL_MANDATORY,
-      PolicyScope::POLICY_SCOPE_MACHINE, PolicySource::POLICY_SOURCE_CLOUD,
-      ReadJson(kInvalidPolicyMismatchedVendorIdType), nullptr);
+  policy.Set(policy_name_, PolicyLevel::POLICY_LEVEL_MANDATORY,
+             PolicyScope::POLICY_SCOPE_MACHINE,
+             PolicySource::POLICY_SOURCE_CLOUD,
+             ReadJson(kInvalidPolicyMismatchedVendorIdType), nullptr);
   UpdateProviderPolicy(policy);
   const base::Value* pref_value = nullptr;
-  EXPECT_FALSE(
-      store_->GetValue(prefs::kManagedWebUsbAllowDevicesForUrls, &pref_value));
+  EXPECT_FALSE(store_->GetValue(pref_name_, &pref_value));
   EXPECT_FALSE(pref_value);
 }
 
-TEST_F(WebUsbAllowDevicesForUrlsPolicyHandlerTest,
+TEST_P(WebUsbAllowDevicesForUrlsPolicyHandlerTest,
        ApplyPolicySettingsWithMismatchedProductIdType) {
-  EXPECT_FALSE(
-      store_->GetValue(prefs::kManagedWebUsbAllowDevicesForUrls, nullptr));
+  EXPECT_FALSE(store_->GetValue(pref_name_, nullptr));
 
   PolicyMap policy;
-  policy.Set(
-      key::kWebUsbAllowDevicesForUrls, PolicyLevel::POLICY_LEVEL_MANDATORY,
-      PolicyScope::POLICY_SCOPE_MACHINE, PolicySource::POLICY_SOURCE_CLOUD,
-      ReadJson(kInvalidPolicyMismatchedProductIdType), nullptr);
+  policy.Set(policy_name_, PolicyLevel::POLICY_LEVEL_MANDATORY,
+             PolicyScope::POLICY_SCOPE_MACHINE,
+             PolicySource::POLICY_SOURCE_CLOUD,
+             ReadJson(kInvalidPolicyMismatchedProductIdType), nullptr);
   UpdateProviderPolicy(policy);
   const base::Value* pref_value = nullptr;
-  EXPECT_FALSE(
-      store_->GetValue(prefs::kManagedWebUsbAllowDevicesForUrls, &pref_value));
+  EXPECT_FALSE(store_->GetValue(pref_name_, &pref_value));
   EXPECT_FALSE(pref_value);
 }
 
-TEST_F(WebUsbAllowDevicesForUrlsPolicyHandlerTest,
+TEST_P(WebUsbAllowDevicesForUrlsPolicyHandlerTest,
        ApplyPolicySettingsProductIdWithoutVendorId) {
-  EXPECT_FALSE(
-      store_->GetValue(prefs::kManagedWebUsbAllowDevicesForUrls, nullptr));
+  EXPECT_FALSE(store_->GetValue(pref_name_, nullptr));
 
   PolicyMap policy;
-  policy.Set(
-      key::kWebUsbAllowDevicesForUrls, PolicyLevel::POLICY_LEVEL_MANDATORY,
-      PolicyScope::POLICY_SCOPE_MACHINE, PolicySource::POLICY_SOURCE_CLOUD,
-      ReadJson(kInvalidPolicyProductIdWithoutVendorId), nullptr);
+  policy.Set(policy_name_, PolicyLevel::POLICY_LEVEL_MANDATORY,
+             PolicyScope::POLICY_SCOPE_MACHINE,
+             PolicySource::POLICY_SOURCE_CLOUD,
+             ReadJson(kInvalidPolicyProductIdWithoutVendorId), nullptr);
   UpdateProviderPolicy(policy);
   const base::Value* pref_value = nullptr;
-  EXPECT_FALSE(
-      store_->GetValue(prefs::kManagedWebUsbAllowDevicesForUrls, &pref_value));
+  EXPECT_FALSE(store_->GetValue(pref_name_, &pref_value));
   EXPECT_FALSE(pref_value);
 }
 
-TEST_F(WebUsbAllowDevicesForUrlsPolicyHandlerTest,
+TEST_P(WebUsbAllowDevicesForUrlsPolicyHandlerTest,
        ApplyPolicySettingsInvalidRequestingUrl) {
-  EXPECT_FALSE(
-      store_->GetValue(prefs::kManagedWebUsbAllowDevicesForUrls, nullptr));
+  EXPECT_FALSE(store_->GetValue(pref_name_, nullptr));
 
   PolicyMap policy;
-  policy.Set(
-      key::kWebUsbAllowDevicesForUrls, PolicyLevel::POLICY_LEVEL_MANDATORY,
-      PolicyScope::POLICY_SCOPE_MACHINE, PolicySource::POLICY_SOURCE_CLOUD,
-      ReadJson(kInvalidPolicyInvalidRequestingUrl), nullptr);
+  policy.Set(policy_name_, PolicyLevel::POLICY_LEVEL_MANDATORY,
+             PolicyScope::POLICY_SCOPE_MACHINE,
+             PolicySource::POLICY_SOURCE_CLOUD,
+             ReadJson(kInvalidPolicyInvalidRequestingUrl), nullptr);
   UpdateProviderPolicy(policy);
   const base::Value* pref_value = nullptr;
-  EXPECT_FALSE(
-      store_->GetValue(prefs::kManagedWebUsbAllowDevicesForUrls, &pref_value));
+  EXPECT_FALSE(store_->GetValue(pref_name_, &pref_value));
   EXPECT_FALSE(pref_value);
 }
 
-TEST_F(WebUsbAllowDevicesForUrlsPolicyHandlerTest,
+TEST_P(WebUsbAllowDevicesForUrlsPolicyHandlerTest,
        ApplyPolicySettingsInvalidEmbeddingUrl) {
-  EXPECT_FALSE(
-      store_->GetValue(prefs::kManagedWebUsbAllowDevicesForUrls, nullptr));
+  EXPECT_FALSE(store_->GetValue(pref_name_, nullptr));
 
   PolicyMap policy;
-  policy.Set(
-      key::kWebUsbAllowDevicesForUrls, PolicyLevel::POLICY_LEVEL_MANDATORY,
-      PolicyScope::POLICY_SCOPE_MACHINE, PolicySource::POLICY_SOURCE_CLOUD,
-      ReadJson(kInvalidPolicyInvalidEmbeddingUrl), nullptr);
+  policy.Set(policy_name_, PolicyLevel::POLICY_LEVEL_MANDATORY,
+             PolicyScope::POLICY_SCOPE_MACHINE,
+             PolicySource::POLICY_SOURCE_CLOUD,
+             ReadJson(kInvalidPolicyInvalidEmbeddingUrl), nullptr);
   UpdateProviderPolicy(policy);
   const base::Value* pref_value = nullptr;
-  EXPECT_FALSE(
-      store_->GetValue(prefs::kManagedWebUsbAllowDevicesForUrls, &pref_value));
+  EXPECT_FALSE(store_->GetValue(pref_name_, &pref_value));
   EXPECT_FALSE(pref_value);
 }
 
-TEST_F(WebUsbAllowDevicesForUrlsPolicyHandlerTest,
+TEST_P(WebUsbAllowDevicesForUrlsPolicyHandlerTest,
        ApplyPolicySettingsInvalidUrlsEntry) {
-  EXPECT_FALSE(
-      store_->GetValue(prefs::kManagedWebUsbAllowDevicesForUrls, nullptr));
+  EXPECT_FALSE(store_->GetValue(pref_name_, nullptr));
 
   PolicyMap policy;
-  policy.Set(
-      key::kWebUsbAllowDevicesForUrls, PolicyLevel::POLICY_LEVEL_MANDATORY,
-      PolicyScope::POLICY_SCOPE_MACHINE, PolicySource::POLICY_SOURCE_CLOUD,
-      ReadJson(kInvalidPolicyInvalidUrlsEntry), nullptr);
+  policy.Set(policy_name_, PolicyLevel::POLICY_LEVEL_MANDATORY,
+             PolicyScope::POLICY_SCOPE_MACHINE,
+             PolicySource::POLICY_SOURCE_CLOUD,
+             ReadJson(kInvalidPolicyInvalidUrlsEntry), nullptr);
   UpdateProviderPolicy(policy);
   const base::Value* pref_value = nullptr;
-  EXPECT_FALSE(
-      store_->GetValue(prefs::kManagedWebUsbAllowDevicesForUrls, &pref_value));
+  EXPECT_FALSE(store_->GetValue(pref_name_, &pref_value));
   EXPECT_FALSE(pref_value);
 }
 
-TEST_F(WebUsbAllowDevicesForUrlsPolicyHandlerTest, ApplyPolicySettingsNoUrls) {
-  EXPECT_FALSE(
-      store_->GetValue(prefs::kManagedWebUsbAllowDevicesForUrls, nullptr));
+TEST_P(WebUsbAllowDevicesForUrlsPolicyHandlerTest, ApplyPolicySettingsNoUrls) {
+  EXPECT_FALSE(store_->GetValue(pref_name_, nullptr));
 
   PolicyMap policy;
-  policy.Set(
-      key::kWebUsbAllowDevicesForUrls, PolicyLevel::POLICY_LEVEL_MANDATORY,
-      PolicyScope::POLICY_SCOPE_MACHINE, PolicySource::POLICY_SOURCE_CLOUD,
-      ReadJson(InvalidPolicyNoUrls), nullptr);
+  policy.Set(policy_name_, PolicyLevel::POLICY_LEVEL_MANDATORY,
+             PolicyScope::POLICY_SCOPE_MACHINE,
+             PolicySource::POLICY_SOURCE_CLOUD, ReadJson(InvalidPolicyNoUrls),
+             nullptr);
   UpdateProviderPolicy(policy);
   const base::Value* pref_value = nullptr;
-  EXPECT_FALSE(
-      store_->GetValue(prefs::kManagedWebUsbAllowDevicesForUrls, &pref_value));
+  EXPECT_FALSE(store_->GetValue(pref_name_, &pref_value));
   EXPECT_FALSE(pref_value);
 }
 
+// For ChromeOS this test is parameterized to test user and device policy. For
+// other operating systems, this test just tests the user policy.
+INSTANTIATE_TEST_SUITE_P(,
+                         WebUsbAllowDevicesForUrlsPolicyHandlerTest,
+#if defined(OS_CHROMEOS)
+                         testing::Values(PolicyType::kUser, PolicyType::kDevice)
+#else
+                         testing::Values(PolicyType::kUser)
+#endif
+);
+
 }  // namespace policy
diff --git a/chrome/browser/prefs/browser_prefs.cc b/chrome/browser/prefs/browser_prefs.cc
index 45e09c1..ce7a864 100644
--- a/chrome/browser/prefs/browser_prefs.cc
+++ b/chrome/browser/prefs/browser_prefs.cc
@@ -45,6 +45,7 @@
 #include "chrome/browser/notifications/platform_notification_service_impl.h"
 #include "chrome/browser/pepper_flash_settings_manager.h"
 #include "chrome/browser/policy/developer_tools_policy_handler.h"
+#include "chrome/browser/policy/webusb_allow_devices_for_urls_policy_handler.h"
 #include "chrome/browser/prefs/chrome_pref_service_factory.h"
 #include "chrome/browser/prefs/incognito_mode_prefs.h"
 #include "chrome/browser/prefs/origin_trial_prefs.h"
@@ -700,6 +701,7 @@
   policy::DMTokenStorage::RegisterPrefs(registry);
   policy::PolicyCertServiceFactory::RegisterPrefs(registry);
   policy::TPMAutoUpdateModePolicyHandler::RegisterPrefs(registry);
+  policy::WebUsbAllowDevicesForUrlsPolicyHandler::RegisterPrefs(registry);
   quirks::QuirksManager::RegisterPrefs(registry);
   UpgradeDetectorChromeos::RegisterPrefs(registry);
   syncer::PerUserTopicRegistrationManager::RegisterPrefs(registry);
diff --git a/chrome/browser/usb/usb_chooser_context.cc b/chrome/browser/usb/usb_chooser_context.cc
index d38392d..5f8ccef 100644
--- a/chrome/browser/usb/usb_chooser_context.cc
+++ b/chrome/browser/usb/usb_chooser_context.cc
@@ -15,10 +15,13 @@
 #include "base/threading/sequenced_task_runner_handle.h"
 #include "base/values.h"
 #include "build/build_config.h"
+#include "chrome/browser/browser_process.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/usb/usb_blocklist.h"
+#include "chrome/common/pref_names.h"
 #include "chrome/grit/generated_resources.h"
 #include "components/content_settings/core/common/content_settings.h"
+#include "components/content_settings/core/common/pref_names.h"
 #include "content/public/browser/system_connector.h"
 #include "services/device/public/cpp/usb/usb_ids.h"
 #include "services/device/public/mojom/constants.mojom.h"
@@ -26,6 +29,10 @@
 #include "services/service_manager/public/cpp/connector.h"
 #include "ui/base/l10n/l10n_util.h"
 
+#if defined(OS_CHROMEOS)
+#include "chrome/browser/chromeos/profiles/profile_helper.h"
+#endif  // defined(OS_CHROMEOS)
+
 namespace {
 
 constexpr char kDeviceNameKey[] = "name";
@@ -130,8 +137,21 @@
                          CONTENT_SETTINGS_TYPE_USB_GUARD,
                          CONTENT_SETTINGS_TYPE_USB_CHOOSER_DATA),
       is_incognito_(profile->IsOffTheRecord()) {
+#if defined(OS_CHROMEOS)
+  bool is_signin_profile = chromeos::ProfileHelper::IsSigninProfile(profile);
+  PrefService* pref_service = is_signin_profile
+                                  ? g_browser_process->local_state()
+                                  : profile->GetPrefs();
+  const char* pref_name =
+      is_signin_profile ? prefs::kDeviceLoginScreenWebUsbAllowDevicesForUrls
+                        : prefs::kManagedWebUsbAllowDevicesForUrls;
+#else   // defined(OS_CHROMEOS)
+  PrefService* pref_service = profile->GetPrefs();
+  const char* pref_name = prefs::kManagedWebUsbAllowDevicesForUrls;
+#endif  // defined(OS_CHROMEOS)
+
   usb_policy_allowed_devices_.reset(
-      new UsbPolicyAllowedDevices(profile->GetPrefs()));
+      new UsbPolicyAllowedDevices(pref_service, pref_name));
 }
 
 // static
diff --git a/chrome/browser/usb/usb_chooser_context_unittest.cc b/chrome/browser/usb/usb_chooser_context_unittest.cc
index f9de110..9817e24 100644
--- a/chrome/browser/usb/usb_chooser_context_unittest.cc
+++ b/chrome/browser/usb/usb_chooser_context_unittest.cc
@@ -14,6 +14,10 @@
 #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/common/pref_names.h"
+#include "chrome/test/base/scoped_testing_local_state.h"
+#include "chrome/test/base/testing_browser_process.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"
@@ -593,6 +597,82 @@
                                          *unrelated_device_info));
 }
 
+#if defined(OS_CHROMEOS)
+
+class DeviceLoginScreenWebUsbChooserContextTest : public UsbChooserContextTest {
+ public:
+  DeviceLoginScreenWebUsbChooserContextTest()
+      : testing_local_state_(TestingBrowserProcess::GetGlobal()) {
+    TestingProfile::Builder builder;
+    builder.SetPath(base::FilePath(FILE_PATH_LITERAL(chrome::kInitialProfile)));
+    signin_profile_ = builder.Build();
+  }
+  ~DeviceLoginScreenWebUsbChooserContextTest() override {}
+
+ protected:
+  Profile* GetSigninProfile() { return signin_profile_.get(); }
+
+ private:
+  ScopedTestingLocalState testing_local_state_;
+  std::unique_ptr<Profile> signin_profile_;
+};
+
+TEST_F(DeviceLoginScreenWebUsbChooserContextTest,
+       UserUsbChooserContextOnlyUsesUserPolicy) {
+  const std::vector<GURL> kValidRequestingOrigins = {kProductVendorUrl,
+                                                     kVendorUrl, kAnyDeviceUrl};
+  const std::vector<GURL> kInvalidRequestingOrigins = {kGadgetUrl, 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()->Set(
+      prefs::kManagedWebUsbAllowDevicesForUrls,
+      *base::JSONReader::ReadDeprecated(kPolicySetting));
+
+  ExpectCorrectPermissions(user_store, kValidRequestingOrigins,
+                           kInvalidRequestingOrigins, *specific_device_info);
+  ExpectNoPermissions(signin_store, *specific_device_info);
+}
+
+TEST_F(DeviceLoginScreenWebUsbChooserContextTest,
+       SigninUsbChooserContextOnlyUsesDevicePolicy) {
+  const std::vector<GURL> kValidRequestingOrigins = {kProductVendorUrl,
+                                                     kVendorUrl, kAnyDeviceUrl};
+  const std::vector<GURL> kInvalidRequestingOrigins = {kGadgetUrl, 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);
+
+  g_browser_process->local_state()->Set(
+      prefs::kDeviceLoginScreenWebUsbAllowDevicesForUrls,
+      *base::JSONReader::ReadDeprecated(kPolicySetting));
+
+  ExpectNoPermissions(user_store, *specific_device_info);
+  ExpectCorrectPermissions(signin_store, kValidRequestingOrigins,
+                           kInvalidRequestingOrigins, *specific_device_info);
+}
+
+#endif  // defined(OS_CHROMEOS)
+
 namespace {
 
 void ExpectDeviceObjectInfo(const base::Value& actual,
diff --git a/chrome/browser/usb/usb_policy_allowed_devices.cc b/chrome/browser/usb/usb_policy_allowed_devices.cc
index bcc26f0..b1298b4 100644
--- a/chrome/browser/usb/usb_policy_allowed_devices.cc
+++ b/chrome/browser/usb/usb_policy_allowed_devices.cc
@@ -10,7 +10,6 @@
 #include "base/bind.h"
 #include "base/strings/string_split.h"
 #include "base/values.h"
-#include "components/content_settings/core/common/pref_names.h"
 #include "components/prefs/pref_service.h"
 #include "services/device/public/mojom/usb_device.mojom.h"
 #include "services/device/public/mojom/usb_manager.mojom.h"
@@ -42,14 +41,15 @@
 
 }  // namespace
 
-UsbPolicyAllowedDevices::UsbPolicyAllowedDevices(PrefService* pref_service) {
+UsbPolicyAllowedDevices::UsbPolicyAllowedDevices(PrefService* pref_service,
+                                                 const char* pref_name)
+    : pref_name_(pref_name) {
   pref_change_registrar_.Init(pref_service);
-  // Add an observer for |kManagedWebUsbAllowDevicesForUrls| to call
-  // CreateOrUpdateMap when the value is changed. The lifetime of
-  // |pref_change_registrar_| is managed by this class, therefore it is safe to
-  // use base::Unretained here.
+  // Add an observer for |pref_name| to call CreateOrUpdateMap when the value is
+  // changed. The lifetime of |pref_change_registrar_| is managed by this class,
+  // therefore it is safe to use base::Unretained here.
   pref_change_registrar_.Add(
-      prefs::kManagedWebUsbAllowDevicesForUrls,
+      pref_name,
       base::BindRepeating(&UsbPolicyAllowedDevices::CreateOrUpdateMap,
                           base::Unretained(this)));
 
@@ -92,8 +92,8 @@
 }
 
 void UsbPolicyAllowedDevices::CreateOrUpdateMap() {
-  const base::Value* pref_value = pref_change_registrar_.prefs()->Get(
-      prefs::kManagedWebUsbAllowDevicesForUrls);
+  const base::Value* pref_value =
+      pref_change_registrar_.prefs()->Get(pref_name_);
   usb_device_ids_to_urls_.clear();
 
   // A policy has not been assigned.
diff --git a/chrome/browser/usb/usb_policy_allowed_devices.h b/chrome/browser/usb/usb_policy_allowed_devices.h
index ae80213..1497744 100644
--- a/chrome/browser/usb/usb_policy_allowed_devices.h
+++ b/chrome/browser/usb/usb_policy_allowed_devices.h
@@ -23,11 +23,12 @@
 class PrefService;
 
 // This class is used to initialize a UsbDeviceIdsToUrlsMap from the
-// preference value for the WebUsbAllowDevicesForUrls policy. The map
-// provides an efficient method of checking if a particular device is allowed to
-// be used by the given requesting and embedding origins. Additionally, this
-// class also uses |pref_change_registrar_| to observe for changes to the
-// preference value so that the map can be updated accordingly.
+// preference value for the WebUsbAllowDevicesForUrls or
+// DeviceLoginScreenWebUsbAllowDevicesForUrls policy. The map provides an
+// efficient method of checking if a particular device is allowed to be used by
+// the given requesting and embedding origins. Additionally, this class also
+// uses |pref_change_registrar_| to observe for changes to the preference value
+// so that the map can be updated accordingly.
 class UsbPolicyAllowedDevices {
  public:
   // A map of device IDs to a set of origins stored in a std::pair. The device
@@ -41,8 +42,8 @@
                std::set<std::pair<url::Origin, base::Optional<url::Origin>>>>;
 
   // Initializes |pref_change_registrar_| with |pref_service| and adds an
-  // an observer for the pref path |kManagedWebUsbAllowDevicesForUrls|.
-  explicit UsbPolicyAllowedDevices(PrefService* pref_service);
+  // an observer for the |pref_name|.
+  UsbPolicyAllowedDevices(PrefService* pref_service, const char* pref_name);
   ~UsbPolicyAllowedDevices();
 
   // Checks if |requesting_origin| (when embedded within |embedding_origin|) is
@@ -58,11 +59,12 @@
 
  private:
   // Creates or updates the |usb_device_ids_to_urls_| map using the
-  // pref at the path |kManagedWebUsbAllowDevicesForUrls|. The existing map is
-  // cleared to ensure that previous pref settings are removed.
+  // pref at |pref_name_|. The existing map is cleared to ensure that previous
+  // pref settings are removed.
   void CreateOrUpdateMap();
 
   // Allow for this class to observe changes to the pref value.
+  const char* pref_name_;
   PrefChangeRegistrar pref_change_registrar_;
   UsbDeviceIdsToUrlsMap usb_device_ids_to_urls_;
 };
diff --git a/chrome/browser/usb/usb_policy_allowed_devices_unittest.cc b/chrome/browser/usb/usb_policy_allowed_devices_unittest.cc
index 9ea6ad9..5527a87 100644
--- a/chrome/browser/usb/usb_policy_allowed_devices_unittest.cc
+++ b/chrome/browser/usb/usb_policy_allowed_devices_unittest.cc
@@ -32,6 +32,11 @@
  protected:
   Profile* profile() { return &profile_; }
 
+  std::unique_ptr<UsbPolicyAllowedDevices> CreateUsbPolicyAllowedDevices() {
+    return std::make_unique<UsbPolicyAllowedDevices>(
+        profile()->GetPrefs(), prefs::kManagedWebUsbAllowDevicesForUrls);
+  }
+
   device::FakeUsbDeviceManager device_manager_;
 
  private:
@@ -39,11 +44,16 @@
   TestingProfile profile_;
 };
 
+std::unique_ptr<base::Value> ReadJson(base::StringPiece json) {
+  base::Optional<base::Value> value = base::JSONReader::Read(json);
+  EXPECT_TRUE(value);
+  return value ? base::Value::ToUniquePtrValue(std::move(*value)) : nullptr;
+}
+
 }  // namespace
 
 TEST_F(UsbPolicyAllowedDevicesTest, InitializeWithMissingPrefValue) {
-  auto usb_policy_allowed_devices =
-      std::make_unique<UsbPolicyAllowedDevices>(profile()->GetPrefs());
+  auto usb_policy_allowed_devices = CreateUsbPolicyAllowedDevices();
 
   EXPECT_TRUE(usb_policy_allowed_devices->map().empty());
 }
@@ -53,8 +63,7 @@
 
   SetWebUsbAllowDevicesForUrlsPrefValue(pref_value);
 
-  auto usb_policy_allowed_devices =
-      std::make_unique<UsbPolicyAllowedDevices>(profile()->GetPrefs());
+  auto usb_policy_allowed_devices = CreateUsbPolicyAllowedDevices();
 
   EXPECT_TRUE(usb_policy_allowed_devices->map().empty());
 }
@@ -94,13 +103,11 @@
 }  // namespace
 
 TEST_F(UsbPolicyAllowedDevicesTest, InitializeWithExistingPrefValue) {
-  std::unique_ptr<base::Value> pref_value =
-      base::JSONReader::ReadDeprecated(kPolicySetting);
+  std::unique_ptr<base::Value> pref_value = ReadJson(kPolicySetting);
 
   SetWebUsbAllowDevicesForUrlsPrefValue(*pref_value);
 
-  auto usb_policy_allowed_devices =
-      std::make_unique<UsbPolicyAllowedDevices>(profile()->GetPrefs());
+  auto usb_policy_allowed_devices = CreateUsbPolicyAllowedDevices();
 
   const UsbPolicyAllowedDevices::UsbDeviceIdsToUrlsMap& map =
       usb_policy_allowed_devices->map();
@@ -132,13 +139,11 @@
 
 TEST_F(UsbPolicyAllowedDevicesTest,
        InitializeWithMissingPolicyThenUpdatePolicy) {
-  auto usb_policy_allowed_devices =
-      std::make_unique<UsbPolicyAllowedDevices>(profile()->GetPrefs());
+  auto usb_policy_allowed_devices = CreateUsbPolicyAllowedDevices();
   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);
+  std::unique_ptr<base::Value> pref_value = ReadJson(kPolicySetting);
 
   SetWebUsbAllowDevicesForUrlsPrefValue(*pref_value);
 
@@ -172,13 +177,11 @@
 
 TEST_F(UsbPolicyAllowedDevicesTest,
        InitializeWithExistingPolicyThenRemovePolicy) {
-  std::unique_ptr<base::Value> pref_value =
-      base::JSONReader::ReadDeprecated(kPolicySetting);
+  std::unique_ptr<base::Value> pref_value = ReadJson(kPolicySetting);
 
   SetWebUsbAllowDevicesForUrlsPrefValue(*pref_value);
 
-  auto usb_policy_allowed_devices =
-      std::make_unique<UsbPolicyAllowedDevices>(profile()->GetPrefs());
+  auto usb_policy_allowed_devices = CreateUsbPolicyAllowedDevices();
 
   const UsbPolicyAllowedDevices::UsbDeviceIdsToUrlsMap& map =
       usb_policy_allowed_devices->map();
@@ -234,13 +237,12 @@
 
 TEST_F(UsbPolicyAllowedDevicesTest,
        InitializeWithExistingPrefValueContainingDuplicateDevices) {
-  std::unique_ptr<base::Value> pref_value = base::JSONReader::ReadDeprecated(
-      kPolicySettingWithEntriesContainingDuplicateDevices);
+  std::unique_ptr<base::Value> pref_value =
+      ReadJson(kPolicySettingWithEntriesContainingDuplicateDevices);
 
   SetWebUsbAllowDevicesForUrlsPrefValue(*pref_value);
 
-  auto usb_policy_allowed_devices =
-      std::make_unique<UsbPolicyAllowedDevices>(profile()->GetPrefs());
+  auto usb_policy_allowed_devices = CreateUsbPolicyAllowedDevices();
 
   const UsbPolicyAllowedDevices::UsbDeviceIdsToUrlsMap& map =
       usb_policy_allowed_devices->map();
@@ -275,13 +277,12 @@
 }  // namespace
 
 TEST_F(UsbPolicyAllowedDevicesTest, IsDeviceAllowed) {
-  std::unique_ptr<base::Value> pref_value = base::JSONReader::ReadDeprecated(
-      kPolicySettingWithEntriesMatchingMultipleDevices);
+  std::unique_ptr<base::Value> pref_value =
+      ReadJson(kPolicySettingWithEntriesMatchingMultipleDevices);
 
   SetWebUsbAllowDevicesForUrlsPrefValue(*pref_value);
 
-  auto usb_policy_allowed_devices =
-      std::make_unique<UsbPolicyAllowedDevices>(profile()->GetPrefs());
+  auto usb_policy_allowed_devices = CreateUsbPolicyAllowedDevices();
 
   const auto kGoogleOrigin = url::Origin::Create(GURL("https://google.com"));
   const auto kYoutubeOrigin =
@@ -345,13 +346,12 @@
 }
 
 TEST_F(UsbPolicyAllowedDevicesTest, IsDeviceAllowedForUrlsNotInPref) {
-  std::unique_ptr<base::Value> pref_value = base::JSONReader::ReadDeprecated(
-      kPolicySettingWithEntriesMatchingMultipleDevices);
+  std::unique_ptr<base::Value> pref_value =
+      ReadJson(kPolicySettingWithEntriesMatchingMultipleDevices);
 
   SetWebUsbAllowDevicesForUrlsPrefValue(*pref_value);
 
-  auto usb_policy_allowed_devices =
-      std::make_unique<UsbPolicyAllowedDevices>(profile()->GetPrefs());
+  auto usb_policy_allowed_devices = CreateUsbPolicyAllowedDevices();
 
   const url::Origin origins[] = {
       url::Origin::Create(GURL("https://evil.com")),
@@ -369,13 +369,12 @@
 }
 
 TEST_F(UsbPolicyAllowedDevicesTest, IsDeviceAllowedForDeviceNotInPref) {
-  std::unique_ptr<base::Value> pref_value = base::JSONReader::ReadDeprecated(
-      kPolicySettingWithEntriesMatchingMultipleDevices);
+  std::unique_ptr<base::Value> pref_value =
+      ReadJson(kPolicySettingWithEntriesMatchingMultipleDevices);
 
   SetWebUsbAllowDevicesForUrlsPrefValue(*pref_value);
 
-  auto usb_policy_allowed_devices =
-      std::make_unique<UsbPolicyAllowedDevices>(profile()->GetPrefs());
+  auto usb_policy_allowed_devices = CreateUsbPolicyAllowedDevices();
 
   const url::Origin origins[] = {
       url::Origin::Create(GURL("https://google.com")),
@@ -407,13 +406,12 @@
 
 TEST_F(UsbPolicyAllowedDevicesTest,
        IsDeviceAllowedForUrlContainingEmbeddingOrigin) {
-  std::unique_ptr<base::Value> pref_value = base::JSONReader::ReadDeprecated(
-      kPolicySettingWithUrlContainingEmbeddingOrigin);
+  std::unique_ptr<base::Value> pref_value =
+      ReadJson(kPolicySettingWithUrlContainingEmbeddingOrigin);
 
   SetWebUsbAllowDevicesForUrlsPrefValue(*pref_value);
 
-  auto usb_policy_allowed_devices =
-      std::make_unique<UsbPolicyAllowedDevices>(profile()->GetPrefs());
+  auto usb_policy_allowed_devices = CreateUsbPolicyAllowedDevices();
 
   const auto requesting_origin =
       url::Origin::Create(GURL("https://requesting.com"));