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/usb/usb_api.h"
10 #include "extensions/shell/test/shell_apitest.h"
11 #include "net/base/io_buffer.h"
12 #include "testing/gmock/include/gmock/gmock.h"
14 using testing::AnyNumber;
16 using testing::Return;
17 using testing::ReturnRef;
18 using content::BrowserThread;
19 using device::UsbConfigDescriptor;
20 using device::UsbDevice;
21 using device::UsbDeviceHandle;
22 using device::UsbEndpointDirection;
23 using device::UsbInterfaceDescriptor;
24 using device::UsbService;
25 using device::UsbTransferCallback;
27 namespace extensions {
31 ACTION_TEMPLATE(InvokeUsbTransferCallback,
32 HAS_1_TEMPLATE_PARAMS(int, k),
33 AND_1_VALUE_PARAMS(p1)) {
34 net::IOBuffer* io_buffer = new net::IOBuffer(1);
35 memset(io_buffer->data(), 0, 1); // Avoid uninitialized reads.
36 ::std::tr1::get<k>(args).Run(p1, io_buffer, 1);
39 class MockUsbDeviceHandle : public UsbDeviceHandle {
41 MockUsbDeviceHandle() : UsbDeviceHandle() {}
43 MOCK_METHOD0(Close, void());
45 MOCK_METHOD10(ControlTransfer,
46 void(UsbEndpointDirection direction,
47 TransferRequestType request_type,
48 TransferRecipient recipient,
52 net::IOBuffer* buffer,
55 const UsbTransferCallback& callback));
57 MOCK_METHOD6(BulkTransfer,
58 void(UsbEndpointDirection direction,
60 net::IOBuffer* buffer,
63 const UsbTransferCallback& callback));
65 MOCK_METHOD6(InterruptTransfer,
66 void(UsbEndpointDirection direction,
68 net::IOBuffer* buffer,
71 const UsbTransferCallback& callback));
73 MOCK_METHOD8(IsochronousTransfer,
74 void(UsbEndpointDirection direction,
76 net::IOBuffer* buffer,
79 unsigned int packet_length,
81 const UsbTransferCallback& callback));
83 MOCK_METHOD0(ResetDevice, bool());
84 MOCK_METHOD2(GetStringDescriptor, bool(uint8_t, base::string16*));
85 MOCK_METHOD1(ClaimInterface, bool(int interface_number));
86 MOCK_METHOD1(ReleaseInterface, bool(int interface_number));
87 MOCK_METHOD2(SetInterfaceAlternateSetting,
88 bool(int interface_number, int alternate_setting));
90 virtual scoped_refptr<UsbDevice> GetDevice() const override {
94 void set_device(UsbDevice* device) { device_ = device; }
99 virtual ~MockUsbDeviceHandle() {}
102 class MockUsbDevice : public UsbDevice {
104 explicit MockUsbDevice(MockUsbDeviceHandle* mock_handle)
105 : UsbDevice(0, 0, 0), mock_handle_(mock_handle) {
106 mock_handle->set_device(this);
109 virtual scoped_refptr<UsbDeviceHandle> Open() override {
113 virtual bool Close(scoped_refptr<UsbDeviceHandle> handle) override {
114 EXPECT_TRUE(false) << "Should not be reached";
118 #if defined(OS_CHROMEOS)
119 virtual void RequestUsbAccess(
121 const base::Callback<void(bool success)>& callback) override {
122 BrowserThread::PostTask(
123 BrowserThread::FILE, FROM_HERE, base::Bind(callback, true));
125 #endif // OS_CHROMEOS
127 MOCK_METHOD0(GetConfiguration, const UsbConfigDescriptor&());
128 MOCK_METHOD1(GetManufacturer, bool(base::string16* manufacturer));
129 MOCK_METHOD1(GetProduct, bool(base::string16* product));
130 MOCK_METHOD1(GetSerialNumber, bool(base::string16* serial_number));
133 MockUsbDeviceHandle* mock_handle_;
134 virtual ~MockUsbDevice() {}
137 class MockUsbService : public UsbService {
139 explicit MockUsbService(scoped_refptr<UsbDevice> device) : device_(device) {}
142 scoped_refptr<UsbDevice> GetDeviceById(uint32 unique_id) override {
143 EXPECT_EQ(unique_id, 0U);
147 void GetDevices(std::vector<scoped_refptr<UsbDevice>>* devices) override {
148 STLClearObject(devices);
149 devices->push_back(device_);
152 scoped_refptr<UsbDevice> device_;
155 class UsbApiTest : public ShellApiTest {
157 void SetUpOnMainThread() override {
158 ShellApiTest::SetUpOnMainThread();
159 mock_device_handle_ = new MockUsbDeviceHandle();
160 mock_device_ = new MockUsbDevice(mock_device_handle_.get());
161 scoped_refptr<content::MessageLoopRunner> runner =
162 new content::MessageLoopRunner;
163 BrowserThread::PostTaskAndReply(BrowserThread::FILE,
165 base::Bind(&UsbApiTest::SetUpService, this),
166 runner->QuitClosure());
170 void SetUpService() {
171 UsbService::SetInstanceForTest(new MockUsbService(mock_device_));
174 void TearDownOnMainThread() override {
175 scoped_refptr<content::MessageLoopRunner> runner =
176 new content::MessageLoopRunner;
177 UsbService* service = NULL;
178 BrowserThread::PostTaskAndReply(
181 base::Bind(&UsbService::SetInstanceForTest, service),
182 runner->QuitClosure());
187 scoped_refptr<MockUsbDeviceHandle> mock_device_handle_;
188 scoped_refptr<MockUsbDevice> mock_device_;
193 IN_PROC_BROWSER_TEST_F(UsbApiTest, DeviceHandling) {
194 EXPECT_CALL(*mock_device_handle_.get(), Close()).Times(4);
195 ASSERT_TRUE(RunAppTest("api_test/usb/device_handling"));
198 IN_PROC_BROWSER_TEST_F(UsbApiTest, ResetDevice) {
199 EXPECT_CALL(*mock_device_handle_.get(), Close()).Times(2);
200 EXPECT_CALL(*mock_device_handle_.get(), ResetDevice())
201 .WillOnce(Return(true))
202 .WillOnce(Return(false));
203 EXPECT_CALL(*mock_device_handle_.get(),
204 InterruptTransfer(device::USB_DIRECTION_OUTBOUND, 2, _, 1, _, _))
205 .WillOnce(InvokeUsbTransferCallback<5>(device::USB_TRANSFER_COMPLETED));
206 ASSERT_TRUE(RunAppTest("api_test/usb/reset_device"));
209 IN_PROC_BROWSER_TEST_F(UsbApiTest, ListInterfaces) {
210 UsbConfigDescriptor config_descriptor;
211 EXPECT_CALL(*mock_device_handle_.get(), Close()).Times(AnyNumber());
212 EXPECT_CALL(*mock_device_.get(), GetConfiguration())
213 .WillOnce(ReturnRef(config_descriptor));
214 ASSERT_TRUE(RunAppTest("api_test/usb/list_interfaces"));
217 IN_PROC_BROWSER_TEST_F(UsbApiTest, TransferEvent) {
218 EXPECT_CALL(*mock_device_handle_.get(),
219 ControlTransfer(device::USB_DIRECTION_OUTBOUND,
220 UsbDeviceHandle::STANDARD,
221 UsbDeviceHandle::DEVICE,
229 .WillOnce(InvokeUsbTransferCallback<9>(device::USB_TRANSFER_COMPLETED));
230 EXPECT_CALL(*mock_device_handle_.get(),
231 BulkTransfer(device::USB_DIRECTION_OUTBOUND, 1, _, 1, _, _))
232 .WillOnce(InvokeUsbTransferCallback<5>(device::USB_TRANSFER_COMPLETED));
233 EXPECT_CALL(*mock_device_handle_.get(),
234 InterruptTransfer(device::USB_DIRECTION_OUTBOUND, 2, _, 1, _, _))
235 .WillOnce(InvokeUsbTransferCallback<5>(device::USB_TRANSFER_COMPLETED));
237 *mock_device_handle_.get(),
238 IsochronousTransfer(device::USB_DIRECTION_OUTBOUND, 3, _, 1, 1, 1, _, _))
239 .WillOnce(InvokeUsbTransferCallback<7>(device::USB_TRANSFER_COMPLETED));
240 EXPECT_CALL(*mock_device_handle_.get(), Close()).Times(AnyNumber());
241 ASSERT_TRUE(RunAppTest("api_test/usb/transfer_event"));
244 IN_PROC_BROWSER_TEST_F(UsbApiTest, ZeroLengthTransfer) {
245 EXPECT_CALL(*mock_device_handle_.get(), BulkTransfer(_, _, _, 0, _, _))
246 .WillOnce(InvokeUsbTransferCallback<5>(device::USB_TRANSFER_COMPLETED));
247 EXPECT_CALL(*mock_device_handle_.get(), Close()).Times(AnyNumber());
248 ASSERT_TRUE(RunAppTest("api_test/usb/zero_length_transfer"));
251 IN_PROC_BROWSER_TEST_F(UsbApiTest, TransferFailure) {
252 EXPECT_CALL(*mock_device_handle_.get(), BulkTransfer(_, _, _, _, _, _))
253 .WillOnce(InvokeUsbTransferCallback<5>(device::USB_TRANSFER_COMPLETED))
254 .WillOnce(InvokeUsbTransferCallback<5>(device::USB_TRANSFER_ERROR))
255 .WillOnce(InvokeUsbTransferCallback<5>(device::USB_TRANSFER_TIMEOUT));
256 EXPECT_CALL(*mock_device_handle_.get(), Close()).Times(AnyNumber());
257 ASSERT_TRUE(RunAppTest("api_test/usb/transfer_failure"));
260 IN_PROC_BROWSER_TEST_F(UsbApiTest, InvalidLengthTransfer) {
261 EXPECT_CALL(*mock_device_handle_.get(), Close()).Times(AnyNumber());
262 ASSERT_TRUE(RunAppTest("api_test/usb/invalid_length_transfer"));
265 } // namespace extensions