summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorreillyg <reillyg@chromium.org>2015-09-17 19:52:02 -0700
committerCommit bot <commit-bot@chromium.org>2015-09-18 02:52:47 +0000
commit98624c769a5268117f4336a46d68c1e5bd5050bd (patch)
tree23e7044ef0c1aff2a41c383d494639d86fe0551e
parent717e49ce3d4eb2949bd1568011de98003667fd07 (diff)
downloadchromium_src-98624c769a5268117f4336a46d68c1e5bd5050bd.zip
chromium_src-98624c769a5268117f4336a46d68c1e5bd5050bd.tar.gz
chromium_src-98624c769a5268117f4336a46d68c1e5bd5050bd.tar.bz2
Add chrome.usb.getConfigurations function.
Add a new extension function that returns all of the configuration descriptors from the provided USB device. In addition to exposing this useful information to applications (as otherwise they would need to call chrome.usb.setConfiguration blindly to set a non-default configuration) it is also now available without having to call chrome.usb.openDevice first. BUG=531586 Review URL: https://codereview.chromium.org/1357523005 Cr-Commit-Position: refs/heads/master@{#349592}
-rw-r--r--device/usb/mock_usb_device.cc15
-rw-r--r--device/usb/mock_usb_device.h6
-rw-r--r--extensions/browser/api/usb/usb_api.cc47
-rw-r--r--extensions/browser/api/usb/usb_api.h15
-rw-r--r--extensions/browser/api/usb/usb_apitest.cc13
-rw-r--r--extensions/browser/extension_function_histogram_value.h1
-rw-r--r--extensions/common/api/usb.idl8
-rw-r--r--extensions/test/data/api_test/usb/device_handling/test.js18
-rw-r--r--tools/metrics/histograms/histograms.xml1
9 files changed, 121 insertions, 3 deletions
diff --git a/device/usb/mock_usb_device.cc b/device/usb/mock_usb_device.cc
index da902c0..1b3e69b 100644
--- a/device/usb/mock_usb_device.cc
+++ b/device/usb/mock_usb_device.cc
@@ -45,6 +45,21 @@ MockUsbDevice::MockUsbDevice(uint16 vendor_id,
configurations_.push_back(configuration);
}
+MockUsbDevice::MockUsbDevice(
+ uint16 vendor_id,
+ uint16 product_id,
+ const std::string& manufacturer_string,
+ const std::string& product_string,
+ const std::string& serial_number,
+ const std::vector<UsbConfigDescriptor>& configurations)
+ : MockUsbDevice(vendor_id,
+ product_id,
+ manufacturer_string,
+ product_string,
+ serial_number) {
+ configurations_ = configurations;
+}
+
MockUsbDevice::~MockUsbDevice() {
}
diff --git a/device/usb/mock_usb_device.h b/device/usb/mock_usb_device.h
index d4dbbac..9dc107a 100644
--- a/device/usb/mock_usb_device.h
+++ b/device/usb/mock_usb_device.h
@@ -31,6 +31,12 @@ class MockUsbDevice : public UsbDevice {
MockUsbDevice(uint16 vendor_id,
uint16 product_id,
const UsbConfigDescriptor& configuration);
+ MockUsbDevice(uint16 vendor_id,
+ uint16 product_id,
+ const std::string& manufacturer_string,
+ const std::string& product_string,
+ const std::string& serial_number,
+ const std::vector<UsbConfigDescriptor>& configurations);
MOCK_METHOD1(Open, void(const OpenCallback&));
MOCK_METHOD1(Close, bool(scoped_refptr<UsbDeviceHandle>));
diff --git a/extensions/browser/api/usb/usb_api.cc b/extensions/browser/api/usb/usb_api.cc
index f45ef43..6979868 100644
--- a/extensions/browser/api/usb/usb_api.cc
+++ b/extensions/browser/api/usb/usb_api.cc
@@ -29,6 +29,7 @@ namespace ClaimInterface = usb::ClaimInterface;
namespace CloseDevice = usb::CloseDevice;
namespace ControlTransfer = usb::ControlTransfer;
namespace FindDevices = usb::FindDevices;
+namespace GetConfigurations = usb::GetConfigurations;
namespace GetDevices = usb::GetDevices;
namespace GetUserSelectedDevices = usb::GetUserSelectedDevices;
namespace InterruptTransfer = usb::InterruptTransfer;
@@ -644,6 +645,51 @@ void UsbGetUserSelectedDevicesFunction::OnDevicesChosen(
Respond(OneArgument(result.Pass()));
}
+UsbGetConfigurationsFunction::UsbGetConfigurationsFunction() {}
+
+UsbGetConfigurationsFunction::~UsbGetConfigurationsFunction() {}
+
+ExtensionFunction::ResponseAction UsbGetConfigurationsFunction::Run() {
+ scoped_ptr<extensions::api::usb::GetConfigurations::Params> parameters =
+ GetConfigurations::Params::Create(*args_);
+ EXTENSION_FUNCTION_VALIDATE(parameters.get());
+
+ UsbService* service = device::DeviceClient::Get()->GetUsbService();
+ if (!service) {
+ return RespondNow(Error(kErrorInitService));
+ }
+
+ std::string guid;
+ if (!UsbGuidMap::Get(browser_context())
+ ->GetGuidFromId(parameters->device.device, &guid)) {
+ return RespondNow(Error(kErrorNoDevice));
+ }
+
+ scoped_refptr<UsbDevice> device = service->GetDevice(guid);
+ if (!device.get()) {
+ return RespondNow(Error(kErrorNoDevice));
+ }
+
+ if (!HasDevicePermission(device)) {
+ // This function must act as if there is no such device. Otherwise it can be
+ // used to fingerprint unauthorized devices.
+ return RespondNow(Error(kErrorNoDevice));
+ }
+
+ scoped_ptr<base::ListValue> configs(new base::ListValue());
+ const UsbConfigDescriptor* active_config = device->GetActiveConfiguration();
+ for (const UsbConfigDescriptor& config : device->configurations()) {
+ ConfigDescriptor api_config;
+ ConvertConfigDescriptor(config, &api_config);
+ if (active_config &&
+ config.configuration_value == active_config->configuration_value) {
+ api_config.active = true;
+ }
+ configs->Append(api_config.ToValue());
+ }
+ return RespondNow(OneArgument(configs.Pass()));
+}
+
UsbRequestAccessFunction::UsbRequestAccessFunction() {
}
@@ -764,6 +810,7 @@ ExtensionFunction::ResponseAction UsbGetConfigurationFunction::Run() {
if (config_descriptor) {
ConfigDescriptor config;
ConvertConfigDescriptor(*config_descriptor, &config);
+ config.active = true;
return RespondNow(OneArgument(config.ToValue()));
} else {
return RespondNow(Error(kErrorNotConfigured));
diff --git a/extensions/browser/api/usb/usb_api.h b/extensions/browser/api/usb/usb_api.h
index be56a51..abc5c89 100644
--- a/extensions/browser/api/usb/usb_api.h
+++ b/extensions/browser/api/usb/usb_api.h
@@ -126,6 +126,21 @@ class UsbGetUserSelectedDevicesFunction : public UIThreadExtensionFunction {
DISALLOW_COPY_AND_ASSIGN(UsbGetUserSelectedDevicesFunction);
};
+class UsbGetConfigurationsFunction : public UsbPermissionCheckingFunction {
+ public:
+ DECLARE_EXTENSION_FUNCTION("usb.getConfigurations", USB_GETCONFIGURATIONS);
+
+ UsbGetConfigurationsFunction();
+
+ private:
+ ~UsbGetConfigurationsFunction() override;
+
+ // ExtensionFunction:
+ ResponseAction Run() override;
+
+ DISALLOW_COPY_AND_ASSIGN(UsbGetConfigurationsFunction);
+};
+
class UsbRequestAccessFunction : public UIThreadExtensionFunction {
public:
DECLARE_EXTENSION_FUNCTION("usb.requestAccess", USB_REQUESTACCESS)
diff --git a/extensions/browser/api/usb/usb_apitest.cc b/extensions/browser/api/usb/usb_apitest.cc
index debe02b..7b654c7 100644
--- a/extensions/browser/api/usb/usb_apitest.cc
+++ b/extensions/browser/api/usb/usb_apitest.cc
@@ -98,8 +98,15 @@ class UsbApiTest : public ShellApiTest {
void SetUpOnMainThread() override {
ShellApiTest::SetUpOnMainThread();
- mock_device_ =
- new MockUsbDevice(0, 0, "Test Manufacturer", "Test Device", "ABC123");
+ std::vector<UsbConfigDescriptor> configs;
+ UsbConfigDescriptor config;
+ config.configuration_value = 1;
+ configs.push_back(config);
+ config.configuration_value = 2;
+ configs.push_back(config);
+
+ mock_device_ = new MockUsbDevice(0, 0, "Test Manufacturer", "Test Device",
+ "ABC123", configs);
mock_device_handle_ = new MockUsbDeviceHandle(mock_device_.get());
EXPECT_CALL(*mock_device_.get(), Open(_))
.WillRepeatedly(InvokeCallback<0>(mock_device_handle_));
@@ -116,6 +123,8 @@ class UsbApiTest : public ShellApiTest {
} // namespace
IN_PROC_BROWSER_TEST_F(UsbApiTest, DeviceHandling) {
+ EXPECT_CALL(*mock_device_.get(), GetActiveConfiguration())
+ .WillOnce(Return(&mock_device_->configurations()[0]));
EXPECT_CALL(*mock_device_handle_.get(), Close()).Times(2);
ASSERT_TRUE(RunAppTest("api_test/usb/device_handling"));
}
diff --git a/extensions/browser/extension_function_histogram_value.h b/extensions/browser/extension_function_histogram_value.h
index fcaba05..87b7504 100644
--- a/extensions/browser/extension_function_histogram_value.h
+++ b/extensions/browser/extension_function_histogram_value.h
@@ -1143,6 +1143,7 @@ enum HistogramValue {
BLUETOOTHPRIVATE_PAIR,
EASYUNLOCKPRIVATE_FINDSETUPCONNECTION,
RESOURCESPRIVATE_GETSTRINGS,
+ USB_GETCONFIGURATIONS,
// Last entry: Add new entries above, then run:
// python tools/metrics/histograms/update_extension_histograms.py
ENUM_BOUNDARY
diff --git a/extensions/common/api/usb.idl b/extensions/common/api/usb.idl
index f953e3f..77163e7 100644
--- a/extensions/common/api/usb.idl
+++ b/extensions/common/api/usb.idl
@@ -90,6 +90,8 @@ namespace usb {
};
[noinline_doc] dictionary ConfigDescriptor {
+ // Is this the active configuration?
+ boolean active;
// The configuration number.
long configurationValue;
// Description of the configuration.
@@ -221,6 +223,7 @@ namespace usb {
callback VoidCallback = void ();
callback GetDevicesCallback = void (Device[] devices);
+ callback GetConfigurationsCallback = void (ConfigDescriptor[] configs);
callback RequestAccessCallback = void (boolean success);
callback OpenDeviceCallback = void (ConnectionHandle handle);
callback FindDevicesCallback = void (ConnectionHandle[] handles);
@@ -246,6 +249,11 @@ namespace usb {
static void getUserSelectedDevices(DevicePromptOptions options,
GetDevicesCallback callback);
+ // Returns the full set of device configuration descriptors.
+ // |device|: The $(ref:Device) to fetch descriptors from.
+ static void getConfigurations(Device device,
+ GetConfigurationsCallback callback);
+
// Requests access from the permission broker to a device claimed by
// Chrome OS if the given interface on the device is not claimed.
//
diff --git a/extensions/test/data/api_test/usb/device_handling/test.js b/extensions/test/data/api_test/usb/device_handling/test.js
index a546564..5914f6a 100644
--- a/extensions/test/data/api_test/usb/device_handling/test.js
+++ b/extensions/test/data/api_test/usb/device_handling/test.js
@@ -22,6 +22,22 @@ function getDevices() {
});
}
+function getConfigurations() {
+ usb.getDevices({}, function(devices) {
+ chrome.test.assertNoLastError();
+ chrome.test.assertEq(1, devices.length);
+ chrome.usb.getConfigurations(devices[0], function(configs) {
+ chrome.test.assertNoLastError();
+ chrome.test.assertEq(2, configs.length);
+ chrome.test.assertTrue(configs[0].active);
+ chrome.test.assertEq(1, configs[0].configurationValue);
+ chrome.test.assertFalse(configs[1].active);
+ chrome.test.assertEq(2, configs[1].configurationValue);
+ chrome.test.succeed();
+ });
+ });
+}
+
function explicitCloseDevice() {
usb.findDevices({
vendorId: 0,
@@ -33,5 +49,5 @@ function explicitCloseDevice() {
}
chrome.test.runTests([
- getDevices, explicitCloseDevice
+ getDevices, getConfigurations, explicitCloseDevice
]);
diff --git a/tools/metrics/histograms/histograms.xml b/tools/metrics/histograms/histograms.xml
index 15e8c7d..43bb7c6 100644
--- a/tools/metrics/histograms/histograms.xml
+++ b/tools/metrics/histograms/histograms.xml
@@ -59326,6 +59326,7 @@ http://cs/file:chrome/histograms.xml - but prefer this file for new entries.
<int value="1082" label="BLUETOOTHPRIVATE_PAIR"/>
<int value="1083" label="EASYUNLOCKPRIVATE_FINDSETUPCONNECTION"/>
<int value="1084" label="RESOURCESPRIVATE_GETSTRINGS"/>
+ <int value="1085" label="USB_GETCONFIGURATIONS"/>
</enum>
<enum name="ExtensionInstallCause" type="int">