Commit 02f2ed13 authored by Ovidio Henriquez's avatar Ovidio Henriquez Committed by Commit Bot

Include policy USB devices in GetAllGrantedObjects

This change updates the GetAllGrantedObjects() method of
UsbChooserContext to include the USB objects granted by the
WebUsbAllowDevicesForUrls policy. The GetAllGrantedObjects() method
removes user granted objects that are also granted permission by the
policy.

SiteSettingsHelper was modified to skip the policy objects until the UI
is ready to display them.

Design Doc:
https://docs.google.com/document/d/1MPvsrWiVD_jAC8ELyk8njFpy6j1thfVU5aWT3TCWE8w

Bug: 854329
Change-Id: I8442f588b0d7029062c67bbb2896cefeb558a887
Reviewed-on: https://chromium-review.googlesource.com/c/1297301
Commit-Queue: Ovidio Henriquez <odejesush@chromium.org>
Reviewed-by: default avatarDave Schuyler <dschuyler@chromium.org>
Reviewed-by: default avatarTheresa <twellington@chromium.org>
Reviewed-by: default avatarReilly Grant <reillyg@chromium.org>
Cr-Commit-Position: refs/heads/master@{#609479}
parent ad9bbcc0
...@@ -591,6 +591,12 @@ void GetChooserExceptionsFromProfile(Profile* profile, ...@@ -591,6 +591,12 @@ void GetChooserExceptionsFromProfile(Profile* profile,
chooser_context->GetAllGrantedObjects(); chooser_context->GetAllGrantedObjects();
AllOriginObjects all_origin_objects; AllOriginObjects all_origin_objects;
for (const auto& object : objects) { for (const auto& object : objects) {
// Skip policy controlled objects until they are ready to be displayed.
// TODO(https://crbug.com/854329): Include policy controlled objects
// when the UI is capable of displaying them properly as policy controlled
// objects.
if (object->source == SiteSettingSourceToString(SiteSettingSource::kPolicy))
continue;
std::string name = chooser_context->GetObjectName(object->object); std::string name = chooser_context->GetObjectName(object->object);
// It is safe for this structure to hold references into |objects| because // It is safe for this structure to hold references into |objects| because
// they are both destroyed at the end of this function. // they are both destroyed at the end of this function.
......
...@@ -12,20 +12,26 @@ ...@@ -12,20 +12,26 @@
#include "base/strings/utf_string_conversions.h" #include "base/strings/utf_string_conversions.h"
#include "base/threading/sequenced_task_runner_handle.h" #include "base/threading/sequenced_task_runner_handle.h"
#include "base/values.h" #include "base/values.h"
#include "build/build_config.h"
#include "chrome/browser/profiles/profile.h" #include "chrome/browser/profiles/profile.h"
#include "chrome/browser/usb/usb_blocklist.h" #include "chrome/browser/usb/usb_blocklist.h"
#include "chrome/grit/generated_resources.h"
#include "content/public/common/service_manager_connection.h" #include "content/public/common/service_manager_connection.h"
#include "device/usb/public/mojom/device.mojom.h" #include "device/usb/public/mojom/device.mojom.h"
#include "device/usb/usb_ids.h"
#include "services/device/public/mojom/constants.mojom.h" #include "services/device/public/mojom/constants.mojom.h"
#include "services/service_manager/public/cpp/connector.h" #include "services/service_manager/public/cpp/connector.h"
#include "ui/base/l10n/l10n_util.h"
namespace { namespace {
const char kDeviceNameKey[] = "name"; constexpr char kDeviceNameKey[] = "name";
const char kGuidKey[] = "ephemeral-guid"; constexpr char kGuidKey[] = "ephemeral-guid";
const char kProductIdKey[] = "product-id"; constexpr char kProductIdKey[] = "product-id";
const char kSerialNumberKey[] = "serial-number"; constexpr char kSerialNumberKey[] = "serial-number";
const char kVendorIdKey[] = "vendor-id"; constexpr char kVendorIdKey[] = "vendor-id";
constexpr char kSourcePolicy[] = "policy";
constexpr char kSourcePreference[] = "preference";
// Reasons a permission may be closed. These are used in histograms so do not // Reasons a permission may be closed. These are used in histograms so do not
// remove/reorder entries. Only add at the end just before // remove/reorder entries. Only add at the end just before
...@@ -49,6 +55,16 @@ bool CanStorePersistentEntry(const device::mojom::UsbDeviceInfo& device_info) { ...@@ -49,6 +55,16 @@ bool CanStorePersistentEntry(const device::mojom::UsbDeviceInfo& device_info) {
return !device_info.serial_number->empty(); return !device_info.serial_number->empty();
} }
std::pair<int, int> GetDeviceIds(const base::DictionaryValue& object) {
DCHECK(object.FindKeyOfType(kVendorIdKey, base::Value::Type::INTEGER));
int vendor_id = object.FindKey(kVendorIdKey)->GetInt();
DCHECK(object.FindKeyOfType(kProductIdKey, base::Value::Type::INTEGER));
int product_id = object.FindKey(kProductIdKey)->GetInt();
return std::make_pair(vendor_id, product_id);
}
std::unique_ptr<base::DictionaryValue> DeviceInfoToDictValue( std::unique_ptr<base::DictionaryValue> DeviceInfoToDictValue(
const device::mojom::UsbDeviceInfo& device_info) { const device::mojom::UsbDeviceInfo& device_info) {
auto device_dict = std::make_unique<base::DictionaryValue>(); auto device_dict = std::make_unique<base::DictionaryValue>();
...@@ -56,17 +72,56 @@ std::unique_ptr<base::DictionaryValue> DeviceInfoToDictValue( ...@@ -56,17 +72,56 @@ std::unique_ptr<base::DictionaryValue> DeviceInfoToDictValue(
device_info.product_name device_info.product_name
? base::Value(*device_info.product_name) ? base::Value(*device_info.product_name)
: base::Value("")); : base::Value(""));
device_dict->SetKey(kVendorIdKey, base::Value(device_info.vendor_id));
device_dict->SetKey(kProductIdKey, base::Value(device_info.product_id));
if (!CanStorePersistentEntry(device_info)) { // CanStorePersistentEntry checks if |device_info.serial_number| is not empty.
if (CanStorePersistentEntry(device_info)) {
device_dict->SetKey(kSerialNumberKey,
base::Value(*device_info.serial_number));
} else {
device_dict->SetKey(kGuidKey, base::Value(device_info.guid)); device_dict->SetKey(kGuidKey, base::Value(device_info.guid));
return device_dict;
} }
device_dict->SetKey(kVendorIdKey, base::Value(device_info.vendor_id));
device_dict->SetKey(kProductIdKey, base::Value(device_info.product_id)); return device_dict;
device_dict->SetKey(kSerialNumberKey, }
device_info.serial_number
? base::Value(*device_info.serial_number) base::string16 GetDeviceNameFromIds(int vendor_id, int product_id) {
: base::Value("")); // This is currently using the UI strings used for the chooser prompt. This is
// fine for now since the policy allowed devices are not being displayed in
// Site Settings yet. However, policy allowed devices can contain wildcards for
// the IDs, so more specific UI string need to be defined.
// TODO(https://crbug.com/854329): Add UI strings that are more specific to
// the Site Settings UI.
#if !defined(OS_ANDROID)
const char* product_name =
device::UsbIds::GetProductName(vendor_id, product_id);
if (product_name)
return base::UTF8ToUTF16(product_name);
const char* vendor_name = device::UsbIds::GetVendorName(vendor_id);
if (vendor_name) {
return l10n_util::GetStringFUTF16(
IDS_DEVICE_CHOOSER_DEVICE_NAME_UNKNOWN_DEVICE_WITH_VENDOR_NAME,
base::UTF8ToUTF16(vendor_name));
}
#endif // !defined(OS_ANDROID)
return l10n_util::GetStringFUTF16(
IDS_DEVICE_CHOOSER_DEVICE_NAME_UNKNOWN_DEVICE_WITH_VENDOR_ID_AND_PRODUCT_ID,
base::ASCIIToUTF16(base::StringPrintf("%04x", vendor_id)),
base::ASCIIToUTF16(base::StringPrintf("%04x", product_id)));
}
std::unique_ptr<base::DictionaryValue> DeviceIdsToDictValue(int vendor_id,
int product_id) {
auto device_dict = std::make_unique<base::DictionaryValue>();
base::string16 device_name = GetDeviceNameFromIds(vendor_id, product_id);
device_dict->SetKey(kDeviceNameKey, base::Value(device_name));
device_dict->SetKey(kVendorIdKey, base::Value(vendor_id));
device_dict->SetKey(kProductIdKey, base::Value(product_id));
device_dict->SetKey(kSerialNumberKey, base::Value(std::string()));
return device_dict; return device_dict;
} }
...@@ -190,7 +245,49 @@ UsbChooserContext::GetAllGrantedObjects() { ...@@ -190,7 +245,49 @@ UsbChooserContext::GetAllGrantedObjects() {
// ChooserContextBase::Object constructor will swap the object. // ChooserContextBase::Object constructor will swap the object.
auto object = DeviceInfoToDictValue(*devices_[guid]); auto object = DeviceInfoToDictValue(*devices_[guid]);
objects.push_back(std::make_unique<ChooserContextBase::Object>( objects.push_back(std::make_unique<ChooserContextBase::Object>(
requesting_origin, embedding_origin, object.get(), "preference", requesting_origin, embedding_origin, object.get(), kSourcePreference,
is_incognito_));
}
}
// Iterate through the user granted objects to create a mapping of device IDs
// to device object for the policy granted objects to use, and remove
// objects that have already been granted permission by the policy.
std::map<std::pair<int, int>, base::Value> device_ids_to_object_map;
for (auto it = objects.begin(); it != objects.end();) {
const Object& object = **it;
auto device_ids = GetDeviceIds(object.object);
const GURL& requesting_origin = object.requesting_origin;
const GURL& embedding_origin = object.embedding_origin;
device_ids_to_object_map[device_ids] = object.object.Clone();
if (usb_policy_allowed_devices_->IsDeviceAllowed(
requesting_origin, embedding_origin, device_ids)) {
it = objects.erase(it);
} else {
++it;
}
}
for (const auto& allowed_devices_entry : usb_policy_allowed_devices_->map()) {
// The map key is a tuple of (vendor_id, product_id).
const int vendor_id = allowed_devices_entry.first.first;
const int product_id = allowed_devices_entry.first.second;
for (const auto& url_pair : allowed_devices_entry.second) {
std::unique_ptr<base::DictionaryValue> object;
auto it =
device_ids_to_object_map.find(std::make_pair(vendor_id, product_id));
if (it != device_ids_to_object_map.end()) {
object = base::DictionaryValue::From(
base::Value::ToUniquePtrValue(it->second.Clone()));
} else {
object = DeviceIdsToDictValue(vendor_id, product_id);
}
objects.push_back(std::make_unique<ChooserContextBase::Object>(
url_pair.first, url_pair.second, object.get(), kSourcePolicy,
is_incognito_)); is_incognito_));
} }
} }
...@@ -324,7 +421,7 @@ base::WeakPtr<UsbChooserContext> UsbChooserContext::AsWeakPtr() { ...@@ -324,7 +421,7 @@ base::WeakPtr<UsbChooserContext> UsbChooserContext::AsWeakPtr() {
bool UsbChooserContext::IsValidObject(const base::DictionaryValue& object) { bool UsbChooserContext::IsValidObject(const base::DictionaryValue& object) {
return object.size() == 4 && object.HasKey(kDeviceNameKey) && return object.size() == 4 && object.HasKey(kDeviceNameKey) &&
object.HasKey(kVendorIdKey) && object.HasKey(kProductIdKey) && object.HasKey(kVendorIdKey) && object.HasKey(kProductIdKey) &&
object.HasKey(kSerialNumberKey); (object.HasKey(kSerialNumberKey) || object.HasKey(kGuidKey));
} }
std::string UsbChooserContext::GetObjectName( std::string UsbChooserContext::GetObjectName(
......
...@@ -76,12 +76,12 @@ class UsbChooserContext : public ChooserContextBase, ...@@ -76,12 +76,12 @@ class UsbChooserContext : public ChooserContextBase,
void SetDeviceManagerForTesting( void SetDeviceManagerForTesting(
device::mojom::UsbDeviceManagerPtr fake_device_manager); device::mojom::UsbDeviceManagerPtr fake_device_manager);
private:
// ChooserContextBase implementation. // ChooserContextBase implementation.
bool IsValidObject(const base::DictionaryValue& object) override; bool IsValidObject(const base::DictionaryValue& object) override;
std::string GetObjectName(const base::DictionaryValue& object) override; std::string GetObjectName(const base::DictionaryValue& object) override;
void InitDeviceList(std::vector<::device::mojom::UsbDeviceInfoPtr> devices); void InitDeviceList(std::vector<::device::mojom::UsbDeviceInfoPtr> devices);
private:
// device::mojom::UsbDeviceManagerClient implementation. // device::mojom::UsbDeviceManagerClient implementation.
void OnDeviceAdded(device::mojom::UsbDeviceInfoPtr device_info) override; void OnDeviceAdded(device::mojom::UsbDeviceInfoPtr device_info) override;
void OnDeviceRemoved(device::mojom::UsbDeviceInfoPtr device_info) override; void OnDeviceRemoved(device::mojom::UsbDeviceInfoPtr device_info) override;
......
...@@ -7,6 +7,7 @@ ...@@ -7,6 +7,7 @@
#include "base/bind_helpers.h" #include "base/bind_helpers.h"
#include "base/json/json_reader.h" #include "base/json/json_reader.h"
#include "base/run_loop.h" #include "base/run_loop.h"
#include "base/strings/utf_string_conversions.h"
#include "chrome/browser/content_settings/host_content_settings_map_factory.h" #include "chrome/browser/content_settings/host_content_settings_map_factory.h"
#include "chrome/browser/usb/usb_chooser_context.h" #include "chrome/browser/usb/usb_chooser_context.h"
#include "chrome/browser/usb/usb_chooser_context_factory.h" #include "chrome/browser/usb/usb_chooser_context_factory.h"
...@@ -24,6 +25,13 @@ using device::mojom::UsbDeviceInfoPtr; ...@@ -24,6 +25,13 @@ using device::mojom::UsbDeviceInfoPtr;
namespace { namespace {
constexpr char kDeviceNameKey[] = "name";
constexpr char kGuidKey[] = "ephemeral-guid";
constexpr char kProductIdKey[] = "product-id";
constexpr char kSerialNumberKey[] = "serial-number";
constexpr char kVendorIdKey[] = "vendor-id";
constexpr int kDeviceIdWildcard = -1;
class UsbChooserContextTest : public testing::Test { class UsbChooserContextTest : public testing::Test {
public: public:
UsbChooserContextTest() {} UsbChooserContextTest() {}
...@@ -62,10 +70,10 @@ TEST_F(UsbChooserContextTest, CheckGrantAndRevokePermission) { ...@@ -62,10 +70,10 @@ TEST_F(UsbChooserContextTest, CheckGrantAndRevokePermission) {
UsbChooserContext* store = GetChooserContext(profile()); UsbChooserContext* store = GetChooserContext(profile());
base::DictionaryValue object_dict; base::DictionaryValue object_dict;
object_dict.SetString("name", "Gizmo"); object_dict.SetString(kDeviceNameKey, "Gizmo");
object_dict.SetInteger("vendor-id", 0); object_dict.SetInteger(kVendorIdKey, 0);
object_dict.SetInteger("product-id", 0); object_dict.SetInteger(kProductIdKey, 0);
object_dict.SetString("serial-number", "123ABC"); object_dict.SetString(kSerialNumberKey, "123ABC");
EXPECT_FALSE(store->HasDevicePermission(origin, origin, *device_info)); EXPECT_FALSE(store->HasDevicePermission(origin, origin, *device_info));
store->GrantDevicePermission(origin, origin, *device_info); store->GrantDevicePermission(origin, origin, *device_info);
...@@ -100,8 +108,10 @@ TEST_F(UsbChooserContextTest, CheckGrantAndRevokeEphemeralPermission) { ...@@ -100,8 +108,10 @@ TEST_F(UsbChooserContextTest, CheckGrantAndRevokeEphemeralPermission) {
UsbChooserContext* store = GetChooserContext(profile()); UsbChooserContext* store = GetChooserContext(profile());
base::DictionaryValue object_dict; base::DictionaryValue object_dict;
object_dict.SetString("name", "Gizmo"); object_dict.SetString(kDeviceNameKey, "Gizmo");
object_dict.SetString("ephemeral-guid", device_info->guid); object_dict.SetString(kGuidKey, device_info->guid);
object_dict.SetInteger(kVendorIdKey, device_info->vendor_id);
object_dict.SetInteger(kProductIdKey, device_info->product_id);
EXPECT_FALSE(store->HasDevicePermission(origin, origin, *device_info)); EXPECT_FALSE(store->HasDevicePermission(origin, origin, *device_info));
store->GrantDevicePermission(origin, origin, *device_info); store->GrantDevicePermission(origin, origin, *device_info);
...@@ -292,16 +302,16 @@ namespace { ...@@ -292,16 +302,16 @@ namespace {
constexpr char kPolicySetting[] = R"( constexpr char kPolicySetting[] = R"(
[ [
{ {
"devices": [{ "vendor_id": 1234, "product_id": 5678 }], "devices": [{ "vendor_id": 6353, "product_id": 5678 }],
"urls": ["https://product.vendor.com"] "urls": ["https://product.vendor.com"]
}, { }, {
"devices": [{ "vendor_id": 1234 }], "devices": [{ "vendor_id": 6353 }],
"urls": ["https://vendor.com"] "urls": ["https://vendor.com"]
}, { }, {
"devices": [{}], "devices": [{}],
"urls": ["https://anydevice.com"] "urls": ["https://anydevice.com"]
}, { }, {
"devices": [{ "vendor_id": 2468, "product_id": 1357 }], "devices": [{ "vendor_id": 6354, "product_id": 1357 }],
"urls": ["https://gadget.com,https://cool.com"] "urls": ["https://gadget.com,https://cool.com"]
} }
])"; ])";
...@@ -352,7 +362,7 @@ TEST_F(UsbChooserContextTest, ...@@ -352,7 +362,7 @@ TEST_F(UsbChooserContextTest,
GURL("https://gadget.com"), GURL("https://cool.com")}; GURL("https://gadget.com"), GURL("https://cool.com")};
UsbDeviceInfoPtr specific_device_info = device_manager_.CreateAndAddDevice( UsbDeviceInfoPtr specific_device_info = device_manager_.CreateAndAddDevice(
1234, 5678, "Google", "Gizmo", "ABC123"); 6353, 5678, "Google", "Gizmo", "ABC123");
auto* store = GetChooserContext(profile()); auto* store = GetChooserContext(profile());
...@@ -374,7 +384,7 @@ TEST_F(UsbChooserContextTest, ...@@ -374,7 +384,7 @@ TEST_F(UsbChooserContextTest,
GURL("https://cool.com")}; GURL("https://cool.com")};
UsbDeviceInfoPtr vendor_related_device_info = UsbDeviceInfoPtr vendor_related_device_info =
device_manager_.CreateAndAddDevice(1234, 8765, "Google", "Widget", device_manager_.CreateAndAddDevice(6353, 8765, "Google", "Widget",
"XYZ987"); "XYZ987");
auto* store = GetChooserContext(profile()); auto* store = GetChooserContext(profile());
...@@ -400,7 +410,7 @@ TEST_F(UsbChooserContextTest, ...@@ -400,7 +410,7 @@ TEST_F(UsbChooserContextTest,
const GURL& kCoolOrigin = kInvalidRequestingOrigins[2]; const GURL& kCoolOrigin = kInvalidRequestingOrigins[2];
UsbDeviceInfoPtr unrelated_device_info = device_manager_.CreateAndAddDevice( UsbDeviceInfoPtr unrelated_device_info = device_manager_.CreateAndAddDevice(
2468, 1357, "Cool", "Gadget", "4W350M3"); 6354, 1357, "Cool", "Gadget", "4W350M3");
auto* store = GetChooserContext(profile()); auto* store = GetChooserContext(profile());
...@@ -428,9 +438,9 @@ TEST_F(UsbChooserContextTest, ...@@ -428,9 +438,9 @@ TEST_F(UsbChooserContextTest,
const GURL kCoolOrigin("https://cool.com"); const GURL kCoolOrigin("https://cool.com");
UsbDeviceInfoPtr specific_device_info = device_manager_.CreateAndAddDevice( UsbDeviceInfoPtr specific_device_info = device_manager_.CreateAndAddDevice(
1234, 5678, "Google", "Gizmo", "ABC123"); 6353, 5678, "Google", "Gizmo", "ABC123");
UsbDeviceInfoPtr unrelated_device_info = device_manager_.CreateAndAddDevice( UsbDeviceInfoPtr unrelated_device_info = device_manager_.CreateAndAddDevice(
2468, 1357, "Cool", "Gadget", "4W350M3"); 6354, 1357, "Cool", "Gadget", "4W350M3");
auto* store = GetChooserContext(profile()); auto* store = GetChooserContext(profile());
...@@ -465,3 +475,338 @@ TEST_F(UsbChooserContextTest, ...@@ -465,3 +475,338 @@ TEST_F(UsbChooserContextTest,
EXPECT_TRUE(store->HasDevicePermission(kGadgetOrigin, kCoolOrigin, EXPECT_TRUE(store->HasDevicePermission(kGadgetOrigin, kCoolOrigin,
*unrelated_device_info)); *unrelated_device_info));
} }
namespace {
// Permission sources
constexpr char kPolicySource[] = "policy";
constexpr char kPreferenceSource[] = "preference";
// Test URLs
const GURL kAnyDeviceOrigin("https://anydevice.com");
const GURL kVendorOrigin("https://vendor.com");
const GURL kProductVendorOrigin("https://product.vendor.com");
const GURL kGadgetOrigin("https://gadget.com");
const GURL kCoolOrigin("https://cool.com");
void ExpectDeviceObjectInfo(const base::DictionaryValue& actual,
int vendor_id,
int product_id,
const std::string& name) {
const base::Value* vendor_id_value =
actual.FindKeyOfType(kVendorIdKey, base::Value::Type::INTEGER);
ASSERT_TRUE(vendor_id_value);
EXPECT_EQ(vendor_id_value->GetInt(), vendor_id);
const base::Value* product_id_value =
actual.FindKeyOfType(kProductIdKey, base::Value::Type::INTEGER);
ASSERT_TRUE(product_id_value);
EXPECT_EQ(product_id_value->GetInt(), product_id);
const base::Value* device_name_value =
actual.FindKeyOfType(kDeviceNameKey, base::Value::Type::STRING);
ASSERT_TRUE(device_name_value);
EXPECT_EQ(device_name_value->GetString(), name);
}
void ExpectChooserObjectInfo(const ChooserContextBase::Object* actual,
const GURL& requesting_origin,
const GURL& embedding_origin,
const std::string& source,
bool incognito,
int vendor_id,
int product_id,
const std::string& name) {
ASSERT_TRUE(actual);
EXPECT_EQ(actual->requesting_origin, requesting_origin);
EXPECT_EQ(actual->embedding_origin, embedding_origin);
EXPECT_EQ(actual->source, source);
EXPECT_EQ(actual->incognito, incognito);
ExpectDeviceObjectInfo(actual->object, vendor_id, product_id, name);
}
void ExpectChooserObjectInfo(const ChooserContextBase::Object* actual,
const GURL& requesting_origin,
const std::string& source,
bool incognito,
int vendor_id,
int product_id,
const std::string& name) {
ExpectChooserObjectInfo(actual, requesting_origin, GURL::EmptyGURL(), source,
incognito, vendor_id, product_id, name);
}
} // namespace
TEST_F(UsbChooserContextTest,
GetAllGrantedObjectsWithOnlyPolicyAllowedDevices) {
auto* store = GetChooserContext(profile());
profile()->GetPrefs()->Set(prefs::kManagedWebUsbAllowDevicesForUrls,
*base::JSONReader::Read(kPolicySetting));
auto objects = store->GetAllGrantedObjects();
ASSERT_EQ(objects.size(), 4ul);
// The policy enforced objects that are returned by GetAllGrantedObjects() are
// ordered by the tuple (vendor_id, product_id) representing the device IDs.
// Wildcard IDs are represented by a value of -1, so they appear first.
ExpectChooserObjectInfo(objects[0].get(),
/*requesting_origin=*/kAnyDeviceOrigin,
/*source=*/kPolicySource,
/*incognito=*/false,
/*vendor_id=*/kDeviceIdWildcard,
/*product_id=*/kDeviceIdWildcard,
/*name=*/"Unknown device [ffffffff:ffffffff]");
ExpectChooserObjectInfo(objects[1].get(),
/*requesting_origin=*/kVendorOrigin,
/*source=*/kPolicySource,
/*incognito=*/false,
/*vendor_id=*/6353,
/*product_id=*/kDeviceIdWildcard,
/*name=*/"Unknown device from Google Inc.");
ExpectChooserObjectInfo(objects[2].get(),
/*requesting_origin=*/kProductVendorOrigin,
/*source=*/kPolicySource,
/*incognito=*/false,
/*vendor_id=*/6353,
/*product_id=*/5678,
/*name=*/"Unknown device from Google Inc.");
ExpectChooserObjectInfo(objects[3].get(),
/*requesting_origin=*/kGadgetOrigin,
/*embedding_origin=*/kCoolOrigin,
/*source=*/kPolicySource,
/*incognito=*/false,
/*vendor_id=*/6354,
/*product_id=*/1357,
/*name=*/"Unknown device [18d2:054d]");
}
TEST_F(UsbChooserContextTest,
GetAllGrantedObjectsWithUserAndPolicyAllowedDevices) {
profile()->GetPrefs()->Set(prefs::kManagedWebUsbAllowDevicesForUrls,
*base::JSONReader::Read(kPolicySetting));
const GURL kGoogleOrigin("https://www.google.com");
UsbDeviceInfoPtr persistent_device_info =
device_manager_.CreateAndAddDevice(1000, 1, "Google", "Gizmo", "123ABC");
UsbDeviceInfoPtr ephemeral_device_info =
device_manager_.CreateAndAddDevice(1000, 2, "Google", "Gadget", "");
auto* store = GetChooserContext(profile());
store->GrantDevicePermission(kGoogleOrigin, kGoogleOrigin,
*persistent_device_info);
store->GrantDevicePermission(kGoogleOrigin, kGoogleOrigin,
*ephemeral_device_info);
auto objects = store->GetAllGrantedObjects();
ASSERT_EQ(objects.size(), 6ul);
for (const auto& object : objects) {
EXPECT_TRUE(store->IsValidObject(object->object));
}
// The user granted permissions appear before the policy granted permissions.
// Within the user granted permissions, the persistent device permissions
// are added to the vector before ephemeral device permissions.
ExpectChooserObjectInfo(objects[0].get(),
/*requesting_origin=*/kGoogleOrigin,
/*embedding_origin=*/kGoogleOrigin,
/*source=*/kPreferenceSource,
/*incognito=*/false,
/*vendor_id=*/1000,
/*product_id=*/1,
/*name=*/"Gizmo");
ExpectChooserObjectInfo(objects[1].get(),
/*requesting_origin=*/kGoogleOrigin,
/*embedding_origin=*/kGoogleOrigin,
/*source=*/kPreferenceSource,
/*incognito=*/false,
/*vendor_id=*/1000,
/*product_id=*/2,
/*name=*/"Gadget");
ExpectChooserObjectInfo(objects[2].get(),
/*requesting_origin=*/kAnyDeviceOrigin,
/*source=*/kPolicySource,
/*incognito=*/false,
/*vendor_id=*/kDeviceIdWildcard,
/*product_id=*/kDeviceIdWildcard,
/*name=*/"Unknown device [ffffffff:ffffffff]");
ExpectChooserObjectInfo(objects[3].get(),
/*requesting_origin=*/kVendorOrigin,
/*source=*/kPolicySource,
/*incognito=*/false,
/*vendor_id=*/6353,
/*product_id=*/kDeviceIdWildcard,
/*name=*/"Unknown device from Google Inc.");
ExpectChooserObjectInfo(objects[4].get(),
/*requesting_origin=*/kProductVendorOrigin,
/*source=*/kPolicySource,
/*incognito=*/false,
/*vendor_id=*/6353,
/*product_id=*/5678,
/*name=*/"Unknown device from Google Inc.");
ExpectChooserObjectInfo(objects[5].get(),
/*requesting_origin=*/kGadgetOrigin,
/*embedding_origin=*/kCoolOrigin,
/*source=*/kPolicySource,
/*incognito=*/false,
/*vendor_id=*/6354,
/*product_id=*/1357,
/*name=*/"Unknown device [18d2:054d]");
}
TEST_F(UsbChooserContextTest,
GetAllGrantedObjectsWithSpecificPolicyAndUserGrantedDevice) {
auto* store = GetChooserContext(profile());
profile()->GetPrefs()->Set(prefs::kManagedWebUsbAllowDevicesForUrls,
*base::JSONReader::Read(kPolicySetting));
const GURL kProductVendorOrigin("https://product.vendor.com");
UsbDeviceInfoPtr persistent_device_info = device_manager_.CreateAndAddDevice(
6353, 5678, "Specific", "Product", "123ABC");
store->GrantDevicePermission(kProductVendorOrigin, kProductVendorOrigin,
*persistent_device_info);
auto objects = store->GetAllGrantedObjects();
ASSERT_EQ(objects.size(), 4ul);
for (const auto& object : objects) {
EXPECT_TRUE(store->IsValidObject(object->object));
}
ExpectChooserObjectInfo(objects[0].get(),
/*requesting_origin=*/kAnyDeviceOrigin,
/*source=*/kPolicySource,
/*incognito=*/false,
/*vendor_id=*/kDeviceIdWildcard,
/*product_id=*/kDeviceIdWildcard,
/*name=*/"Unknown device [ffffffff:ffffffff]");
ExpectChooserObjectInfo(objects[1].get(),
/*requesting_origin=*/kVendorOrigin,
/*source=*/kPolicySource,
/*incognito=*/false,
/*vendor_id=*/6353,
/*product_id=*/kDeviceIdWildcard,
/*name=*/"Unknown device from Google Inc.");
ExpectChooserObjectInfo(objects[2].get(),
/*requesting_origin=*/kProductVendorOrigin,
/*source=*/kPolicySource,
/*incognito=*/false,
/*vendor_id=*/6353,
/*product_id=*/5678,
/*name=*/"Product");
ExpectChooserObjectInfo(objects[3].get(),
/*requesting_origin=*/kGadgetOrigin,
/*embedding_origin=*/kCoolOrigin,
/*source=*/kPolicySource,
/*incognito=*/false,
/*vendor_id=*/6354,
/*product_id=*/1357,
/*name=*/"Unknown device [18d2:054d]");
ASSERT_TRUE(persistent_device_info->product_name);
EXPECT_EQ(base::UTF8ToUTF16(store->GetObjectName(objects[2]->object)),
persistent_device_info->product_name.value());
}
TEST_F(UsbChooserContextTest,
GetAllGrantedObjectsWithVendorPolicyAndUserGrantedDevice) {
const GURL kVendorOrigin("https://vendor.com");
UsbDeviceInfoPtr persistent_device_info = device_manager_.CreateAndAddDevice(
6353, 1000, "Vendor", "Product", "123ABC");
auto* store = GetChooserContext(profile());
profile()->GetPrefs()->Set(prefs::kManagedWebUsbAllowDevicesForUrls,
*base::JSONReader::Read(kPolicySetting));
store->GrantDevicePermission(kVendorOrigin, kVendorOrigin,
*persistent_device_info);
auto objects = store->GetAllGrantedObjects();
ASSERT_EQ(objects.size(), 4ul);
for (const auto& object : objects) {
EXPECT_TRUE(store->IsValidObject(object->object));
}
ExpectChooserObjectInfo(objects[0].get(),
/*requesting_origin=*/kAnyDeviceOrigin,
/*source=*/kPolicySource,
/*incognito=*/false,
/*vendor_id=*/kDeviceIdWildcard,
/*product_id=*/kDeviceIdWildcard,
/*name=*/"Unknown device [ffffffff:ffffffff]");
ExpectChooserObjectInfo(objects[1].get(),
/*requesting_origin=*/kVendorOrigin,
/*source=*/kPolicySource,
/*incognito=*/false,
/*vendor_id=*/6353,
/*product_id=*/kDeviceIdWildcard,
/*name=*/"Unknown device from Google Inc.");
ExpectChooserObjectInfo(objects[2].get(),
/*requesting_origin=*/kProductVendorOrigin,
/*source=*/kPolicySource,
/*incognito=*/false,
/*vendor_id=*/6353,
/*product_id=*/5678,
/*name=*/"Unknown device from Google Inc.");
ExpectChooserObjectInfo(objects[3].get(),
/*requesting_origin=*/kGadgetOrigin,
/*embedding_origin=*/kCoolOrigin,
/*source=*/kPolicySource,
/*incognito=*/false,
/*vendor_id=*/6354,
/*product_id=*/1357,
/*name=*/"Unknown device [18d2:054d]");
}
TEST_F(UsbChooserContextTest,
GetAllGrantedObjectsWithAnyPolicyAndUserGrantedDevice) {
const GURL kAnyDeviceOrigin("https://anydevice.com");
UsbDeviceInfoPtr persistent_device_info = device_manager_.CreateAndAddDevice(
1123, 5813, "Some", "Product", "123ABC");
auto* store = GetChooserContext(profile());
profile()->GetPrefs()->Set(prefs::kManagedWebUsbAllowDevicesForUrls,
*base::JSONReader::Read(kPolicySetting));
store->GrantDevicePermission(kAnyDeviceOrigin, kAnyDeviceOrigin,
*persistent_device_info);
auto objects = store->GetAllGrantedObjects();
ASSERT_EQ(objects.size(), 4ul);
for (const auto& object : objects) {
EXPECT_TRUE(store->IsValidObject(object->object));
}
ExpectChooserObjectInfo(objects[0].get(),
/*requesting_origin=*/kAnyDeviceOrigin,
/*source=*/kPolicySource,
/*incognito=*/false,
/*vendor_id=*/kDeviceIdWildcard,
/*product_id=*/kDeviceIdWildcard,
/*name=*/"Unknown device [ffffffff:ffffffff]");
ExpectChooserObjectInfo(objects[1].get(),
/*requesting_origin=*/kVendorOrigin,
/*source=*/kPolicySource,
/*incognito=*/false,
/*vendor_id=*/6353,
/*product_id=*/kDeviceIdWildcard,
/*name=*/"Unknown device from Google Inc.");
ExpectChooserObjectInfo(objects[2].get(),
/*requesting_origin=*/kProductVendorOrigin,
/*source=*/kPolicySource,
/*incognito=*/false,
/*vendor_id=*/6353,
/*product_id=*/5678,
/*name=*/"Unknown device from Google Inc.");
ExpectChooserObjectInfo(objects[3].get(),
/*requesting_origin=*/kGadgetOrigin,
/*embedding_origin=*/kCoolOrigin,
/*source=*/kPolicySource,
/*incognito=*/false,
/*vendor_id=*/6354,
/*product_id=*/1357,
/*name=*/"Unknown device [18d2:054d]");
}
...@@ -59,14 +59,23 @@ bool UsbPolicyAllowedDevices::IsDeviceAllowed( ...@@ -59,14 +59,23 @@ bool UsbPolicyAllowedDevices::IsDeviceAllowed(
const GURL& requesting_origin, const GURL& requesting_origin,
const GURL& embedding_origin, const GURL& embedding_origin,
const device::mojom::UsbDeviceInfo& device_info) { const device::mojom::UsbDeviceInfo& device_info) {
return IsDeviceAllowed(
requesting_origin, embedding_origin,
std::make_pair(device_info.vendor_id, device_info.product_id));
}
bool UsbPolicyAllowedDevices::IsDeviceAllowed(
const GURL& requesting_origin,
const GURL& embedding_origin,
const std::pair<int, int>& device_ids) {
// Search through each set of URL pair that match the given device. The // Search through each set of URL pair that match the given device. The
// keys correspond to the following URL pair sets: // keys correspond to the following URL pair sets:
// * (vendor_id, product_id): A set corresponding to the exact device. // * (vendor_id, product_id): A set corresponding to the exact device.
// * (vendor_id, -1): A set corresponding to any device with |vendor_id|. // * (vendor_id, -1): A set corresponding to any device with |vendor_id|.
// * (-1, -1): A set corresponding to any device. // * (-1, -1): A set corresponding to any device.
const std::pair<int, int> set_keys[] = { const std::pair<int, int> set_keys[] = {
std::make_pair(device_info.vendor_id, device_info.product_id), std::make_pair(device_ids.first, device_ids.second),
std::make_pair(device_info.vendor_id, -1), std::make_pair(-1, -1)}; std::make_pair(device_ids.first, -1), std::make_pair(-1, -1)};
for (const auto& key : set_keys) { for (const auto& key : set_keys) {
const auto entry = usb_device_ids_to_urls_.find(key); const auto entry = usb_device_ids_to_urls_.find(key);
......
...@@ -46,6 +46,9 @@ class UsbPolicyAllowedDevices { ...@@ -46,6 +46,9 @@ class UsbPolicyAllowedDevices {
bool IsDeviceAllowed(const GURL& requesting_origin, bool IsDeviceAllowed(const GURL& requesting_origin,
const GURL& embedding_origin, const GURL& embedding_origin,
const device::mojom::UsbDeviceInfo& device_info); const device::mojom::UsbDeviceInfo& device_info);
bool IsDeviceAllowed(const GURL& requesting_origin,
const GURL& embedding_origin,
const std::pair<int, int>& device_ids);
const UsbDeviceIdsToUrlsMap& map() const { return usb_device_ids_to_urls_; } const UsbDeviceIdsToUrlsMap& map() const { return usb_device_ids_to_urls_; }
......
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