From c2454884f0878d17ed8096edb22cfaf3209c22ac Mon Sep 17 00:00:00 2001 From: "rockot@chromium.org" Date: Sat, 1 Feb 2014 14:47:15 +0000 Subject: [PATCH] HID API frontend for Apps. This issue is a continuation of https://codereview.chromium.org/145653003/ with some cleanup to reflect conventions adopted by other I/O APIs. BUG=290428 Review URL: https://codereview.chromium.org/149163006 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@248366 0039d316-1c4b-4281-b951-d872f2087c98 --- chrome/app/generated_resources.grd | 3 + chrome/browser/extensions/api/hid/DEPS | 3 + chrome/browser/extensions/api/hid/hid_api.cc | 325 ++++++++++++++++++ chrome/browser/extensions/api/hid/hid_api.h | 193 +++++++++++ .../extensions/api/hid/hid_device_resource.cc | 34 ++ .../extensions/api/hid/hid_device_resource.h | 53 +++ .../extension_function_histogram_value.h | 7 + chrome/chrome_browser_extensions.gypi | 4 + .../common/extensions/api/_api_features.json | 4 + .../extensions/api/_permission_features.json | 4 + chrome/common/extensions/api/api.gyp | 1 + chrome/common/extensions/api/hid.idl | 103 ++++++ .../permissions/chrome_api_permissions.cc | 3 + .../common/permissions/api_permission.h | 1 + .../common/permissions/permission_message.h | 1 + 15 files changed, 739 insertions(+) create mode 100644 chrome/browser/extensions/api/hid/DEPS create mode 100644 chrome/browser/extensions/api/hid/hid_api.cc create mode 100644 chrome/browser/extensions/api/hid/hid_api.h create mode 100644 chrome/browser/extensions/api/hid/hid_device_resource.cc create mode 100644 chrome/browser/extensions/api/hid/hid_device_resource.h create mode 100644 chrome/common/extensions/api/hid.idl diff --git a/chrome/app/generated_resources.grd b/chrome/app/generated_resources.grd index b501d19040cbb6..0d7d71defffe81 100644 --- a/chrome/app/generated_resources.grd +++ b/chrome/app/generated_resources.grd @@ -4285,6 +4285,9 @@ Make sure you do not expose any sensitive information. Access USB devices + + Access HID (Human Interface Device) devices + Access information about Bluetooth devices paired with your system. diff --git a/chrome/browser/extensions/api/hid/DEPS b/chrome/browser/extensions/api/hid/DEPS new file mode 100644 index 00000000000000..76a0f69b39ad53 --- /dev/null +++ b/chrome/browser/extensions/api/hid/DEPS @@ -0,0 +1,3 @@ +include_rules = [ + "+device/hid", +] diff --git a/chrome/browser/extensions/api/hid/hid_api.cc b/chrome/browser/extensions/api/hid/hid_api.cc new file mode 100644 index 00000000000000..e5e8eb38a9a676 --- /dev/null +++ b/chrome/browser/extensions/api/hid/hid_api.cc @@ -0,0 +1,325 @@ +// 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 "chrome/browser/extensions/api/hid/hid_api.h" + +#include +#include + +#include "chrome/browser/extensions/api/api_resource_manager.h" +#include "chrome/browser/extensions/api/hid/hid_device_resource.h" +#include "chrome/common/extensions/api/hid.h" +#include "chrome/common/extensions/permissions/usb_device_permission.h" +#include "device/hid/hid_connection.h" +#include "device/hid/hid_device_info.h" +#include "device/hid/hid_service.h" +#include "extensions/common/permissions/permissions_data.h" +#include "net/base/io_buffer.h" + +namespace hid = extensions::api::hid; + +using device::HidConnection; +using device::HidService; +using device::HidDeviceInfo; + +namespace { + +const char kErrorPermissionDenied[] = "Permission to access device was denied."; +const char kErrorServiceFailed[] = "HID service failed be created."; +const char kErrorDeviceNotFound[] = "HID device not found."; +const char kErrorFailedToOpenDevice[] = "Failed to open HID device."; +const char kErrorConnectionNotFound[] = "Connection not established."; +const char kErrorTransfer[] = "Transfer failed."; + +base::Value* PopulateHidDevice(const HidDeviceInfo& info) { + hid::HidDeviceInfo device_info; + device_info.path = info.device_id; + device_info.product_id = info.product_id; + device_info.vendor_id = info.vendor_id; + return device_info.ToValue().release(); +} + +base::Value* PopulateHidConnection(int connection_id, + scoped_refptr connection) { + hid::HidConnectInfo connection_value; + connection_value.connection_id = connection_id; + return connection_value.ToValue().release(); +} + +} // namespace + +namespace extensions { + +HidAsyncApiFunction::HidAsyncApiFunction() : manager_(NULL) { +} + +HidAsyncApiFunction::~HidAsyncApiFunction() {} + +bool HidAsyncApiFunction::PrePrepare() { + manager_ = ApiResourceManager::Get(GetProfile()); + if (!manager_) return false; + set_work_thread_id(content::BrowserThread::FILE); + return true; +} + +bool HidAsyncApiFunction::Respond() { return error_.empty(); } + +HidConnectionResource* HidAsyncApiFunction::GetHidConnectionResource( + int api_resource_id) { + return manager_->Get(extension_->id(), api_resource_id); +} + +void HidAsyncApiFunction::RemoveHidConnectionResource(int api_resource_id) { + manager_->Remove(extension_->id(), api_resource_id); +} + +void HidAsyncApiFunction::CompleteWithError(const std::string& error) { + SetError(error); + AsyncWorkCompleted(); +} + +HidGetDevicesFunction::HidGetDevicesFunction() {} + +HidGetDevicesFunction::~HidGetDevicesFunction() {} + +bool HidGetDevicesFunction::Prepare() { + parameters_ = hid::GetDevices::Params::Create(*args_); + EXTENSION_FUNCTION_VALIDATE(parameters_.get()); + return true; +} + +void HidGetDevicesFunction::AsyncWorkStart() { + const uint16_t vendor_id = parameters_->options.vendor_id; + const uint16_t product_id = parameters_->options.product_id; + UsbDevicePermission::CheckParam param( + vendor_id, product_id, UsbDevicePermissionData::UNSPECIFIED_INTERFACE); + if (!PermissionsData::CheckAPIPermissionWithParam( + GetExtension(), APIPermission::kUsbDevice, ¶m)) { + LOG(WARNING) << "Insufficient permissions to access device."; + CompleteWithError(kErrorPermissionDenied); + return; + } + + HidService* service = HidService::GetInstance(); + if (!service) { + CompleteWithError(kErrorServiceFailed); + return; + } + std::vector devices; + service->GetDevices(&devices); + + scoped_ptr result(new base::ListValue()); + for (std::vector::iterator it = devices.begin(); + it != devices.end(); it++) { + if (it->product_id == product_id && + it->vendor_id == vendor_id) + result->Append(PopulateHidDevice(*it)); + } + SetResult(result.release()); + AsyncWorkCompleted(); +} + +HidConnectFunction::HidConnectFunction() {} + +HidConnectFunction::~HidConnectFunction() {} + +bool HidConnectFunction::Prepare() { + parameters_ = hid::Connect::Params::Create(*args_); + EXTENSION_FUNCTION_VALIDATE(parameters_.get()); + return true; +} + +void HidConnectFunction::AsyncWorkStart() { + HidService* service = HidService::GetInstance(); + if (!service) { + CompleteWithError(kErrorServiceFailed); + return; + } + HidDeviceInfo device; + if (!service->GetInfo(parameters_->device_info.path, &device)) { + CompleteWithError(kErrorDeviceNotFound); + return; + } + if (device.vendor_id != parameters_->device_info.vendor_id || + device.product_id != parameters_->device_info.product_id) { + CompleteWithError(kErrorDeviceNotFound); + return; + } + scoped_refptr connection = service->Connect(device.device_id); + if (!connection) { + CompleteWithError(kErrorFailedToOpenDevice); + return; + } + int connection_id = + manager_->Add(new HidConnectionResource(extension_->id(), connection)); + SetResult(PopulateHidConnection(connection_id, connection)); + AsyncWorkCompleted(); +} + +HidDisconnectFunction::HidDisconnectFunction() {} + +HidDisconnectFunction::~HidDisconnectFunction() {} + +bool HidDisconnectFunction::Prepare() { + parameters_ = hid::Disconnect::Params::Create(*args_); + EXTENSION_FUNCTION_VALIDATE(parameters_.get()); + return true; +} + +void HidDisconnectFunction::AsyncWorkStart() { + int connection_id = parameters_->connection_id; + HidConnectionResource* resource = + manager_->Get(extension_->id(), connection_id); + if (!resource) { + CompleteWithError(kErrorConnectionNotFound); + return; + } + manager_->Remove(extension_->id(), connection_id); + AsyncWorkCompleted(); +} + +HidReceiveFunction::HidReceiveFunction() {} + +HidReceiveFunction::~HidReceiveFunction() {} + +bool HidReceiveFunction::Prepare() { + parameters_ = hid::Receive::Params::Create(*args_); + EXTENSION_FUNCTION_VALIDATE(parameters_.get()); + return true; +} + +void HidReceiveFunction::AsyncWorkStart() { + int connection_id = parameters_->connection_id; + HidConnectionResource* resource = + manager_->Get(extension_->id(), connection_id); + if (!resource) { + CompleteWithError(kErrorConnectionNotFound); + return; + } + + buffer_ = new net::IOBuffer(parameters_->size); + resource->connection()->Read( + buffer_, + parameters_->size, + base::Bind(&HidReceiveFunction::OnFinished, this)); +} + +void HidReceiveFunction::OnFinished(bool success, size_t bytes) { + if (!success) { + CompleteWithError(kErrorTransfer); + return; + } + + SetResult(base::BinaryValue::CreateWithCopiedBuffer(buffer_->data(), bytes)); + AsyncWorkCompleted(); +} + +HidSendFunction::HidSendFunction() {} + +HidSendFunction::~HidSendFunction() {} + +bool HidSendFunction::Prepare() { + parameters_ = hid::Send::Params::Create(*args_); + EXTENSION_FUNCTION_VALIDATE(parameters_.get()); + return true; +} + +void HidSendFunction::AsyncWorkStart() { + int connection_id = parameters_->connection_id; + HidConnectionResource* resource = + manager_->Get(extension_->id(), connection_id); + if (!resource) { + CompleteWithError(kErrorConnectionNotFound); + return; + } + + scoped_refptr buffer( + new net::WrappedIOBuffer(parameters_->data.c_str())); + memcpy(buffer->data(), + parameters_->data.c_str(), + parameters_->data.size()); + resource->connection()->Write( + buffer, + parameters_->data.size(), + base::Bind(&HidSendFunction::OnFinished, this)); +} + +void HidSendFunction::OnFinished(bool success, size_t bytes) { + if (!success) { + CompleteWithError(kErrorTransfer); + return; + } + AsyncWorkCompleted(); +} + +HidReceiveFeatureReportFunction::HidReceiveFeatureReportFunction() {} + +HidReceiveFeatureReportFunction::~HidReceiveFeatureReportFunction() {} + +bool HidReceiveFeatureReportFunction::Prepare() { + parameters_ = hid::ReceiveFeatureReport::Params::Create(*args_); + EXTENSION_FUNCTION_VALIDATE(parameters_.get()); + return true; +} + +void HidReceiveFeatureReportFunction::AsyncWorkStart() { + int connection_id = parameters_->connection_id; + HidConnectionResource* resource = + manager_->Get(extension_->id(), connection_id); + if (!resource) { + CompleteWithError(kErrorConnectionNotFound); + return; + } + buffer_ = new net::IOBuffer(parameters_->size); + resource->connection()->GetFeatureReport( + buffer_, + parameters_->size, + base::Bind(&HidReceiveFeatureReportFunction::OnFinished, this)); +} + +void HidReceiveFeatureReportFunction::OnFinished(bool success, size_t bytes) { + if (!success) { + CompleteWithError(kErrorTransfer); + return; + } + + SetResult(base::BinaryValue::CreateWithCopiedBuffer(buffer_->data(), bytes)); + AsyncWorkCompleted(); +} + +HidSendFeatureReportFunction::HidSendFeatureReportFunction() {} + +HidSendFeatureReportFunction::~HidSendFeatureReportFunction() {} + +bool HidSendFeatureReportFunction::Prepare() { + parameters_ = hid::SendFeatureReport::Params::Create(*args_); + EXTENSION_FUNCTION_VALIDATE(parameters_.get()); + return true; +} + +void HidSendFeatureReportFunction::AsyncWorkStart() { + int connection_id = parameters_->connection_id; + HidConnectionResource* resource = + manager_->Get(extension_->id(), connection_id); + if (!resource) { + CompleteWithError(kErrorConnectionNotFound); + return; + } + scoped_refptr buffer( + new net::WrappedIOBuffer(parameters_->data.c_str())); + resource->connection()->SendFeatureReport( + buffer, + parameters_->data.size(), + base::Bind(&HidSendFeatureReportFunction::OnFinished, this)); +} + +void HidSendFeatureReportFunction::OnFinished(bool success, size_t bytes) { + if (!success) { + CompleteWithError(kErrorTransfer); + return; + } + AsyncWorkCompleted(); +} + +} // namespace extensions diff --git a/chrome/browser/extensions/api/hid/hid_api.h b/chrome/browser/extensions/api/hid/hid_api.h new file mode 100644 index 00000000000000..3a443c217043e6 --- /dev/null +++ b/chrome/browser/extensions/api/hid/hid_api.h @@ -0,0 +1,193 @@ +// 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. + +#ifndef CHROME_BROWSER_EXTENSIONS_API_HID_HID_API_H_ +#define CHROME_BROWSER_EXTENSIONS_API_HID_HID_API_H_ + +#include + +#include "base/basictypes.h" +#include "base/memory/ref_counted.h" +#include "chrome/browser/extensions/api/api_function.h" +#include "chrome/browser/extensions/api/api_resource_manager.h" +#include "chrome/browser/extensions/api/hid/hid_device_resource.h" +#include "chrome/browser/extensions/extension_function_histogram_value.h" +#include "chrome/common/extensions/api/hid.h" + +namespace net { + +class IOBuffer; + +} // namespace net + +namespace extensions { + +class HidAsyncApiFunction : public AsyncApiFunction { + public: + HidAsyncApiFunction(); + + virtual bool PrePrepare() OVERRIDE; + virtual bool Respond() OVERRIDE; + + protected: + virtual ~HidAsyncApiFunction(); + + HidConnectionResource* GetHidConnectionResource(int api_resource_id); + void RemoveHidConnectionResource(int api_resource_id); + + void CompleteWithError(const std::string& error); + + ApiResourceManager* manager_; + + private: + DISALLOW_COPY_AND_ASSIGN(HidAsyncApiFunction); +}; + +class HidGetDevicesFunction : public HidAsyncApiFunction { + public: + DECLARE_EXTENSION_FUNCTION("hid.getDevices", HID_GETDEVICES); + + HidGetDevicesFunction(); + + protected: + virtual bool Prepare() OVERRIDE; + virtual void AsyncWorkStart() OVERRIDE; + + virtual ~HidGetDevicesFunction(); + + scoped_ptr result_; + scoped_ptr parameters_; + + private: + DISALLOW_COPY_AND_ASSIGN(HidGetDevicesFunction); +}; + +class HidConnectFunction : public HidAsyncApiFunction { + public: + DECLARE_EXTENSION_FUNCTION("hid.connect", HID_CONNECT); + + HidConnectFunction(); + + protected: + virtual bool Prepare() OVERRIDE; + virtual void AsyncWorkStart() OVERRIDE; + + private: + virtual ~HidConnectFunction(); + + scoped_ptr result_; + scoped_ptr parameters_; + + DISALLOW_COPY_AND_ASSIGN(HidConnectFunction); +}; + +class HidDisconnectFunction : public HidAsyncApiFunction { + public: + DECLARE_EXTENSION_FUNCTION("hid.disconnect", HID_DISCONNECT); + + HidDisconnectFunction(); + + protected: + virtual bool Prepare() OVERRIDE; + virtual void AsyncWorkStart() OVERRIDE; + + private: + virtual ~HidDisconnectFunction(); + + scoped_ptr result_; + scoped_ptr parameters_; + + DISALLOW_COPY_AND_ASSIGN(HidDisconnectFunction); +}; + +class HidReceiveFunction : public HidAsyncApiFunction { + public: + DECLARE_EXTENSION_FUNCTION("hid.receive", HID_RECEIVE); + + HidReceiveFunction(); + + protected: + virtual bool Prepare() OVERRIDE; + virtual void AsyncWorkStart() OVERRIDE; + + private: + virtual ~HidReceiveFunction(); + + void OnFinished(bool success, size_t bytes); + + scoped_refptr buffer_; + scoped_ptr result_; + scoped_ptr parameters_; + + DISALLOW_COPY_AND_ASSIGN(HidReceiveFunction); +}; + +class HidSendFunction : public HidAsyncApiFunction { + public: + DECLARE_EXTENSION_FUNCTION("hid.send", HID_SEND); + + HidSendFunction(); + + protected: + virtual bool Prepare() OVERRIDE; + virtual void AsyncWorkStart() OVERRIDE; + + private: + virtual ~HidSendFunction(); + + void OnFinished(bool success, size_t bytes); + + scoped_ptr result_; + scoped_ptr parameters_; + + DISALLOW_COPY_AND_ASSIGN(HidSendFunction); +}; + +class HidReceiveFeatureReportFunction : public HidAsyncApiFunction { + public: + DECLARE_EXTENSION_FUNCTION("hid.receiveFeatureReport", + HID_RECEIVEFEATUREREPORT); + + HidReceiveFeatureReportFunction(); + + protected: + virtual bool Prepare() OVERRIDE; + virtual void AsyncWorkStart() OVERRIDE; + + private: + virtual ~HidReceiveFeatureReportFunction(); + + void OnFinished(bool success, size_t bytes); + + scoped_refptr buffer_; + scoped_ptr result_; + scoped_ptr parameters_; + + DISALLOW_COPY_AND_ASSIGN(HidReceiveFeatureReportFunction); +}; + +class HidSendFeatureReportFunction : public HidAsyncApiFunction { + public: + DECLARE_EXTENSION_FUNCTION("hid.sendFeatureReport", HID_SENDFEATUREREPORT); + + HidSendFeatureReportFunction(); + + protected: + virtual bool Prepare() OVERRIDE; + virtual void AsyncWorkStart() OVERRIDE; + + private: + virtual ~HidSendFeatureReportFunction(); + + void OnFinished(bool success, size_t bytes); + + scoped_ptr result_; + scoped_ptr parameters_; + + DISALLOW_COPY_AND_ASSIGN(HidSendFeatureReportFunction); +}; + +} // namespace extensions + +#endif // CHROME_BROWSER_EXTENSIONS_API_HID_HID_API_H_ diff --git a/chrome/browser/extensions/api/hid/hid_device_resource.cc b/chrome/browser/extensions/api/hid/hid_device_resource.cc new file mode 100644 index 00000000000000..074337a2a6810b --- /dev/null +++ b/chrome/browser/extensions/api/hid/hid_device_resource.cc @@ -0,0 +1,34 @@ +// 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 "chrome/browser/extensions/api/hid/hid_device_resource.h" + +#include + +#include "base/bind.h" +#include "base/bind_helpers.h" +#include "base/memory/ref_counted.h" +#include "device/hid/hid_connection.h" + +namespace extensions { + +static base::LazyInstance > > + g_factory = LAZY_INSTANCE_INITIALIZER; + +// static +template <> +ProfileKeyedAPIFactory >* +ApiResourceManager::GetFactoryInstance() { + return &g_factory.Get(); +} + +HidConnectionResource::HidConnectionResource( + const std::string& owner_extension_id, + scoped_refptr connection) + : ApiResource(owner_extension_id), connection_(connection) {} + +HidConnectionResource::~HidConnectionResource() {} + +} // namespace extensions diff --git a/chrome/browser/extensions/api/hid/hid_device_resource.h b/chrome/browser/extensions/api/hid/hid_device_resource.h new file mode 100644 index 00000000000000..84b9153041b8d4 --- /dev/null +++ b/chrome/browser/extensions/api/hid/hid_device_resource.h @@ -0,0 +1,53 @@ +// 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. + +#ifndef CHROME_BROWSER_EXTENSIONS_API_HID_HID_DEVICE_RESOURCE_H_ +#define CHROME_BROWSER_EXTENSIONS_API_HID_HID_DEVICE_RESOURCE_H_ + +#include + +#include "base/basictypes.h" +#include "base/lazy_instance.h" +#include "base/memory/ref_counted.h" +#include "chrome/browser/extensions/api/api_resource.h" +#include "chrome/browser/extensions/api/api_resource_manager.h" +#include "content/public/browser/browser_thread.h" +#include "device/hid/hid_connection.h" +#include "device/hid/hid_device_info.h" + +namespace net { +class IOBuffer; +} // namespace net + +namespace extensions { + +class HidConnectionResource : public ApiResource { + public: + HidConnectionResource(const std::string& owner_extension_id, + scoped_refptr connection); + + virtual ~HidConnectionResource(); + + scoped_refptr connection() { + return connection_; + } + + private: + friend class ApiResourceManager; + static const char* service_name() { + return "HidDeviceResourceManager"; + } + + + static const content::BrowserThread::ID kThreadId = + content::BrowserThread::FILE; + + scoped_refptr connection_; + + DISALLOW_COPY_AND_ASSIGN(HidConnectionResource); +}; + +} // namespace extensions + +#endif // CHROME_BROWSER_EXTENSIONS_API_HID_HID_DEVICE_RESOURCE_H_ diff --git a/chrome/browser/extensions/extension_function_histogram_value.h b/chrome/browser/extensions/extension_function_histogram_value.h index 6108df8932cb0d..0443c083fe6f95 100644 --- a/chrome/browser/extensions/extension_function_histogram_value.h +++ b/chrome/browser/extensions/extension_function_histogram_value.h @@ -730,6 +730,13 @@ enum HistogramValue { FILEBROWSERPRIVATE_GETPROFILES, FILEBROWSERPRIVATE_VISITDESKTOP, VIRTUALKEYBOARDPRIVATE_GETKEYBOARDCONFIG, + HID_GETDEVICES, + HID_CONNECT, + HID_DISCONNECT, + HID_RECEIVE, + HID_SEND, + HID_RECEIVEFEATUREREPORT, + HID_SENDFEATUREREPORT, ENUM_BOUNDARY // Last entry: Add new entries above. }; diff --git a/chrome/chrome_browser_extensions.gypi b/chrome/chrome_browser_extensions.gypi index 501b4fd6fc9677..b27992a7dfc8c2 100644 --- a/chrome/chrome_browser_extensions.gypi +++ b/chrome/chrome_browser_extensions.gypi @@ -284,6 +284,10 @@ 'browser/extensions/api/font_settings/font_settings_api.h', 'browser/extensions/api/gcm/gcm_api.cc', 'browser/extensions/api/gcm/gcm_api.h', + 'browser/extensions/api/hid/hid_api.cc', + 'browser/extensions/api/hid/hid_api.h', + 'browser/extensions/api/hid/hid_device_resource.cc', + 'browser/extensions/api/hid/hid_device_resource.h', 'browser/extensions/api/history/history_api.h', 'browser/extensions/api/history/history_api.cc', 'browser/extensions/api/i18n/i18n_api.cc', diff --git a/chrome/common/extensions/api/_api_features.json b/chrome/common/extensions/api/_api_features.json index e9b66e889423ae..0dfda8b6e12800 100644 --- a/chrome/common/extensions/api/_api_features.json +++ b/chrome/common/extensions/api/_api_features.json @@ -360,6 +360,10 @@ "eggnbpckecmjlblplehfpjjdhhidfdoj" ] }, + "hid": { + "dependencies": ["permission:hid"], + "contexts": ["blessed_extension"] + }, "history": { "dependencies": ["permission:history"], "contexts": ["blessed_extension"] diff --git a/chrome/common/extensions/api/_permission_features.json b/chrome/common/extensions/api/_permission_features.json index 18c1e1f56ff84a..3da804ccb8b66c 100644 --- a/chrome/common/extensions/api/_permission_features.json +++ b/chrome/common/extensions/api/_permission_features.json @@ -418,6 +418,10 @@ "extension", "legacy_packaged_app", "hosted_app", "platform_app" ] }, + "hid": { + "channel": "dev", + "extension_types": ["platform_app"] + }, "history": { "channel": "stable", "extension_types": ["extension", "legacy_packaged_app"] diff --git a/chrome/common/extensions/api/api.gyp b/chrome/common/extensions/api/api.gyp index b6dfc90a9488a8..e32291d85bf603 100644 --- a/chrome/common/extensions/api/api.gyp +++ b/chrome/common/extensions/api/api.gyp @@ -70,6 +70,7 @@ 'font_settings.json', 'gcm.json', 'hangouts_private.idl', + 'hid.idl', 'history.json', 'i18n.json', 'identity.idl', diff --git a/chrome/common/extensions/api/hid.idl b/chrome/common/extensions/api/hid.idl new file mode 100644 index 00000000000000..6923a3ab940329 --- /dev/null +++ b/chrome/common/extensions/api/hid.idl @@ -0,0 +1,103 @@ +// 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. + +// Use the chrome.hid API to interact with connected HID devices. +// This API provides access to HID operations from within the context of an app. +// Using this API, apps can function as drivers for hardware devices. +namespace hid { + + // Returned by getDevices functions to describes a connected HID + // device. Use connect to connect to any of the returned devices. + dictionary HidDeviceInfo { + DOMString path; + long vendorId; + long productId; + }; + + // Returned by connect to represent a communication session with + // an HID device. Must be closed with a call to disconnect. + dictionary HidConnectInfo { + long connectionId; + }; + + // Searching criteria to enumerate devices with. + dictionary GetDevicesOptions { + long vendorId; + long productId; + }; + + callback GetDevicesCallback = void (HidDeviceInfo[] devices); + callback ConnectCallback = void (HidConnectInfo connection); + callback DisconnectCallback = void (); + + // The callback to be invoked when a receive or + // receiveFeatureReport call is finished. + // |data|: The content of the report. + callback ReceiveCallback = void (ArrayBuffer data); + callback SendCallback = void(); + + interface Functions { + // Enumerate all the connected HID devices specified by the vendorId/ + // productId/interfaceId tuple. + // |options|: The properties to search for on target devices. + // |callback|: Invoked with the HidDeviceInfo array on success. + static void getDevices(GetDevicesOptions options, + GetDevicesCallback callback); + + // Open a connection to an HID device for communication. + // |deviceInfo|: The device to open. + // |callback|: Invoked with an HidConnectInfo. + static void connect(HidDeviceInfo deviceInfo, + ConnectCallback callback); + + // Disconnect from a device. Invoking operations on a device after calling + // this is safe but has no effect. + // |connectionId|: The connection to close. + // |callback|: The callback to invoke once the device is closed. + static void disconnect(long connectionId, + optional DisconnectCallback callback); + + // Receive an Input report from an HID device. + // + // Input reports are returned to the host through the INTERRUPT IN endpoint. + // |connectionId|: The connection from which to receive a report. + // |size|: The size of the Input report to receive. + // |callback|: The callback to invoke with received report. + static void receive(long connectionId, + long size, + ReceiveCallback callback); + + // Send an Output report to an HID device. + // send will send the data on the first OUT endpoint, if one + // exists. If one does not exist, the report will be sent through the + // Control endpoint. + // + // |connectionId|: The connection to which to send a report. + // |data|: The report data. + // |callback|: The callback to invoke once the write is finished. + static void send(long connectionId, + ArrayBuffer data, + SendCallback callback); + + // Receive a Feature report from the device. + // + // |connectionId|: The connection to read Input report from. + // |size|: The size of the Feature report to receive. + // |callback|: The callback to invoke once the write is finished. + static void receiveFeatureReport(long connectionId, + long size, + ReceiveCallback callback); + + // Send a Feature report to the device. + // + // Feature reports are sent over the Control endpoint as a Set_Report + // transfer. + // |connectionId|: The connection to read Input report from. + // |data|: The report data. + // |callback|: The callback to invoke once the write is finished. + static void sendFeatureReport(long connectionId, + ArrayBuffer data, + SendCallback callback); + }; +}; diff --git a/chrome/common/extensions/permissions/chrome_api_permissions.cc b/chrome/common/extensions/permissions/chrome_api_permissions.cc index a828d43c5ddcba..bd06b4c5c77b9a 100644 --- a/chrome/common/extensions/permissions/chrome_api_permissions.cc +++ b/chrome/common/extensions/permissions/chrome_api_permissions.cc @@ -318,6 +318,9 @@ std::vector ChromeAPIPermissions::GetAllPermissions() APIPermissionInfo::kFlagNone, IDS_EXTENSION_PROMPT_WARNING_FILE_SYSTEM_WRITE_DIRECTORY, PermissionMessage::kFileSystemWriteDirectory }, + { APIPermission::kHid, "hid", APIPermissionInfo::kFlagNone, + IDS_EXTENSION_PROMPT_WARNING_HID, + PermissionMessage::kHid }, // Because warning messages for the "mediaGalleries" permission vary based // on the permissions parameters, no message ID or message text is // specified here. diff --git a/extensions/common/permissions/api_permission.h b/extensions/common/permissions/api_permission.h index b8f23f81210c48..f3e3c6b6c410c0 100644 --- a/extensions/common/permissions/api_permission.h +++ b/extensions/common/permissions/api_permission.h @@ -90,6 +90,7 @@ class APIPermission { kFullscreen, kGcm, kGeolocation, + kHid, kHistory, kHomepage, kIdentity, diff --git a/extensions/common/permissions/permission_message.h b/extensions/common/permissions/permission_message.h index e745b59976f74b..9c3fe7ec1ca193 100644 --- a/extensions/common/permissions/permission_message.h +++ b/extensions/common/permissions/permission_message.h @@ -31,6 +31,7 @@ class PermissionMessage { kManagement, kDebugger, kDesktopCapture, + kHid, kHosts1, kHosts2, kHosts3,