Index: chrome/browser/devtools/device/usb/android_usb_browser_test.cc |
diff --git a/chrome/browser/devtools/device/usb/android_usb_browser_test.cc b/chrome/browser/devtools/device/usb/android_usb_browser_test.cc |
new file mode 100644 |
index 0000000000000000000000000000000000000000..37356d00063e0ec5122ec40b52bd526c2333f377 |
--- /dev/null |
+++ b/chrome/browser/devtools/device/usb/android_usb_browser_test.cc |
@@ -0,0 +1,268 @@ |
+// Copyright (c) 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 <algorithm> |
+ |
+#include "chrome/browser/devtools/device/devtools_android_bridge.h" |
+#include "chrome/browser/ui/browser.h" |
+#include "chrome/test/base/in_process_browser_test.h" |
+#include "components/usb_service/usb_device.h" |
+#include "components/usb_service/usb_device_handle.h" |
+#include "components/usb_service/usb_interface.h" |
+#include "components/usb_service/usb_service.h" |
+#include "content/public/browser/browser_thread.h" |
+#include "content/public/test/test_utils.h" |
+#include "testing/gtest/include/gtest/gtest.h" |
+ |
+using content::BrowserThread; |
+using usb_service::UsbConfigDescriptor; |
+using usb_service::UsbDevice; |
+using usb_service::UsbDeviceHandle; |
+using usb_service::UsbEndpointDescriptor; |
+using usb_service::UsbInterfaceAltSettingDescriptor; |
+using usb_service::UsbInterfaceDescriptor; |
+using usb_service::UsbService; |
+ |
+namespace { |
+ |
+struct AndroidTraits { |
+ static const int kClass = 0xff; |
+ static const int kSubclass = 0x42; |
+ static const int kProtocol = 0x1; |
+}; |
+ |
+struct NonAndroidTraits { |
+ static const int kClass = 0xf0; |
+ static const int kSubclass = 0x42; |
+ static const int kProtocol = 0x2; |
+}; |
+ |
+template <class T> |
+class MockUsbInterfaceAltSettingDescriptor |
+ : public UsbInterfaceAltSettingDescriptor { |
+ public: |
+ MockUsbInterfaceAltSettingDescriptor(int interface_number, |
+ int alternate_setting) |
+ : interface_number_(interface_number), |
+ alternate_setting_(alternate_setting) {} |
+ |
+ virtual size_t GetNumEndpoints() const OVERRIDE { |
+ // See IsAndroidInterface function in android_usb_device.cc |
+ return 2; |
+ } |
+ |
+ virtual scoped_refptr<const UsbEndpointDescriptor> GetEndpoint( |
+ size_t index) const OVERRIDE { |
+ EXPECT_GT(static_cast<size_t>(2), index); |
+ return NULL; |
+ } |
+ |
+ virtual int GetInterfaceNumber() const OVERRIDE { return interface_number_; } |
+ |
+ virtual int GetAlternateSetting() const OVERRIDE { |
+ return alternate_setting_; |
+ } |
+ |
+ virtual int GetInterfaceClass() const OVERRIDE { return T::kClass; } |
+ |
+ virtual int GetInterfaceSubclass() const OVERRIDE { return T::kSubclass; } |
+ |
+ virtual int GetInterfaceProtocol() const OVERRIDE { return T::kProtocol; } |
+ |
+ protected: |
+ virtual ~MockUsbInterfaceAltSettingDescriptor() {}; |
+ |
+ private: |
+ const int interface_number_; |
+ const int alternate_setting_; |
+}; |
+ |
+template <class T> |
+class MockUsbInterfaceDescriptor : public UsbInterfaceDescriptor { |
+ public: |
+ explicit MockUsbInterfaceDescriptor(int interface_number) |
+ : interface_number_(interface_number) {} |
+ |
+ virtual size_t GetNumAltSettings() const OVERRIDE { |
+ // See IsAndroidInterface function in android_usb_device.cc |
+ return 1; |
+ } |
+ virtual scoped_refptr<const UsbInterfaceAltSettingDescriptor> GetAltSetting( |
+ size_t index) const OVERRIDE { |
+ EXPECT_EQ(static_cast<size_t>(0), index); |
+ return new MockUsbInterfaceAltSettingDescriptor<T>(interface_number_, 0); |
+ } |
+ |
+ protected: |
+ const int interface_number_; |
+ virtual ~MockUsbInterfaceDescriptor() {} |
+}; |
+ |
+template <class T> |
+class MockUsbConfigDescriptor : public UsbConfigDescriptor { |
+ public: |
+ MockUsbConfigDescriptor() {} |
+ |
+ virtual size_t GetNumInterfaces() const OVERRIDE { return 1; } |
+ |
+ virtual scoped_refptr<const UsbInterfaceDescriptor> GetInterface( |
+ size_t index) const OVERRIDE { |
+ EXPECT_EQ(static_cast<size_t>(0), index); |
+ return new MockUsbInterfaceDescriptor<T>(index); |
+ } |
+ |
+ protected: |
+ virtual ~MockUsbConfigDescriptor() {}; |
+}; |
+ |
+template <class T> |
+class MockUsbDevice : public UsbDevice { |
+ public: |
+ MockUsbDevice() : UsbDevice(0, 0, 0) {} |
+ |
+ virtual ~MockUsbDevice() {} |
+ |
+ virtual scoped_refptr<UsbDeviceHandle> Open() OVERRIDE { return NULL; } |
+ |
+ virtual scoped_refptr<UsbConfigDescriptor> ListInterfaces() OVERRIDE { |
+ return new MockUsbConfigDescriptor<T>(); |
+ } |
+ |
+ virtual bool Close(scoped_refptr<UsbDeviceHandle> handle) { return true; } |
+ |
+#if defined(OS_CHROMEOS) |
+ // On ChromeOS, if an interface of a claimed device is not claimed, the |
+ // permission broker can change the owner of the device so that the unclaimed |
+ // interfaces can be used. If this argument is missing, permission broker will |
+ // not be used and this method fails if the device is claimed. |
+ virtual void RequestUsbAcess( |
+ int interface_id, |
+ const base::Callback<void(bool success)>& callback) OVERRIDE { |
+ callback.Run(true); |
+ } |
+#endif // OS_CHROMEOS |
+}; |
+ |
+class MockUsbService : public UsbService { |
+ public: |
+ virtual ~MockUsbService() {} |
+ |
+ virtual scoped_refptr<UsbDevice> GetDeviceById(uint32 unique_id) OVERRIDE { |
+ NOTIMPLEMENTED(); |
+ return NULL; |
+ } |
+ |
+ virtual void GetDevices( |
+ std::vector<scoped_refptr<UsbDevice> >* devices) OVERRIDE { |
+ STLClearObject(devices); |
+ // This switch should be kept in sync with |
+ // AndroidUsbBrowserTest::DeviceCountChanged. |
+ switch (step_) { |
+ case 0: |
+ // No devices. |
+ break; |
+ case 1: |
+ // Android device. |
+ devices->push_back(new MockUsbDevice<AndroidTraits>()); |
+ break; |
+ case 2: |
+ // Android and non-android device. |
+ devices->push_back(new MockUsbDevice<AndroidTraits>()); |
+ devices->push_back(new MockUsbDevice<NonAndroidTraits>()); |
+ break; |
+ case 3: |
+ // Non-android device. |
+ devices->push_back(new MockUsbDevice<NonAndroidTraits>()); |
+ break; |
+ } |
+ step_++; |
+ } |
+ |
+ private: |
+ int step_ = 0; |
+}; |
+ |
+class AndroidUsbBrowserTest |
+ : public InProcessBrowserTest, |
+ public DevToolsAndroidBridge::DeviceCountListener { |
+ protected: |
+ AndroidUsbBrowserTest() : step_(0) {} |
+ |
+ virtual void SetUpOnMainThread() OVERRIDE { |
+ scoped_refptr<content::MessageLoopRunner> runner = |
+ new content::MessageLoopRunner; |
+ |
+ BrowserThread::PostTaskAndReply( |
+ BrowserThread::FILE, |
+ FROM_HERE, |
+ base::Bind(&AndroidUsbBrowserTest::SetUpService, this), |
+ runner->QuitClosure()); |
+ runner->Run(); |
+ runner_ = new content::MessageLoopRunner; |
+ adb_bridge_ = |
+ DevToolsAndroidBridge::Factory::GetForProfile(browser()->profile()); |
+ |
+ if (!adb_bridge_) |
+ FAIL() << "Failed to get DevToolsAndroidBridge."; |
+ |
+ adb_bridge_->AddDeviceCountListener(this); |
+ } |
+ |
+ void SetUpService() { |
+ service_ = new MockUsbService(); |
+ UsbService::SetInstanceForTest(service_); |
+ } |
+ |
+ virtual void CleanUpOnMainThread() OVERRIDE { |
+ scoped_refptr<content::MessageLoopRunner> runner = |
+ new content::MessageLoopRunner; |
+ UsbService* service = NULL; |
+ BrowserThread::PostTaskAndReply( |
+ BrowserThread::FILE, |
+ FROM_HERE, |
+ base::Bind(&UsbService::SetInstanceForTest, service), |
+ runner->QuitClosure()); |
+ runner->Run(); |
+ } |
+ |
+ virtual void DeviceCountChanged(int count) OVERRIDE { |
+ adb_bridge_->RemoveDeviceCountListener(this); |
+ adb_bridge_->AddDeviceCountListener(this); |
+ // This switch should be kept in sync with MockUsbService::GetDevice. |
+ switch (step_) { |
+ case 0: |
+ // Check for 0 devices when no devices present. |
+ EXPECT_EQ(0, count); |
+ break; |
+ case 1: |
+ // Check for 1 device when only android device present. |
+ EXPECT_EQ(1, count); |
+ break; |
+ case 2: |
+ // Check for 1 device when android and non-android devices present. |
+ EXPECT_EQ(1, count); |
+ break; |
+ case 3: |
+ // Check for 0 devices when only non-android devices present. |
+ EXPECT_EQ(0, count); |
+ adb_bridge_->RemoveDeviceCountListener(this); |
+ runner_->Quit(); |
+ break; |
+ default: |
+ EXPECT_TRUE(false) << "Unknown step " << step_; |
+ } |
+ step_++; |
+ } |
+ |
+ int step_; |
+ scoped_refptr<content::MessageLoopRunner> runner_; |
+ MockUsbService* service_; |
+ scoped_refptr<DevToolsAndroidBridge> adb_bridge_; |
+}; |
+ |
+} // namespace |
+ |
+IN_PROC_BROWSER_TEST_F(AndroidUsbBrowserTest, TestDeviceCounting) { |
+ runner_->Run(); |
+} |