Commit d69ab302 authored by Ovidio Henriquez's avatar Ovidio Henriquez Committed by Commit Bot

Implement UsbPolicyAllowedDevices class

This change creates a new UsbPolicyAllowedDevices class that reads the
preference value for kManagedWebUsbAllowedDevicesForUrls and creates a
mapping of the tuple (vendor_id, product_id) to a set of URL patterns.
The class also provides a method to check if a pair of requesting and
embedding origins are allowed to access a device with vendor_id and
product_id.

The design document for this feature can be found at:
https://docs.google.com/document/d/1MPvsrWiVD_jAC8ELyk8njFpy6j1thfVU5aWT3TCWE8w

Bug: 854329
Change-Id: I014849be2ef4779e45c28c6699ff34022d3e9b89
Reviewed-on: https://chromium-review.googlesource.com/c/1250060
Commit-Queue: Ovidio Henriquez <odejesush@chromium.org>
Reviewed-by: default avatarReilly Grant <reillyg@chromium.org>
Cr-Commit-Position: refs/heads/master@{#596710}
parent 169cb740
...@@ -1611,6 +1611,8 @@ jumbo_split_static_library("browser") { ...@@ -1611,6 +1611,8 @@ jumbo_split_static_library("browser") {
"usb/usb_chooser_context_factory.h", "usb/usb_chooser_context_factory.h",
"usb/usb_chooser_controller.cc", "usb/usb_chooser_controller.cc",
"usb/usb_chooser_controller.h", "usb/usb_chooser_controller.h",
"usb/usb_policy_allowed_devices.cc",
"usb/usb_policy_allowed_devices.h",
"usb/usb_tab_helper.cc", "usb/usb_tab_helper.cc",
"usb/usb_tab_helper.h", "usb/usb_tab_helper.h",
"usb/web_usb_chooser.cc", "usb/web_usb_chooser.cc",
......
// Copyright 2018 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "chrome/browser/usb/usb_policy_allowed_devices.h"
#include "base/values.h"
#include "components/content_settings/core/common/content_settings_pattern.h"
#include "components/content_settings/core/common/pref_names.h"
#include "components/prefs/pref_service.h"
#include "device/usb/public/mojom/device_manager.mojom.h"
#include "url/gurl.h"
namespace {
constexpr char kPrefDevicesKey[] = "devices";
constexpr char kPrefUrlPatternsKey[] = "url_patterns";
constexpr char kPrefVendorIdKey[] = "vendor_id";
constexpr char kPrefProductIdKey[] = "product_id";
// Find the URL match by checking if the pattern matches the given GURL types
// using ContentSettingsPattern::Matches().
bool FindMatchInSet(const std::set<content_settings::PatternPair>& pattern_set,
const GURL& requesting_origin,
const GURL& embedding_origin) {
for (const auto& pattern : pattern_set) {
if (pattern.first.Matches(requesting_origin) &&
pattern.second.Matches(embedding_origin)) {
return true;
}
}
return false;
}
} // namespace
UsbPolicyAllowedDevices::UsbPolicyAllowedDevices(PrefService* pref_service) {
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.
pref_change_registrar_.Add(
prefs::kManagedWebUsbAllowDevicesForUrls,
base::BindRepeating(&UsbPolicyAllowedDevices::CreateOrUpdateMap,
base::Unretained(this)));
CreateOrUpdateMap();
}
UsbPolicyAllowedDevices::~UsbPolicyAllowedDevices() {}
bool UsbPolicyAllowedDevices::IsDeviceAllowed(
const GURL& requesting_origin,
const GURL& embedding_origin,
const device::mojom::UsbDeviceInfo& device_info) {
// Search through each set of URL patterns that match the given device. The
// keys correspond to the following URL pattern sets:
// * (vendor_id, product_id): A set corresponding to the exact device.
// * (vendor_id, -1): A set corresponding to any device with |vendor_id|.
// * (-1, -1): A set corresponding to any device.
const std::pair<int, int> set_keys[] = {
std::make_pair(device_info.vendor_id, device_info.product_id),
std::make_pair(device_info.vendor_id, -1), std::make_pair(-1, -1)};
for (const auto& key : set_keys) {
const auto patterns = usb_device_ids_to_url_patterns_.find(key);
if (patterns == usb_device_ids_to_url_patterns_.cend())
continue;
if (FindMatchInSet(patterns->second, requesting_origin, embedding_origin))
return true;
}
return false;
}
void UsbPolicyAllowedDevices::CreateOrUpdateMap() {
const base::Value* pref_value = pref_change_registrar_.prefs()->Get(
prefs::kManagedWebUsbAllowDevicesForUrls);
usb_device_ids_to_url_patterns_.clear();
// A policy has not been assigned.
if (!pref_value) {
return;
}
// The pref value has already been validated by the policy handler, so it is
// safe to assume that |pref_value| follows the policy template.
for (const auto& item : pref_value->GetList()) {
const base::Value* url_patterns = item.FindKey(kPrefUrlPatternsKey);
std::set<content_settings::PatternPair> parsed_url_set;
// Parse each URL pattern into a PatternPair and store it in
// |parsed_url_set|.
for (const auto& url_pattern : url_patterns->GetList()) {
content_settings::PatternPair pattern_pair =
content_settings::ParsePatternString(url_pattern.GetString());
// Ignore invalid patterns.
if (!pattern_pair.first.IsValid())
continue;
parsed_url_set.insert(std::move(pattern_pair));
}
// Ignore items with empty parsed URLs.
if (parsed_url_set.empty())
continue;
// For each device entry in the map, create or update its respective URL
// pattern set.
const base::Value* devices = item.FindKey(kPrefDevicesKey);
for (const auto& device : devices->GetList()) {
// A missing ID signifies a wildcard for that ID, so a sentinel value of
// -1 is assigned.
const base::Value* vendor_id_value = device.FindKey(kPrefVendorIdKey);
const base::Value* product_id_value = device.FindKey(kPrefProductIdKey);
int vendor_id = vendor_id_value ? vendor_id_value->GetInt() : -1;
int product_id = product_id_value ? product_id_value->GetInt() : -1;
DCHECK(vendor_id != -1 || product_id == -1);
auto key = std::make_pair(vendor_id, product_id);
usb_device_ids_to_url_patterns_[key].insert(parsed_url_set.begin(),
parsed_url_set.end());
}
}
}
// Copyright 2018 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef CHROME_BROWSER_USB_USB_POLICY_ALLOWED_DEVICES_H_
#define CHROME_BROWSER_USB_USB_POLICY_ALLOWED_DEVICES_H_
#include <map>
#include <memory>
#include <set>
#include <utility>
#include "components/content_settings/core/browser/content_settings_utils.h"
#include "components/prefs/pref_change_registrar.h"
namespace device {
namespace mojom {
class UsbDeviceInfo;
} // namespace mojom
} // namespace device
class GURL;
class PrefService;
// This class is used to initialize a UsbDeviceIdsToUrlPatternsMap 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.
class UsbPolicyAllowedDevices {
public:
// A map of device IDs to a set of parsed URLs stored in a
// content_settings::PatternPair. The device IDs correspond to a pair of
// |vendor_id| and |product_id|. The content_settings::PatternPair is simply
// an alias for a pair of content_settings::ContentSettingsPattern objects.
using UsbDeviceIdsToUrlPatternsMap =
std::map<std::pair<int, int>, std::set<content_settings::PatternPair>>;
// Initializes |pref_change_registrar_| with |pref_service| and adds an
// an observer for the pref path |kManagedWebUsbAllowDevicesForUrls|.
explicit UsbPolicyAllowedDevices(PrefService* pref_service);
~UsbPolicyAllowedDevices();
// Checks if |requesting_origin| (when embedded within |embedding_origin|) is
// allowed to use the device with |device_info|.
bool IsDeviceAllowed(const GURL& requesting_origin,
const GURL& embedding_origin,
const device::mojom::UsbDeviceInfo& device_info);
const UsbDeviceIdsToUrlPatternsMap& map() const {
return usb_device_ids_to_url_patterns_;
}
private:
// Creates or updates the |usb_device_ids_to_url_patterns_| map using the
// pref at the path |kManagedWebUsbAllowDevicesForUrls|. 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.
PrefChangeRegistrar pref_change_registrar_;
UsbDeviceIdsToUrlPatternsMap usb_device_ids_to_url_patterns_;
};
#endif // CHROME_BROWSER_USB_USB_POLICY_ALLOWED_DEVICES_H_
This diff is collapsed.
...@@ -3203,6 +3203,7 @@ test("unit_tests") { ...@@ -3203,6 +3203,7 @@ test("unit_tests") {
"../browser/usb/usb_blocklist_unittest.cc", "../browser/usb/usb_blocklist_unittest.cc",
"../browser/usb/usb_chooser_context_unittest.cc", "../browser/usb/usb_chooser_context_unittest.cc",
"../browser/usb/usb_chooser_controller_unittest.cc", "../browser/usb/usb_chooser_controller_unittest.cc",
"../browser/usb/usb_policy_allowed_devices_unittest.cc",
"../browser/usb/web_usb_detector_unittest.cc", "../browser/usb/web_usb_detector_unittest.cc",
"../browser/usb/web_usb_service_impl_unittest.cc", "../browser/usb/web_usb_service_impl_unittest.cc",
"../browser/webauthn/authenticator_request_dialog_model_unittest.cc", "../browser/webauthn/authenticator_request_dialog_model_unittest.cc",
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment