// Copyright 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 "base/bind.h" #include "base/compiler_specific.h" #include "base/macros.h" #include "base/run_loop.h" #include "chrome/browser/chromeos/device/input_service_proxy.h" #include "chrome/test/base/in_process_browser_test.h" #include "content/public/browser/browser_thread.h" #include "device/hid/input_service_linux.h" using content::BrowserThread; using device::InputServiceLinux; typedef InputServiceLinux::InputDeviceInfo InputDeviceInfo; namespace chromeos { namespace { const char kKeyboardId[] = "keyboard"; const char kMouseId[] = "mouse"; class InputServiceLinuxTestImpl : public InputServiceLinux { public: InputServiceLinuxTestImpl() {} ~InputServiceLinuxTestImpl() override {} void AddDeviceForTesting(const InputDeviceInfo& info) { AddDevice(info); } void RemoveDeviceForTesting(const std::string& id) { RemoveDevice(id); } private: DISALLOW_COPY_AND_ASSIGN(InputServiceLinuxTestImpl); }; class TestObserver : public InputServiceProxy::Observer { public: TestObserver() : wait_for_device_addition_(false), wait_for_device_removal_(false) {} ~TestObserver() override {} void OnInputDeviceAdded(const InputDeviceInfo& info) override { if (!wait_for_device_addition_) return; EXPECT_TRUE(Equals(expected_info_, info)); done_.Run(); } void OnInputDeviceRemoved(const std::string& id) override { if (!wait_for_device_removal_) return; EXPECT_EQ(expected_id_, id); done_.Run(); } void WaitForDeviceAddition(const InputDeviceInfo& info) { base::RunLoop run; expected_info_ = info; wait_for_device_addition_ = true; done_ = run.QuitClosure(); run.Run(); done_.Reset(); wait_for_device_addition_ = false; } void WaitForDeviceRemoval(const std::string& id) { base::RunLoop run; expected_id_ = id; wait_for_device_removal_ = true; done_ = run.QuitClosure(); run.Run(); done_.Reset(); wait_for_device_removal_ = false; } private: static bool Equals(const InputDeviceInfo& lhs, const InputDeviceInfo& rhs) { return lhs.id == rhs.id && lhs.name == rhs.name && lhs.subsystem == rhs.subsystem && lhs.type == rhs.type && lhs.is_accelerometer == rhs.is_accelerometer && lhs.is_joystick == rhs.is_joystick && lhs.is_key == rhs.is_key && lhs.is_keyboard == rhs.is_keyboard && lhs.is_mouse == rhs.is_mouse && lhs.is_tablet == rhs.is_tablet && lhs.is_touchpad == rhs.is_touchpad && lhs.is_touchscreen == rhs.is_touchscreen; } InputDeviceInfo expected_info_; std::string expected_id_; bool wait_for_device_addition_; bool wait_for_device_removal_; base::Closure done_; DISALLOW_COPY_AND_ASSIGN(TestObserver); }; void InitInputService() { InputServiceLinux::SetForTesting(new InputServiceLinuxTestImpl()); } void AddDevice(const InputDeviceInfo& device) { InputServiceLinuxTestImpl* service = static_cast<InputServiceLinuxTestImpl*>(InputServiceLinux::GetInstance()); service->AddDeviceForTesting(device); } void RemoveDevice(const std::string& id) { InputServiceLinuxTestImpl* service = static_cast<InputServiceLinuxTestImpl*>(InputServiceLinux::GetInstance()); service->RemoveDeviceForTesting(id); } void OnGetDevices(const base::Closure& done, const std::vector<InputDeviceInfo>& devices) { EXPECT_EQ(2, static_cast<int>(devices.size())); done.Run(); } void OnGetKeyboard(const base::Closure& done, bool success, const InputDeviceInfo& info) { EXPECT_TRUE(success); EXPECT_EQ("keyboard", info.id); EXPECT_TRUE(info.is_keyboard); done.Run(); } void OnGetMouse(const base::Closure& done, bool success, const InputDeviceInfo& /* info */) { EXPECT_FALSE(success); done.Run(); } } // namespace class InputServiceProxyTest : public InProcessBrowserTest { public: InputServiceProxyTest() {} ~InputServiceProxyTest() override {} private: DISALLOW_COPY_AND_ASSIGN(InputServiceProxyTest); }; IN_PROC_BROWSER_TEST_F(InputServiceProxyTest, Simple) { BrowserThread::PostTask( BrowserThread::FILE, FROM_HERE, base::Bind(&InitInputService)); InputServiceProxy proxy; TestObserver observer; proxy.AddObserver(&observer); InputDeviceInfo keyboard; keyboard.id = kKeyboardId; keyboard.subsystem = InputServiceLinux::InputDeviceInfo::SUBSYSTEM_INPUT; keyboard.type = InputServiceLinux::InputDeviceInfo::TYPE_USB; keyboard.is_keyboard = true; BrowserThread::PostTask( BrowserThread::FILE, FROM_HERE, base::Bind(&AddDevice, keyboard)); observer.WaitForDeviceAddition(keyboard); InputDeviceInfo mouse; mouse.id = kMouseId; mouse.subsystem = InputServiceLinux::InputDeviceInfo::SUBSYSTEM_INPUT; mouse.type = InputServiceLinux::InputDeviceInfo::TYPE_BLUETOOTH; mouse.is_mouse = true; BrowserThread::PostTask( BrowserThread::FILE, FROM_HERE, base::Bind(&AddDevice, mouse)); observer.WaitForDeviceAddition(mouse); { base::RunLoop run; proxy.GetDevices(base::Bind(&OnGetDevices, run.QuitClosure())); run.Run(); } BrowserThread::PostTask( BrowserThread::FILE, FROM_HERE, base::Bind(&RemoveDevice, kMouseId)); observer.WaitForDeviceRemoval(kMouseId); { base::RunLoop run; proxy.GetDeviceInfo(kKeyboardId, base::Bind(&OnGetKeyboard, run.QuitClosure())); run.Run(); } { base::RunLoop run; proxy.GetDeviceInfo(kMouseId, base::Bind(&OnGetMouse, run.QuitClosure())); run.Run(); } proxy.RemoveObserver(&observer); } } // namespace chromeos