1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "chrome/browser/extensions/extension_apitest.h"
6 #include "content/public/browser/browser_thread.h"
7 #include "content/public/test/test_utils.h"
8 #include "device/usb/usb_service.h"
9 #include "extensions/browser/api/device_permissions_prompt.h"
10 #include "extensions/browser/api/usb/usb_api.h"
11 #include "extensions/shell/browser/shell_extensions_api_client.h"
12 #include "extensions/shell/test/shell_apitest.h"
13 #include "extensions/test/extension_test_message_listener.h"
14 #include "net/base/io_buffer.h"
15 #include "testing/gmock/include/gmock/gmock.h"
18 using testing::AnyNumber
;
19 using testing::Invoke
;
20 using testing::Return
;
21 using content::BrowserThread
;
22 using device::UsbConfigDescriptor
;
23 using device::UsbDevice
;
24 using device::UsbDeviceHandle
;
25 using device::UsbEndpointDirection
;
26 using device::UsbInterfaceDescriptor
;
27 using device::UsbService
;
28 using device::UsbTransferCallback
;
30 namespace extensions
{
34 ACTION_TEMPLATE(InvokeUsbTransferCallback
,
35 HAS_1_TEMPLATE_PARAMS(int, k
),
36 AND_1_VALUE_PARAMS(p1
)) {
37 net::IOBuffer
* io_buffer
= new net::IOBuffer(1);
38 memset(io_buffer
->data(), 0, 1); // Avoid uninitialized reads.
39 ::std::tr1::get
<k
>(args
).Run(p1
, io_buffer
, 1);
42 class TestDevicePermissionsPrompt
43 : public DevicePermissionsPrompt
,
44 public DevicePermissionsPrompt::Prompt::Observer
{
46 TestDevicePermissionsPrompt(content::WebContents
* web_contents
)
47 : DevicePermissionsPrompt(web_contents
) {}
49 void ShowDialog() override
{ prompt()->SetObserver(this); }
51 void OnDevicesChanged() override
{
52 std::vector
<scoped_refptr
<UsbDevice
>> devices
;
53 for (size_t i
= 0; i
< prompt()->GetDeviceCount(); ++i
) {
54 prompt()->GrantDevicePermission(i
);
55 devices
.push_back(prompt()->GetDevice(i
));
56 if (!prompt()->multiple()) {
60 delegate()->OnUsbDevicesChosen(devices
);
64 class TestExtensionsAPIClient
: public ShellExtensionsAPIClient
{
66 TestExtensionsAPIClient() : ShellExtensionsAPIClient() {}
68 scoped_ptr
<DevicePermissionsPrompt
> CreateDevicePermissionsPrompt(
69 content::WebContents
* web_contents
) const override
{
70 return make_scoped_ptr(new TestDevicePermissionsPrompt(web_contents
));
74 class MockUsbDeviceHandle
: public UsbDeviceHandle
{
76 MockUsbDeviceHandle() : UsbDeviceHandle() {}
78 MOCK_METHOD0(Close
, void());
80 MOCK_METHOD10(ControlTransfer
,
81 void(UsbEndpointDirection direction
,
82 TransferRequestType request_type
,
83 TransferRecipient recipient
,
87 net::IOBuffer
* buffer
,
90 const UsbTransferCallback
& callback
));
92 MOCK_METHOD6(BulkTransfer
,
93 void(UsbEndpointDirection direction
,
95 net::IOBuffer
* buffer
,
98 const UsbTransferCallback
& callback
));
100 MOCK_METHOD6(InterruptTransfer
,
101 void(UsbEndpointDirection direction
,
103 net::IOBuffer
* buffer
,
105 unsigned int timeout
,
106 const UsbTransferCallback
& callback
));
108 MOCK_METHOD8(IsochronousTransfer
,
109 void(UsbEndpointDirection direction
,
111 net::IOBuffer
* buffer
,
113 unsigned int packets
,
114 unsigned int packet_length
,
115 unsigned int timeout
,
116 const UsbTransferCallback
& callback
));
118 MOCK_METHOD0(ResetDevice
, bool());
119 MOCK_METHOD2(GetStringDescriptor
, bool(uint8_t, base::string16
*));
120 MOCK_METHOD1(SetConfiguration
, bool(int));
121 MOCK_METHOD1(ClaimInterface
, bool(int interface_number
));
122 MOCK_METHOD1(ReleaseInterface
, bool(int interface_number
));
123 MOCK_METHOD2(SetInterfaceAlternateSetting
,
124 bool(int interface_number
, int alternate_setting
));
126 virtual scoped_refptr
<UsbDevice
> GetDevice() const override
{
130 void set_device(UsbDevice
* device
) { device_
= device
; }
135 virtual ~MockUsbDeviceHandle() {}
138 class MockUsbDevice
: public UsbDevice
{
140 MockUsbDevice(uint16 vendor_id
, uint16 product_id
, uint32 unique_id
)
141 : UsbDevice(vendor_id
, product_id
, unique_id
) {}
143 MOCK_METHOD0(Open
, scoped_refptr
<UsbDeviceHandle
>());
144 MOCK_METHOD1(Close
, bool(scoped_refptr
<UsbDeviceHandle
>));
145 MOCK_METHOD0(GetConfiguration
, const device::UsbConfigDescriptor
*());
146 MOCK_METHOD1(GetManufacturer
, bool(base::string16
*));
147 MOCK_METHOD1(GetProduct
, bool(base::string16
*));
148 MOCK_METHOD1(GetSerialNumber
, bool(base::string16
*));
151 virtual ~MockUsbDevice() {}
154 class MockUsbService
: public UsbService
{
156 explicit MockUsbService(scoped_refptr
<UsbDevice
> device
) : device_(device
) {}
158 // Public wrapper around the protected base class method.
159 void NotifyDeviceAdded(scoped_refptr
<UsbDevice
> device
) {
160 UsbService::NotifyDeviceAdded(device
);
163 // Public wrapper around the protected base class method.
164 void NotifyDeviceRemoved(scoped_refptr
<UsbDevice
> device
) {
165 UsbService::NotifyDeviceRemoved(device
);
169 scoped_refptr
<UsbDevice
> GetDeviceById(uint32 unique_id
) override
{
170 EXPECT_EQ(unique_id
, 0U);
174 void GetDevices(std::vector
<scoped_refptr
<UsbDevice
>>* devices
) override
{
175 STLClearObject(devices
);
176 devices
->push_back(device_
);
179 scoped_refptr
<UsbDevice
> device_
;
182 class UsbApiTest
: public ShellApiTest
{
184 void SetUpOnMainThread() override
{
185 ShellApiTest::SetUpOnMainThread();
187 mock_device_
= new MockUsbDevice(0, 0, 0);
188 EXPECT_CALL(*mock_device_
.get(), GetManufacturer(_
))
189 .WillRepeatedly(Return(false));
190 EXPECT_CALL(*mock_device_
.get(), GetProduct(_
))
191 .WillRepeatedly(Return(false));
192 EXPECT_CALL(*mock_device_
.get(), GetSerialNumber(_
))
193 .WillRepeatedly(Return(false));
195 mock_device_handle_
= new MockUsbDeviceHandle();
196 mock_device_handle_
->set_device(mock_device_
.get());
197 EXPECT_CALL(*mock_device_
.get(), Open())
198 .WillRepeatedly(Return(mock_device_handle_
));
200 base::RunLoop run_loop
;
201 BrowserThread::PostTaskAndReply(BrowserThread::FILE, FROM_HERE
,
202 base::Bind(&UsbApiTest::SetUpService
, this),
203 run_loop
.QuitClosure());
207 void SetUpService() {
208 mock_service_
= new MockUsbService(mock_device_
);
209 UsbService::SetInstanceForTest(mock_service_
);
212 void AddTestDevices() {
213 scoped_refptr
<MockUsbDevice
> device(new MockUsbDevice(0x18D1, 0x58F0, 1));
214 EXPECT_CALL(*device
.get(), GetSerialNumber(_
))
215 .WillRepeatedly(Return(false));
216 mock_service_
->NotifyDeviceAdded(device
);
218 device
= new MockUsbDevice(0x18D1, 0x58F1, 2);
219 EXPECT_CALL(*device
.get(), GetSerialNumber(_
))
220 .WillRepeatedly(Return(false));
221 mock_service_
->NotifyDeviceAdded(device
);
225 scoped_refptr
<MockUsbDeviceHandle
> mock_device_handle_
;
226 scoped_refptr
<MockUsbDevice
> mock_device_
;
227 MockUsbService
* mock_service_
;
232 IN_PROC_BROWSER_TEST_F(UsbApiTest
, DeviceHandling
) {
233 EXPECT_CALL(*mock_device_handle_
.get(), Close()).Times(2);
234 ASSERT_TRUE(RunAppTest("api_test/usb/device_handling"));
237 IN_PROC_BROWSER_TEST_F(UsbApiTest
, ResetDevice
) {
238 EXPECT_CALL(*mock_device_handle_
.get(), Close()).Times(2);
239 EXPECT_CALL(*mock_device_handle_
.get(), ResetDevice())
240 .WillOnce(Return(true))
241 .WillOnce(Return(false));
242 EXPECT_CALL(*mock_device_handle_
.get(),
243 InterruptTransfer(device::USB_DIRECTION_OUTBOUND
, 2, _
, 1, _
, _
))
244 .WillOnce(InvokeUsbTransferCallback
<5>(device::USB_TRANSFER_COMPLETED
));
245 ASSERT_TRUE(RunAppTest("api_test/usb/reset_device"));
248 IN_PROC_BROWSER_TEST_F(UsbApiTest
, SetConfiguration
) {
249 UsbConfigDescriptor config_descriptor
;
250 EXPECT_CALL(*mock_device_handle_
.get(), SetConfiguration(1))
251 .WillOnce(Return(true));
252 EXPECT_CALL(*mock_device_handle_
.get(), Close()).Times(1);
253 EXPECT_CALL(*mock_device_
.get(), GetConfiguration())
254 .WillOnce(Return(nullptr))
255 .WillOnce(Return(&config_descriptor
));
256 ASSERT_TRUE(RunAppTest("api_test/usb/set_configuration"));
259 IN_PROC_BROWSER_TEST_F(UsbApiTest
, ListInterfaces
) {
260 UsbConfigDescriptor config_descriptor
;
261 EXPECT_CALL(*mock_device_handle_
.get(), Close()).Times(1);
262 EXPECT_CALL(*mock_device_
.get(), GetConfiguration())
263 .WillOnce(Return(&config_descriptor
));
264 ASSERT_TRUE(RunAppTest("api_test/usb/list_interfaces"));
267 IN_PROC_BROWSER_TEST_F(UsbApiTest
, TransferEvent
) {
268 EXPECT_CALL(*mock_device_handle_
.get(),
269 ControlTransfer(device::USB_DIRECTION_OUTBOUND
,
270 UsbDeviceHandle::STANDARD
,
271 UsbDeviceHandle::DEVICE
,
279 .WillOnce(InvokeUsbTransferCallback
<9>(device::USB_TRANSFER_COMPLETED
));
280 EXPECT_CALL(*mock_device_handle_
.get(),
281 BulkTransfer(device::USB_DIRECTION_OUTBOUND
, 1, _
, 1, _
, _
))
282 .WillOnce(InvokeUsbTransferCallback
<5>(device::USB_TRANSFER_COMPLETED
));
283 EXPECT_CALL(*mock_device_handle_
.get(),
284 InterruptTransfer(device::USB_DIRECTION_OUTBOUND
, 2, _
, 1, _
, _
))
285 .WillOnce(InvokeUsbTransferCallback
<5>(device::USB_TRANSFER_COMPLETED
));
287 *mock_device_handle_
.get(),
288 IsochronousTransfer(device::USB_DIRECTION_OUTBOUND
, 3, _
, 1, 1, 1, _
, _
))
289 .WillOnce(InvokeUsbTransferCallback
<7>(device::USB_TRANSFER_COMPLETED
));
290 EXPECT_CALL(*mock_device_handle_
.get(), Close()).Times(AnyNumber());
291 ASSERT_TRUE(RunAppTest("api_test/usb/transfer_event"));
294 IN_PROC_BROWSER_TEST_F(UsbApiTest
, ZeroLengthTransfer
) {
295 EXPECT_CALL(*mock_device_handle_
.get(), BulkTransfer(_
, _
, _
, 0, _
, _
))
296 .WillOnce(InvokeUsbTransferCallback
<5>(device::USB_TRANSFER_COMPLETED
));
297 EXPECT_CALL(*mock_device_handle_
.get(), Close()).Times(AnyNumber());
298 ASSERT_TRUE(RunAppTest("api_test/usb/zero_length_transfer"));
301 IN_PROC_BROWSER_TEST_F(UsbApiTest
, TransferFailure
) {
302 EXPECT_CALL(*mock_device_handle_
.get(), BulkTransfer(_
, _
, _
, _
, _
, _
))
303 .WillOnce(InvokeUsbTransferCallback
<5>(device::USB_TRANSFER_COMPLETED
))
304 .WillOnce(InvokeUsbTransferCallback
<5>(device::USB_TRANSFER_ERROR
))
305 .WillOnce(InvokeUsbTransferCallback
<5>(device::USB_TRANSFER_TIMEOUT
));
306 EXPECT_CALL(*mock_device_handle_
.get(), Close()).Times(AnyNumber());
307 ASSERT_TRUE(RunAppTest("api_test/usb/transfer_failure"));
310 IN_PROC_BROWSER_TEST_F(UsbApiTest
, InvalidLengthTransfer
) {
311 EXPECT_CALL(*mock_device_handle_
.get(), Close()).Times(AnyNumber());
312 ASSERT_TRUE(RunAppTest("api_test/usb/invalid_length_transfer"));
315 IN_PROC_BROWSER_TEST_F(UsbApiTest
, InvalidTimeout
) {
316 EXPECT_CALL(*mock_device_handle_
.get(), Close()).Times(AnyNumber());
317 ASSERT_TRUE(RunAppTest("api_test/usb/invalid_timeout"));
320 IN_PROC_BROWSER_TEST_F(UsbApiTest
, OnDeviceAdded
) {
321 ExtensionTestMessageListener
load_listener("loaded", false);
322 ExtensionTestMessageListener
result_listener("success", false);
323 result_listener
.set_failure_message("failure");
325 ASSERT_TRUE(LoadApp("api_test/usb/add_event"));
326 ASSERT_TRUE(load_listener
.WaitUntilSatisfied());
328 base::RunLoop run_loop
;
329 BrowserThread::PostTaskAndReply(
330 BrowserThread::FILE, FROM_HERE
,
331 base::Bind(&UsbApiTest::AddTestDevices
, base::Unretained(this)),
332 run_loop
.QuitClosure());
335 ASSERT_TRUE(result_listener
.WaitUntilSatisfied());
338 IN_PROC_BROWSER_TEST_F(UsbApiTest
, OnDeviceRemoved
) {
339 ExtensionTestMessageListener
load_listener("loaded", false);
340 ExtensionTestMessageListener
result_listener("success", false);
341 result_listener
.set_failure_message("failure");
343 ASSERT_TRUE(LoadApp("api_test/usb/remove_event"));
344 ASSERT_TRUE(load_listener
.WaitUntilSatisfied());
346 base::RunLoop run_loop
;
347 BrowserThread::PostTaskAndReply(
348 BrowserThread::FILE, FROM_HERE
,
349 base::Bind(&MockUsbService::NotifyDeviceRemoved
,
350 base::Unretained(mock_service_
), mock_device_
),
351 run_loop
.QuitClosure());
354 ASSERT_TRUE(result_listener
.WaitUntilSatisfied());
357 IN_PROC_BROWSER_TEST_F(UsbApiTest
, GetUserSelectedDevices
) {
358 ExtensionTestMessageListener
ready_listener("opened_device", false);
359 ExtensionTestMessageListener
result_listener("success", false);
360 result_listener
.set_failure_message("failure");
362 EXPECT_CALL(*mock_device_handle_
.get(), Close()).Times(1);
364 TestExtensionsAPIClient test_api_client
;
365 ASSERT_TRUE(LoadApp("api_test/usb/get_user_selected_devices"));
366 ASSERT_TRUE(ready_listener
.WaitUntilSatisfied());
368 base::RunLoop run_loop
;
369 BrowserThread::PostTaskAndReply(
370 BrowserThread::FILE, FROM_HERE
,
371 base::Bind(&MockUsbService::NotifyDeviceRemoved
,
372 base::Unretained(mock_service_
), mock_device_
),
373 run_loop
.QuitClosure());
376 ASSERT_TRUE(result_listener
.WaitUntilSatisfied());
379 } // namespace extensions