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.
4
5 #include "base/bind.h"
6 #include "base/compiler_specific.h"
7 #include "base/macros.h"
8 #include "base/run_loop.h"
9 #include "chrome/browser/chromeos/device/input_service_proxy.h"
10 #include "chrome/test/base/in_process_browser_test.h"
11 #include "content/public/browser/browser_thread.h"
12 #include "device/hid/input_service_linux.h"
13
14 using content::BrowserThread;
15 using device::InputServiceLinux;
16
17 typedef InputServiceLinux::InputDeviceInfo InputDeviceInfo;
18
19 namespace chromeos {
20
21 namespace {
22
23 const char kKeyboardId[] = "keyboard";
24 const char kMouseId[] = "mouse";
25
26 class InputServiceLinuxTestImpl : public InputServiceLinux {
27 public:
InputServiceLinuxTestImpl()28 InputServiceLinuxTestImpl() {}
~InputServiceLinuxTestImpl()29 virtual ~InputServiceLinuxTestImpl() {}
30
AddDeviceForTesting(const InputDeviceInfo & info)31 void AddDeviceForTesting(const InputDeviceInfo& info) { AddDevice(info); }
RemoveDeviceForTesting(const std::string & id)32 void RemoveDeviceForTesting(const std::string& id) { RemoveDevice(id); }
33
34 private:
35 DISALLOW_COPY_AND_ASSIGN(InputServiceLinuxTestImpl);
36 };
37
38 class TestObserver : public InputServiceProxy::Observer {
39 public:
TestObserver()40 TestObserver()
41 : wait_for_device_addition_(false), wait_for_device_removal_(false) {}
~TestObserver()42 virtual ~TestObserver() {}
43
OnInputDeviceAdded(const InputDeviceInfo & info)44 virtual void OnInputDeviceAdded(const InputDeviceInfo& info) OVERRIDE {
45 if (!wait_for_device_addition_)
46 return;
47 EXPECT_TRUE(Equals(expected_info_, info));
48 done_.Run();
49 }
50
OnInputDeviceRemoved(const std::string & id)51 virtual void OnInputDeviceRemoved(const std::string& id) OVERRIDE {
52 if (!wait_for_device_removal_)
53 return;
54 EXPECT_EQ(expected_id_, id);
55 done_.Run();
56 }
57
WaitForDeviceAddition(const InputDeviceInfo & info)58 void WaitForDeviceAddition(const InputDeviceInfo& info) {
59 base::RunLoop run;
60 expected_info_ = info;
61 wait_for_device_addition_ = true;
62 done_ = run.QuitClosure();
63
64 run.Run();
65
66 done_.Reset();
67 wait_for_device_addition_ = false;
68 }
69
WaitForDeviceRemoval(const std::string & id)70 void WaitForDeviceRemoval(const std::string& id) {
71 base::RunLoop run;
72 expected_id_ = id;
73 wait_for_device_removal_ = true;
74 done_ = run.QuitClosure();
75
76 run.Run();
77
78 done_.Reset();
79 wait_for_device_removal_ = false;
80 }
81
82 private:
Equals(const InputDeviceInfo & lhs,const InputDeviceInfo & rhs)83 static bool Equals(const InputDeviceInfo& lhs, const InputDeviceInfo& rhs) {
84 return lhs.id == rhs.id && lhs.name == rhs.name &&
85 lhs.subsystem == rhs.subsystem &&
86 lhs.type == rhs.type &&
87 lhs.is_accelerometer == rhs.is_accelerometer &&
88 lhs.is_joystick == rhs.is_joystick && lhs.is_key == rhs.is_key &&
89 lhs.is_keyboard == rhs.is_keyboard && lhs.is_mouse == rhs.is_mouse &&
90 lhs.is_tablet == rhs.is_tablet &&
91 lhs.is_touchpad == rhs.is_touchpad &&
92 lhs.is_touchscreen == rhs.is_touchscreen;
93 }
94
95 InputDeviceInfo expected_info_;
96 std::string expected_id_;
97
98 bool wait_for_device_addition_;
99 bool wait_for_device_removal_;
100
101 base::Closure done_;
102
103 DISALLOW_COPY_AND_ASSIGN(TestObserver);
104 };
105
InitInputService()106 void InitInputService() {
107 InputServiceLinux::SetForTesting(new InputServiceLinuxTestImpl());
108 }
109
AddDevice(const InputDeviceInfo & device)110 void AddDevice(const InputDeviceInfo& device) {
111 InputServiceLinuxTestImpl* service =
112 static_cast<InputServiceLinuxTestImpl*>(InputServiceLinux::GetInstance());
113 service->AddDeviceForTesting(device);
114 }
115
RemoveDevice(const std::string & id)116 void RemoveDevice(const std::string& id) {
117 InputServiceLinuxTestImpl* service =
118 static_cast<InputServiceLinuxTestImpl*>(InputServiceLinux::GetInstance());
119 service->RemoveDeviceForTesting(id);
120 }
121
OnGetDevices(const base::Closure & done,const std::vector<InputDeviceInfo> & devices)122 void OnGetDevices(const base::Closure& done,
123 const std::vector<InputDeviceInfo>& devices) {
124 EXPECT_EQ(2, static_cast<int>(devices.size()));
125 done.Run();
126 }
127
OnGetKeyboard(const base::Closure & done,bool success,const InputDeviceInfo & info)128 void OnGetKeyboard(const base::Closure& done,
129 bool success,
130 const InputDeviceInfo& info) {
131 EXPECT_TRUE(success);
132 EXPECT_EQ("keyboard", info.id);
133 EXPECT_TRUE(info.is_keyboard);
134 done.Run();
135 }
136
OnGetMouse(const base::Closure & done,bool success,const InputDeviceInfo &)137 void OnGetMouse(const base::Closure& done,
138 bool success,
139 const InputDeviceInfo& /* info */) {
140 EXPECT_FALSE(success);
141 done.Run();
142 }
143
144 } // namespace
145
146 class InputServiceProxyTest : public InProcessBrowserTest {
147 public:
InputServiceProxyTest()148 InputServiceProxyTest() {}
~InputServiceProxyTest()149 virtual ~InputServiceProxyTest() {}
150
151 private:
152 DISALLOW_COPY_AND_ASSIGN(InputServiceProxyTest);
153 };
154
IN_PROC_BROWSER_TEST_F(InputServiceProxyTest,Simple)155 IN_PROC_BROWSER_TEST_F(InputServiceProxyTest, Simple) {
156 BrowserThread::PostTask(
157 BrowserThread::FILE, FROM_HERE, base::Bind(&InitInputService));
158 InputServiceProxy proxy;
159 TestObserver observer;
160 proxy.AddObserver(&observer);
161
162 InputDeviceInfo keyboard;
163 keyboard.id = kKeyboardId;
164 keyboard.subsystem = InputServiceLinux::InputDeviceInfo::SUBSYSTEM_INPUT;
165 keyboard.type = InputServiceLinux::InputDeviceInfo::TYPE_USB;
166 keyboard.is_keyboard = true;
167 BrowserThread::PostTask(
168 BrowserThread::FILE, FROM_HERE, base::Bind(&AddDevice, keyboard));
169 observer.WaitForDeviceAddition(keyboard);
170
171 InputDeviceInfo mouse;
172 mouse.id = kMouseId;
173 mouse.subsystem = InputServiceLinux::InputDeviceInfo::SUBSYSTEM_INPUT;
174 mouse.type = InputServiceLinux::InputDeviceInfo::TYPE_BLUETOOTH;
175 mouse.is_mouse = true;
176 BrowserThread::PostTask(
177 BrowserThread::FILE, FROM_HERE, base::Bind(&AddDevice, mouse));
178 observer.WaitForDeviceAddition(mouse);
179
180 {
181 base::RunLoop run;
182 proxy.GetDevices(base::Bind(&OnGetDevices, run.QuitClosure()));
183 run.Run();
184 }
185
186 BrowserThread::PostTask(
187 BrowserThread::FILE, FROM_HERE, base::Bind(&RemoveDevice, kMouseId));
188 observer.WaitForDeviceRemoval(kMouseId);
189
190 {
191 base::RunLoop run;
192 proxy.GetDeviceInfo(kKeyboardId,
193 base::Bind(&OnGetKeyboard, run.QuitClosure()));
194 run.Run();
195 }
196
197 {
198 base::RunLoop run;
199 proxy.GetDeviceInfo(kMouseId, base::Bind(&OnGetMouse, run.QuitClosure()));
200 run.Run();
201 }
202
203 proxy.RemoveObserver(&observer);
204 }
205
206 } // namespace chromeos
207