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 "chrome/browser/ui/browser.h"
7 #include "content/public/browser/browser_thread.h"
8 #include "content/public/test/test_utils.h"
9 #include "device/usb/usb_service.h"
10 #include "extensions/browser/api/usb/usb_api.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;
29 ACTION_TEMPLATE(InvokeUsbTransferCallback,
30 HAS_1_TEMPLATE_PARAMS(int, k),
31 AND_1_VALUE_PARAMS(p1)) {
32 net::IOBuffer* io_buffer = new net::IOBuffer(1);
33 memset(io_buffer->data(), 0, 1); // Avoid uninitialized reads.
34 ::std::tr1::get<k>(args).Run(p1, io_buffer, 1);
37 // MSVC erroneously thinks that at least one of the arguments for the transfer
38 // methods differ by const or volatility and emits a warning about the old
39 // standards-noncompliant behaviour of their compiler.
42 #pragma warning(disable : 4373)
45 class MockUsbDeviceHandle : public UsbDeviceHandle {
47 MockUsbDeviceHandle() : UsbDeviceHandle() {}
49 MOCK_METHOD0(Close, void());
51 MOCK_METHOD10(ControlTransfer,
52 void(const UsbEndpointDirection direction,
53 const TransferRequestType request_type,
54 const TransferRecipient recipient,
58 net::IOBuffer* buffer,
60 const unsigned int timeout,
61 const UsbTransferCallback& callback));
63 MOCK_METHOD6(BulkTransfer,
64 void(const UsbEndpointDirection direction,
66 net::IOBuffer* buffer,
68 const unsigned int timeout,
69 const UsbTransferCallback& callback));
71 MOCK_METHOD6(InterruptTransfer,
72 void(const UsbEndpointDirection direction,
74 net::IOBuffer* buffer,
76 const unsigned int timeout,
77 const UsbTransferCallback& callback));
79 MOCK_METHOD8(IsochronousTransfer,
80 void(const UsbEndpointDirection direction,
82 net::IOBuffer* buffer,
84 const unsigned int packets,
85 const unsigned int packet_length,
86 const unsigned int timeout,
87 const UsbTransferCallback& callback));
89 MOCK_METHOD0(ResetDevice, bool());
90 MOCK_METHOD2(GetStringDescriptor, bool(uint8_t, base::string16*));
91 MOCK_METHOD1(ClaimInterface, bool(const int interface_number));
92 MOCK_METHOD1(ReleaseInterface, bool(const int interface_number));
93 MOCK_METHOD2(SetInterfaceAlternateSetting,
94 bool(const int interface_number, const int alternate_setting));
96 virtual scoped_refptr<UsbDevice> GetDevice() const OVERRIDE {
100 void set_device(UsbDevice* device) { device_ = device; }
105 virtual ~MockUsbDeviceHandle() {}
108 class MockUsbDevice : public UsbDevice {
110 explicit MockUsbDevice(MockUsbDeviceHandle* mock_handle)
111 : UsbDevice(0, 0, 0), mock_handle_(mock_handle) {
112 mock_handle->set_device(this);
115 virtual scoped_refptr<UsbDeviceHandle> Open() OVERRIDE {
119 virtual bool Close(scoped_refptr<UsbDeviceHandle> handle) OVERRIDE {
120 EXPECT_TRUE(false) << "Should not be reached";
124 #if defined(OS_CHROMEOS)
125 virtual void RequestUsbAccess(
127 const base::Callback<void(bool success)>& callback) OVERRIDE {
128 BrowserThread::PostTask(
129 BrowserThread::FILE, FROM_HERE, base::Bind(callback, true));
131 #endif // OS_CHROMEOS
133 MOCK_METHOD0(GetConfiguration, const UsbConfigDescriptor&());
134 MOCK_METHOD1(GetManufacturer, bool(base::string16* manufacturer));
135 MOCK_METHOD1(GetProduct, bool(base::string16* product));
136 MOCK_METHOD1(GetSerialNumber, bool(base::string16* serial_number));
139 MockUsbDeviceHandle* mock_handle_;
140 virtual ~MockUsbDevice() {}
143 class MockUsbService : public UsbService {
145 explicit MockUsbService(scoped_refptr<UsbDevice> device) : device_(device) {}
148 virtual scoped_refptr<UsbDevice> GetDeviceById(uint32 unique_id) OVERRIDE {
149 EXPECT_EQ(unique_id, 0U);
153 virtual void GetDevices(
154 std::vector<scoped_refptr<UsbDevice> >* devices) OVERRIDE {
155 STLClearObject(devices);
156 devices->push_back(device_);
159 scoped_refptr<UsbDevice> device_;
166 class UsbApiTest : public ExtensionApiTest {
168 virtual void SetUpOnMainThread() OVERRIDE {
169 mock_device_handle_ = new MockUsbDeviceHandle();
170 mock_device_ = new MockUsbDevice(mock_device_handle_.get());
171 scoped_refptr<content::MessageLoopRunner> runner =
172 new content::MessageLoopRunner;
173 BrowserThread::PostTaskAndReply(BrowserThread::FILE,
175 base::Bind(&UsbApiTest::SetUpService, this),
176 runner->QuitClosure());
180 void SetUpService() {
181 UsbService::SetInstanceForTest(new MockUsbService(mock_device_));
184 virtual void TearDownOnMainThread() OVERRIDE {
185 scoped_refptr<content::MessageLoopRunner> runner =
186 new content::MessageLoopRunner;
187 UsbService* service = NULL;
188 BrowserThread::PostTaskAndReply(
191 base::Bind(&UsbService::SetInstanceForTest, service),
192 runner->QuitClosure());
197 scoped_refptr<MockUsbDeviceHandle> mock_device_handle_;
198 scoped_refptr<MockUsbDevice> mock_device_;
203 IN_PROC_BROWSER_TEST_F(UsbApiTest, DeviceHandling) {
204 EXPECT_CALL(*mock_device_handle_.get(), Close()).Times(4);
205 ASSERT_TRUE(RunExtensionTest("usb/device_handling"));
208 IN_PROC_BROWSER_TEST_F(UsbApiTest, ResetDevice) {
209 EXPECT_CALL(*mock_device_handle_.get(), Close()).Times(2);
210 EXPECT_CALL(*mock_device_handle_.get(), ResetDevice())
211 .WillOnce(Return(true))
212 .WillOnce(Return(false));
213 EXPECT_CALL(*mock_device_handle_.get(),
214 InterruptTransfer(device::USB_DIRECTION_OUTBOUND, 2, _, 1, _, _))
215 .WillOnce(InvokeUsbTransferCallback<5>(device::USB_TRANSFER_COMPLETED));
216 ASSERT_TRUE(RunExtensionTest("usb/reset_device"));
219 IN_PROC_BROWSER_TEST_F(UsbApiTest, ListInterfaces) {
220 UsbConfigDescriptor config_descriptor;
221 EXPECT_CALL(*mock_device_handle_.get(), Close()).Times(AnyNumber());
222 EXPECT_CALL(*mock_device_.get(), GetConfiguration())
223 .WillOnce(ReturnRef(config_descriptor));
224 ASSERT_TRUE(RunExtensionTest("usb/list_interfaces"));
227 IN_PROC_BROWSER_TEST_F(UsbApiTest, TransferEvent) {
228 EXPECT_CALL(*mock_device_handle_.get(),
229 ControlTransfer(device::USB_DIRECTION_OUTBOUND,
230 UsbDeviceHandle::STANDARD,
231 UsbDeviceHandle::DEVICE,
239 .WillOnce(InvokeUsbTransferCallback<9>(device::USB_TRANSFER_COMPLETED));
240 EXPECT_CALL(*mock_device_handle_.get(),
241 BulkTransfer(device::USB_DIRECTION_OUTBOUND, 1, _, 1, _, _))
242 .WillOnce(InvokeUsbTransferCallback<5>(device::USB_TRANSFER_COMPLETED));
243 EXPECT_CALL(*mock_device_handle_.get(),
244 InterruptTransfer(device::USB_DIRECTION_OUTBOUND, 2, _, 1, _, _))
245 .WillOnce(InvokeUsbTransferCallback<5>(device::USB_TRANSFER_COMPLETED));
247 *mock_device_handle_.get(),
248 IsochronousTransfer(device::USB_DIRECTION_OUTBOUND, 3, _, 1, 1, 1, _, _))
249 .WillOnce(InvokeUsbTransferCallback<7>(device::USB_TRANSFER_COMPLETED));
250 EXPECT_CALL(*mock_device_handle_.get(), Close()).Times(AnyNumber());
251 ASSERT_TRUE(RunExtensionTest("usb/transfer_event"));
254 IN_PROC_BROWSER_TEST_F(UsbApiTest, ZeroLengthTransfer) {
255 EXPECT_CALL(*mock_device_handle_.get(), BulkTransfer(_, _, _, 0, _, _))
256 .WillOnce(InvokeUsbTransferCallback<5>(device::USB_TRANSFER_COMPLETED));
257 EXPECT_CALL(*mock_device_handle_.get(), Close()).Times(AnyNumber());
258 ASSERT_TRUE(RunExtensionTest("usb/zero_length_transfer"));
261 IN_PROC_BROWSER_TEST_F(UsbApiTest, TransferFailure) {
262 EXPECT_CALL(*mock_device_handle_.get(), BulkTransfer(_, _, _, _, _, _))
263 .WillOnce(InvokeUsbTransferCallback<5>(device::USB_TRANSFER_COMPLETED))
264 .WillOnce(InvokeUsbTransferCallback<5>(device::USB_TRANSFER_ERROR))
265 .WillOnce(InvokeUsbTransferCallback<5>(device::USB_TRANSFER_TIMEOUT));
266 EXPECT_CALL(*mock_device_handle_.get(), Close()).Times(AnyNumber());
267 ASSERT_TRUE(RunExtensionTest("usb/transfer_failure"));
270 IN_PROC_BROWSER_TEST_F(UsbApiTest, InvalidLengthTransfer) {
271 EXPECT_CALL(*mock_device_handle_.get(), Close()).Times(AnyNumber());
272 ASSERT_TRUE(RunExtensionTest("usb/invalid_length_transfer"));