blob: f4a894ab09c1569bdbf35fa90121214ee1f7a93f [file] [log] [blame]
// Copyright 2014 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 <stdint.h>
#include <memory>
#include "base/bind.h"
#include "base/run_loop.h"
#include "base/strings/utf_string_conversions.h"
#include "base/test/values_test_util.h"
#include "chrome/browser/extensions/test_extension_environment.h"
#include "chrome/test/base/testing_profile.h"
#include "device/base/mock_device_client.h"
#include "device/usb/mock_usb_device.h"
#include "device/usb/mock_usb_service.h"
#include "extensions/browser/api/device_permissions_manager.h"
#include "extensions/browser/api/hid/hid_device_manager.h"
#include "extensions/browser/extension_prefs.h"
#include "extensions/common/extension.h"
#include "services/device/public/mojom/hid.mojom.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace extensions {
namespace {
using device::MockUsbDevice;
using testing::_;
using testing::DoAll;
using testing::Return;
using testing::SetArgPointee;
const char* kTestDeviceGuids[] = {"A", "B", "C", "D"};
class FakeHidDeviceManager : public HidDeviceManager {
public:
explicit FakeHidDeviceManager(content::BrowserContext* context)
: HidDeviceManager(context) {}
void LazyInitialize() override {}
};
std::unique_ptr<KeyedService> CreateHidDeviceManager(
content::BrowserContext* context) {
return std::make_unique<FakeHidDeviceManager>(context);
}
} // namespace
class DevicePermissionsManagerTest : public testing::Test {
protected:
void SetUp() override {
testing::Test::SetUp();
env_.reset(new extensions::TestExtensionEnvironment());
extension_ =
env_->MakeExtension(*base::test::ParseJson(
"{"
" \"app\": {"
" \"background\": {"
" \"scripts\": [\"background.js\"]"
" }"
" },"
" \"permissions\": [ \"hid\", \"usb\" ]"
"}"));
HidDeviceManager::GetFactoryInstance()->SetTestingFactory(
env_->profile(), base::BindRepeating(&CreateHidDeviceManager));
device0_ =
new MockUsbDevice(0, 0, "Test Manufacturer", "Test Product", "ABCDE");
device1_ = new MockUsbDevice(0, 0, "Test Manufacturer", "Test Product", "");
device2_ =
new MockUsbDevice(0, 0, "Test Manufacturer", "Test Product", "12345");
device3_ = new MockUsbDevice(0, 0, "Test Manufacturer", "Test Product", "");
device4_ = device::mojom::HidDeviceInfo::New();
device4_->guid = kTestDeviceGuids[0];
device4_->product_name = "Test HID Device";
device4_->serial_number = "abcde";
device4_->bus_type = device::mojom::HidBusType::kHIDBusTypeUSB;
device5_ = device::mojom::HidDeviceInfo::New();
device5_->guid = kTestDeviceGuids[1];
device5_->product_name = "Test HID Device";
device5_->serial_number = "";
device5_->bus_type = device::mojom::HidBusType::kHIDBusTypeUSB;
device6_ = device::mojom::HidDeviceInfo::New();
device6_->guid = kTestDeviceGuids[2];
device6_->product_name = "Test HID Device";
device6_->serial_number = "67890";
device6_->bus_type = device::mojom::HidBusType::kHIDBusTypeUSB;
device7_ = device::mojom::HidDeviceInfo::New();
device7_->guid = kTestDeviceGuids[3];
device7_->product_name = "Test HID Device";
device7_->serial_number = "";
device7_->bus_type = device::mojom::HidBusType::kHIDBusTypeUSB;
}
void TearDown() override { env_.reset(nullptr); }
std::unique_ptr<extensions::TestExtensionEnvironment> env_;
const extensions::Extension* extension_;
device::MockDeviceClient device_client_;
scoped_refptr<MockUsbDevice> device0_;
scoped_refptr<MockUsbDevice> device1_;
scoped_refptr<MockUsbDevice> device2_;
scoped_refptr<MockUsbDevice> device3_;
device::mojom::HidDeviceInfoPtr device4_;
device::mojom::HidDeviceInfoPtr device5_;
device::mojom::HidDeviceInfoPtr device6_;
device::mojom::HidDeviceInfoPtr device7_;
};
TEST_F(DevicePermissionsManagerTest, AllowAndClearDevices) {
DevicePermissionsManager* manager =
DevicePermissionsManager::Get(env_->profile());
manager->AllowUsbDevice(extension_->id(), device0_);
manager->AllowUsbDevice(extension_->id(), device1_);
manager->AllowHidDevice(extension_->id(), *device4_);
manager->AllowHidDevice(extension_->id(), *device5_);
DevicePermissions* device_permissions =
manager->GetForExtension(extension_->id());
scoped_refptr<DevicePermissionEntry> device0_entry =
device_permissions->FindUsbDeviceEntry(device0_);
ASSERT_TRUE(device0_entry.get());
scoped_refptr<DevicePermissionEntry> device1_entry =
device_permissions->FindUsbDeviceEntry(device1_);
ASSERT_TRUE(device1_entry.get());
EXPECT_FALSE(device_permissions->FindUsbDeviceEntry(device2_).get());
EXPECT_FALSE(device_permissions->FindUsbDeviceEntry(device3_).get());
scoped_refptr<DevicePermissionEntry> device4_entry =
device_permissions->FindHidDeviceEntry(*device4_);
ASSERT_TRUE(device4_entry.get());
scoped_refptr<DevicePermissionEntry> device5_entry =
device_permissions->FindHidDeviceEntry(*device5_);
ASSERT_TRUE(device5_entry.get());
EXPECT_FALSE(device_permissions->FindHidDeviceEntry(*device6_).get());
EXPECT_FALSE(device_permissions->FindHidDeviceEntry(*device7_).get());
EXPECT_EQ(4U, device_permissions->entries().size());
EXPECT_EQ(base::ASCIIToUTF16(
"Test Product from Test Manufacturer (serial number ABCDE)"),
device0_entry->GetPermissionMessageString());
EXPECT_EQ(base::ASCIIToUTF16("Test Product from Test Manufacturer"),
device1_entry->GetPermissionMessageString());
EXPECT_EQ(base::ASCIIToUTF16("Test HID Device (serial number abcde)"),
device4_entry->GetPermissionMessageString());
EXPECT_EQ(base::ASCIIToUTF16("Test HID Device"),
device5_entry->GetPermissionMessageString());
manager->Clear(extension_->id());
// The device_permissions object is deleted by Clear.
device_permissions = manager->GetForExtension(extension_->id());
EXPECT_FALSE(device_permissions->FindUsbDeviceEntry(device0_).get());
EXPECT_FALSE(device_permissions->FindUsbDeviceEntry(device1_).get());
EXPECT_FALSE(device_permissions->FindUsbDeviceEntry(device2_).get());
EXPECT_FALSE(device_permissions->FindUsbDeviceEntry(device3_).get());
EXPECT_FALSE(device_permissions->FindHidDeviceEntry(*device4_).get());
EXPECT_FALSE(device_permissions->FindHidDeviceEntry(*device5_).get());
EXPECT_FALSE(device_permissions->FindHidDeviceEntry(*device6_).get());
EXPECT_FALSE(device_permissions->FindHidDeviceEntry(*device7_).get());
EXPECT_EQ(0U, device_permissions->entries().size());
// After clearing device it should be possible to grant permission again.
manager->AllowUsbDevice(extension_->id(), device0_);
manager->AllowUsbDevice(extension_->id(), device1_);
manager->AllowHidDevice(extension_->id(), *device4_);
manager->AllowHidDevice(extension_->id(), *device5_);
EXPECT_TRUE(device_permissions->FindUsbDeviceEntry(device0_).get());
EXPECT_TRUE(device_permissions->FindUsbDeviceEntry(device1_).get());
EXPECT_FALSE(device_permissions->FindUsbDeviceEntry(device2_).get());
EXPECT_FALSE(device_permissions->FindUsbDeviceEntry(device3_).get());
EXPECT_TRUE(device_permissions->FindHidDeviceEntry(*device4_).get());
EXPECT_TRUE(device_permissions->FindHidDeviceEntry(*device5_).get());
EXPECT_FALSE(device_permissions->FindHidDeviceEntry(*device6_).get());
EXPECT_FALSE(device_permissions->FindHidDeviceEntry(*device7_).get());
}
TEST_F(DevicePermissionsManagerTest, DisconnectDevice) {
DevicePermissionsManager* manager =
DevicePermissionsManager::Get(env_->profile());
manager->AllowUsbDevice(extension_->id(), device0_);
manager->AllowUsbDevice(extension_->id(), device1_);
manager->AllowHidDevice(extension_->id(), *device4_);
manager->AllowHidDevice(extension_->id(), *device5_);
DevicePermissions* device_permissions =
manager->GetForExtension(extension_->id());
EXPECT_TRUE(device_permissions->FindUsbDeviceEntry(device0_).get());
EXPECT_TRUE(device_permissions->FindUsbDeviceEntry(device1_).get());
EXPECT_FALSE(device_permissions->FindUsbDeviceEntry(device2_).get());
EXPECT_FALSE(device_permissions->FindUsbDeviceEntry(device3_).get());
EXPECT_TRUE(device_permissions->FindHidDeviceEntry(*device4_).get());
EXPECT_TRUE(device_permissions->FindHidDeviceEntry(*device5_).get());
EXPECT_FALSE(device_permissions->FindHidDeviceEntry(*device6_).get());
EXPECT_FALSE(device_permissions->FindHidDeviceEntry(*device7_).get());
device_client_.usb_service()->RemoveDevice(device0_);
device_client_.usb_service()->RemoveDevice(device1_);
manager->RemoveEntryByHidDeviceGUID(device4_->guid);
manager->RemoveEntryByHidDeviceGUID(device5_->guid);
// Device 0 will be accessible when it is reconnected because it can be
// recognized by its serial number.
EXPECT_TRUE(device_permissions->FindUsbDeviceEntry(device0_).get());
// Device 1 does not have a serial number and cannot be distinguished from
// any other device of the same model so the app must request permission again
// when it is reconnected.
EXPECT_FALSE(device_permissions->FindUsbDeviceEntry(device1_).get());
EXPECT_FALSE(device_permissions->FindUsbDeviceEntry(device2_).get());
EXPECT_FALSE(device_permissions->FindUsbDeviceEntry(device3_).get());
// Device 4 is like device 0, but HID.
EXPECT_TRUE(device_permissions->FindHidDeviceEntry(*device4_).get());
// Device 5 is like device 1, but HID.
EXPECT_FALSE(device_permissions->FindHidDeviceEntry(*device5_).get());
EXPECT_FALSE(device_permissions->FindHidDeviceEntry(*device6_).get());
EXPECT_FALSE(device_permissions->FindHidDeviceEntry(*device7_).get());
}
TEST_F(DevicePermissionsManagerTest, RevokeAndRegrantAccess) {
DevicePermissionsManager* manager =
DevicePermissionsManager::Get(env_->profile());
manager->AllowUsbDevice(extension_->id(), device0_);
manager->AllowUsbDevice(extension_->id(), device1_);
manager->AllowHidDevice(extension_->id(), *device4_);
manager->AllowHidDevice(extension_->id(), *device5_);
DevicePermissions* device_permissions =
manager->GetForExtension(extension_->id());
scoped_refptr<DevicePermissionEntry> device0_entry =
device_permissions->FindUsbDeviceEntry(device0_);
ASSERT_TRUE(device0_entry.get());
scoped_refptr<DevicePermissionEntry> device1_entry =
device_permissions->FindUsbDeviceEntry(device1_);
ASSERT_TRUE(device1_entry.get());
scoped_refptr<DevicePermissionEntry> device4_entry =
device_permissions->FindHidDeviceEntry(*device4_);
ASSERT_TRUE(device4_entry.get());
scoped_refptr<DevicePermissionEntry> device5_entry =
device_permissions->FindHidDeviceEntry(*device5_);
ASSERT_TRUE(device5_entry.get());
manager->RemoveEntry(extension_->id(), device0_entry);
EXPECT_FALSE(device_permissions->FindUsbDeviceEntry(device0_).get());
EXPECT_TRUE(device_permissions->FindUsbDeviceEntry(device1_).get());
manager->AllowUsbDevice(extension_->id(), device0_);
EXPECT_TRUE(device_permissions->FindUsbDeviceEntry(device0_).get());
EXPECT_TRUE(device_permissions->FindUsbDeviceEntry(device1_).get());
manager->RemoveEntry(extension_->id(), device1_entry);
EXPECT_TRUE(device_permissions->FindUsbDeviceEntry(device0_).get());
EXPECT_FALSE(device_permissions->FindUsbDeviceEntry(device1_).get());
manager->AllowUsbDevice(extension_->id(), device1_);
EXPECT_TRUE(device_permissions->FindUsbDeviceEntry(device0_).get());
EXPECT_TRUE(device_permissions->FindUsbDeviceEntry(device1_).get());
manager->RemoveEntry(extension_->id(), device4_entry);
EXPECT_FALSE(device_permissions->FindHidDeviceEntry(*device4_).get());
EXPECT_TRUE(device_permissions->FindHidDeviceEntry(*device5_).get());
manager->AllowHidDevice(extension_->id(), *device4_);
EXPECT_TRUE(device_permissions->FindHidDeviceEntry(*device4_).get());
EXPECT_TRUE(device_permissions->FindHidDeviceEntry(*device5_).get());
manager->RemoveEntry(extension_->id(), device5_entry);
EXPECT_TRUE(device_permissions->FindHidDeviceEntry(*device4_).get());
EXPECT_FALSE(device_permissions->FindHidDeviceEntry(*device5_).get());
manager->AllowHidDevice(extension_->id(), *device5_);
EXPECT_TRUE(device_permissions->FindHidDeviceEntry(*device4_).get());
EXPECT_TRUE(device_permissions->FindHidDeviceEntry(*device5_).get());
}
TEST_F(DevicePermissionsManagerTest, UpdateLastUsed) {
DevicePermissionsManager* manager =
DevicePermissionsManager::Get(env_->profile());
manager->AllowUsbDevice(extension_->id(), device0_);
manager->AllowHidDevice(extension_->id(), *device4_);
DevicePermissions* device_permissions =
manager->GetForExtension(extension_->id());
scoped_refptr<DevicePermissionEntry> device0_entry =
device_permissions->FindUsbDeviceEntry(device0_);
EXPECT_TRUE(device0_entry->last_used().is_null());
scoped_refptr<DevicePermissionEntry> device4_entry =
device_permissions->FindHidDeviceEntry(*device4_);
EXPECT_TRUE(device4_entry->last_used().is_null());
manager->UpdateLastUsed(extension_->id(), device0_entry);
EXPECT_FALSE(device0_entry->last_used().is_null());
manager->UpdateLastUsed(extension_->id(), device4_entry);
EXPECT_FALSE(device4_entry->last_used().is_null());
}
TEST_F(DevicePermissionsManagerTest, LoadPrefs) {
std::unique_ptr<base::Value> prefs_value = base::test::ParseJson(
"["
" {"
" \"manufacturer_string\": \"Test Manufacturer\","
" \"product_id\": 0,"
" \"product_string\": \"Test Product\","
" \"serial_number\": \"ABCDE\","
" \"type\": \"usb\","
" \"vendor_id\": 0"
" },"
" {"
" \"product_id\": 0,"
" \"product_string\": \"Test HID Device\","
" \"serial_number\": \"abcde\","
" \"type\": \"hid\","
" \"vendor_id\": 0"
" }"
"]");
env_->GetExtensionPrefs()->UpdateExtensionPref(extension_->id(), "devices",
std::move(prefs_value));
DevicePermissionsManager* manager =
DevicePermissionsManager::Get(env_->profile());
DevicePermissions* device_permissions =
manager->GetForExtension(extension_->id());
scoped_refptr<DevicePermissionEntry> device0_entry =
device_permissions->FindUsbDeviceEntry(device0_);
ASSERT_TRUE(device0_entry.get());
EXPECT_FALSE(device_permissions->FindUsbDeviceEntry(device1_).get());
EXPECT_FALSE(device_permissions->FindUsbDeviceEntry(device2_).get());
EXPECT_FALSE(device_permissions->FindUsbDeviceEntry(device3_).get());
scoped_refptr<DevicePermissionEntry> device4_entry =
device_permissions->FindHidDeviceEntry(*device4_);
ASSERT_TRUE(device4_entry.get());
EXPECT_FALSE(device_permissions->FindHidDeviceEntry(*device5_).get());
EXPECT_FALSE(device_permissions->FindHidDeviceEntry(*device6_).get());
EXPECT_FALSE(device_permissions->FindHidDeviceEntry(*device7_).get());
EXPECT_EQ(base::ASCIIToUTF16(
"Test Product from Test Manufacturer (serial number ABCDE)"),
device0_entry->GetPermissionMessageString());
EXPECT_EQ(base::ASCIIToUTF16("Test HID Device (serial number abcde)"),
device4_entry->GetPermissionMessageString());
}
TEST_F(DevicePermissionsManagerTest, PermissionMessages) {
base::string16 empty;
base::string16 product(base::ASCIIToUTF16("Widget"));
base::string16 manufacturer(base::ASCIIToUTF16("ACME"));
base::string16 serial_number(base::ASCIIToUTF16("A"));
EXPECT_EQ(base::ASCIIToUTF16("Unknown product 0001 from vendor 0000"),
DevicePermissionsManager::GetPermissionMessage(
0x0000, 0x0001, empty, empty, empty, false));
EXPECT_EQ(base::ASCIIToUTF16(
"Unknown product 0001 from vendor 0000 (serial number A)"),
DevicePermissionsManager::GetPermissionMessage(
0x0000, 0x0001, empty, empty, base::ASCIIToUTF16("A"), false));
EXPECT_EQ(base::ASCIIToUTF16("Unknown product 0001 from Google Inc."),
DevicePermissionsManager::GetPermissionMessage(
0x18D1, 0x0001, empty, empty, empty, false));
EXPECT_EQ(base::ASCIIToUTF16(
"Unknown product 0001 from Google Inc. (serial number A)"),
DevicePermissionsManager::GetPermissionMessage(
0x18D1, 0x0001, empty, empty, serial_number, false));
EXPECT_EQ(base::ASCIIToUTF16("Nexus One from Google Inc."),
DevicePermissionsManager::GetPermissionMessage(
0x18D1, 0x4E11, empty, empty, empty, true));
EXPECT_EQ(base::ASCIIToUTF16("Nexus One from Google Inc. (serial number A)"),
DevicePermissionsManager::GetPermissionMessage(
0x18D1, 0x4E11, empty, empty, serial_number, true));
EXPECT_EQ(base::ASCIIToUTF16("Nexus One"),
DevicePermissionsManager::GetPermissionMessage(
0x18D1, 0x4E11, empty, empty, empty, false));
EXPECT_EQ(base::ASCIIToUTF16("Nexus One (serial number A)"),
DevicePermissionsManager::GetPermissionMessage(
0x18D1, 0x4E11, empty, empty, serial_number, false));
EXPECT_EQ(base::ASCIIToUTF16("Unknown product 0001 from ACME"),
DevicePermissionsManager::GetPermissionMessage(
0x0000, 0x0001, manufacturer, empty, empty, false));
EXPECT_EQ(
base::ASCIIToUTF16("Unknown product 0001 from ACME (serial number A)"),
DevicePermissionsManager::GetPermissionMessage(
0x0000, 0x0001, manufacturer, empty, serial_number, false));
EXPECT_EQ(base::ASCIIToUTF16("Widget from ACME"),
DevicePermissionsManager::GetPermissionMessage(
0x0001, 0x0000, manufacturer, product, empty, true));
EXPECT_EQ(base::ASCIIToUTF16("Widget from ACME (serial number A)"),
DevicePermissionsManager::GetPermissionMessage(
0x0001, 0x0000, manufacturer, product, serial_number, true));
EXPECT_EQ(base::ASCIIToUTF16("Widget"),
DevicePermissionsManager::GetPermissionMessage(
0x0001, 0x0000, manufacturer, product, empty, false));
EXPECT_EQ(base::ASCIIToUTF16("Widget (serial number A)"),
DevicePermissionsManager::GetPermissionMessage(
0x0001, 0x0000, manufacturer, product, serial_number, false));
}
} // namespace extensions