diff --git a/chrome/browser/extensions/api/hid/hid_device_manager.cc b/chrome/browser/extensions/api/hid/hid_device_manager.cc index a8381b1c3255..45d82a6f87b4 100644 --- a/chrome/browser/extensions/api/hid/hid_device_manager.cc +++ b/chrome/browser/extensions/api/hid/hid_device_manager.cc @@ -11,6 +11,7 @@ #include "device/hid/hid_service.h" using device::HidService; +using device::HidUsageAndPage; namespace extensions { @@ -44,7 +45,8 @@ scoped_ptr HidDeviceManager::GetApiDevices( device::HidDeviceInfo device_info; if (hid_service->GetDeviceInfo(device_id, &device_info)) { if (device_info.vendor_id == vendor_id && - device_info.product_id == product_id) { + device_info.product_id == product_id && + IsDeviceAccessible(device_info)) { api::hid::HidDeviceInfo api_device_info; api_device_info.device_id = resource_id; api_device_info.vendor_id = device_info.vendor_id; @@ -114,4 +116,48 @@ void HidDeviceManager::UpdateDevices() { resource_ids_.swap(new_resource_ids); } +// static +// TODO(rockot): Add some tests for this. +bool HidDeviceManager::IsDeviceAccessible( + const device::HidDeviceInfo& device_info) { + for (std::vector::const_iterator iter = + device_info.usages.begin(); + iter != device_info.usages.end(); ++iter) { + if (!IsUsageAccessible(*iter)) { + return false; + } + } + return true; +} + +// static +bool HidDeviceManager::IsUsageAccessible( + const HidUsageAndPage& usage_and_page) { + if (usage_and_page.usage_page == HidUsageAndPage::kPageKeyboard) + return false; + + if (usage_and_page.usage_page != HidUsageAndPage::kPageGenericDesktop) + return true; + + uint16_t usage = usage_and_page.usage; + if (usage == HidUsageAndPage::kGenericDesktopPointer || + usage == HidUsageAndPage::kGenericDesktopMouse || + usage == HidUsageAndPage::kGenericDesktopKeyboard || + usage == HidUsageAndPage::kGenericDesktopKeypad) { + return false; + } + + if (usage >= HidUsageAndPage::kGenericDesktopSystemControl && + usage <= HidUsageAndPage::kGenericDesktopSystemWarmRestart) { + return false; + } + + if (usage >= HidUsageAndPage::kGenericDesktopSystemDock && + usage <= HidUsageAndPage::kGenericDesktopSystemDisplaySwap) { + return false; + } + + return true; +} + } // namespace extensions diff --git a/chrome/browser/extensions/api/hid/hid_device_manager.h b/chrome/browser/extensions/api/hid/hid_device_manager.h index 84a6e3022e53..c0abedd0ccf6 100644 --- a/chrome/browser/extensions/api/hid/hid_device_manager.h +++ b/chrome/browser/extensions/api/hid/hid_device_manager.h @@ -44,6 +44,15 @@ class HidDeviceManager : public BrowserContextKeyedAPI { void UpdateDevices(); + // Determines if a given device interface should be accessible to API + // consumers. In order for a device interface to be accessible, ALL of its + // specified usages must be accessible. + static bool IsDeviceAccessible(const device::HidDeviceInfo& device_info); + + // Determines if a given usage is available to API consumers. This is used to + // blacklist usages which could be security or privacy concerns. + static bool IsUsageAccessible(const device::HidUsageAndPage& usage_and_page); + base::ThreadChecker thread_checker_; int next_resource_id_; diff --git a/device/hid/hid_usage_and_page.h b/device/hid/hid_usage_and_page.h index e024b2b6b245..98ac80d6b544 100644 --- a/device/hid/hid_usage_and_page.h +++ b/device/hid/hid_usage_and_page.h @@ -46,6 +46,79 @@ struct HidUsageAndPage { kPageMediaCenter = 0xFFBC }; + // These usage enumerations are derived from the HID Usage Tables v1.11 spec. + enum GenericDesktopUsage { + kGenericDesktopUndefined = 0, + kGenericDesktopPointer = 1, + kGenericDesktopMouse = 2, + kGenericDesktopJoystick = 4, + kGenericDesktopGamePad = 5, + kGenericDesktopKeyboard = 6, + kGenericDesktopKeypad = 7, + kGenericDesktopMultiAxisController = 8, + kGenericDesktopX = 0x30, + kGenericDesktopY = 0x31, + kGenericDesktopZ = 0x32, + kGenericDesktopRx = 0x33, + kGenericDesktopRy = 0x34, + kGenericDesktopRz = 0x35, + kGenericDesktopSlider = 0x36, + kGenericDesktopDial = 0x37, + kGenericDesktopWheel = 0x38, + kGenericDesktopHatSwitch = 0x39, + kGenericDesktopCountedBuffer = 0x3a, + kGenericDesktopByteCount = 0x3b, + kGenericDesktopMotionWakeup = 0x3c, + kGenericDesktopStart = 0x3d, + kGenericDesktopSelect = 0x3e, + kGenericDesktopVx = 0x40, + kGenericDesktopVy = 0x41, + kGenericDesktopVz = 0x42, + kGenericDesktopVbrx = 0x43, + kGenericDesktopVbry = 0x44, + kGenericDesktopVbrz = 0x45, + kGenericDesktopVno = 0x46, + + kGenericDesktopSystemControl = 0x80, + kGenericDesktopSystemPowerDown = 0x81, + kGenericDesktopSystemSleep = 0x82, + kGenericDesktopSystemWakeUp = 0x83, + kGenericDesktopSystemContextMenu = 0x84, + kGenericDesktopSystemMainMenu = 0x85, + kGenericDesktopSystemAppMenu = 0x86, + kGenericDesktopSystemMenuHelp = 0x87, + kGenericDesktopSystemMenuExit = 0x88, + kGenericDesktopSystemMenuSelect = 0x89, + kGenericDesktopSystemMenuRight = 0x8a, + kGenericDesktopSystemMenuLeft = 0x8b, + kGenericDesktopSystemMenuUp = 0x8c, + kGenericDesktopSystemMenuDown = 0x8d, + kGenericDesktopSystemColdRestart = 0x8e, + kGenericDesktopSystemWarmRestart = 0x8f, + + kGenericDesktopDPadUp = 0x90, + kGenericDesktopDPadDown = 0x91, + kGenericDesktopDPadLeft = 0x92, + kGenericDesktopDPadRight = 0x93, + + kGenericDesktopSystemDock = 0xa0, + kGenericDesktopSystemUndock = 0xa1, + kGenericDesktopSystemSetup = 0xa2, + kGenericDesktopSystemBreak = 0xa3, + kGenericDesktopSystemDebuggerBreak = 0xa4, + kGenericDesktopApplicationBreak = 0xa5, + kGenericDesktopApplicationDebuggerBreak = 0xa6, + kGenericDesktopSystemSpeakerMute = 0xa7, + kGenericDesktopSystemHibernate = 0xa8, + kGenericDesktopSystemDisplayInvert = 0xb0, + kGenericDesktopSystemDisplayInternal = 0xb1, + kGenericDesktopSystemDisplayExternal = 0xb2, + kGenericDesktopSystemDisplayBoth = 0xb3, + kGenericDesktopSystemDisplayDual = 0xb4, + kGenericDesktopSystemDisplayToggle = 0xb5, + kGenericDesktopSystemDisplaySwap = 0xb6, + }; + HidUsageAndPage(uint16_t usage, Page usage_page) : usage(usage), usage_page(usage_page) {} ~HidUsageAndPage() {}