Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(225)

Side by Side Diff: chrome/browser/apps/app_window_intercept_all_keys_uitest.cc

Issue 297123002: API proposal for chrome.app.window to intercept all keys. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Fix class comments based on Sadrul's comments Created 6 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
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/callback.h"
6 #include "base/logging.h"
7 #include "base/macros.h"
8 #include "base/strings/stringprintf.h"
9 #include "chrome/browser/apps/app_browsertest_util.h"
10 #include "chrome/test/base/interactive_test_utils.h"
11 #include "extensions/browser/app_window/native_app_window.h"
12 #include "extensions/test/extension_test_message_listener.h"
13 #include "testing/gtest/include/gtest/gtest-spi.h"
14
15 using extensions::NativeAppWindow;
16
17 class AppWindowInterceptAllKeysTest
18 : public extensions::PlatformAppBrowserTest {
19 public:
20 // Send key to window but does not wait till the key is actually in the input
21 // queue (like ui_test_utils::SendKeyPressToWindowSync()) as key will not be
22 // sent to hook when keyboard is intercepted.
23 bool SimulateKeyPress(ui::KeyboardCode key,
24 bool control,
25 bool shift,
26 bool alt,
27 bool command) {
28 DVLOG(1) << "Sending: " << key << " control = " << control
29 << " shift = " << shift << " alt = " << alt
30 << " command = " << command;
31 if (!ui_controls::SendKeyPressNotifyWhenDone(
32 GetFirstAppWindow()->GetNativeWindow(), key, control, shift, alt,
33 command, null_callback_)) {
34 LOG(WARNING) << "Failed to send key to app";
35 failure_message_ = "Failed to send key to app.";
36 return false;
37 }
38
39 base::RunLoop().RunUntilIdle();
40 return !testing::Test::HasFatalFailure();
41 }
42
43 bool SimulateKeyPress(ui::KeyboardCode key) {
44 return SimulateKeyPress(key, false, false, false, false);
45 }
46
47 bool WaitForKeyEvent(ui::KeyboardCode code) {
48 std::string key_event = base::StringPrintf("KeyReceived: %d", code);
49 ExtensionTestMessageListener key_listener(key_event, false);
50
51 if (!SimulateKeyPress(code)) {
52 failure_message_ = "Failed to send key to app";
53 return false;
54 }
55
56 key_listener.WaitUntilSatisfied();
57
58 DVLOG(1) << "Application ACK-ed keypress";
59 return true;
60 }
61
62 bool LoadApplication(const char* app_path) {
63 DVLOG(1) << "Launching app = " << app_path;
64 LoadAndLaunchPlatformApp(app_path, "Launched");
65
66 DVLOG(1) << "Validating that application is in focus";
67 // We start by making sure the window is actually focused.
68 if (!ui_test_utils::ShowAndFocusNativeWindow(
69 GetFirstAppWindow()->GetNativeWindow())) {
70 failure_message_ = "App did not get focus.";
71 return false;
72 }
73
74 DVLOG(1) << "Launched application";
75 return true;
76 }
77
78 void SendTaskSwitchKeys() {
79 // Send switch sequence (currently just for windows - will have to update as
80 // more platform support is added).
81 SimulateKeyPress(ui::VKEY_TAB, false, false, true, false);
82 }
83
84 void ValidateCannotInterceptKeys(const char* app_path,
85 bool change_intercept,
86 bool enable_intercept) {
87 ExtensionTestMessageListener command_listener("readyForCommand", true);
88 ASSERT_TRUE(LoadApplication(app_path)) << failure_message_;
89
90 const char* message = "";
91 if (change_intercept) {
92 message = enable_intercept ? "enable" : "disable";
93 }
94 ASSERT_TRUE(command_listener.WaitUntilSatisfied());
95 command_listener.Reply(message);
96 command_listener.Reset();
97
98 ASSERT_TRUE(WaitForKeyEvent(ui::VKEY_Z)) << failure_message_;
99
100 SendTaskSwitchKeys();
101
102 // Send key and check if it is received.
103 ASSERT_FALSE(SimulateKeyPress(ui::VKEY_Z)) << failure_message_;
104 }
105
106 void ValidateInterceptKeys(bool disable_after_enabling) {
107 ExtensionTestMessageListener command_listener("readyForCommand", true);
108 ASSERT_TRUE(LoadApplication(app_with_permission_)) << failure_message_;
109
110 // setInterceptAllKeys() is asynchronous so wait for response and receiving
111 // a key back.
112 ASSERT_TRUE(command_listener.WaitUntilSatisfied());
113 command_listener.Reply("enable");
114 command_listener.Reset();
115
116 ASSERT_TRUE(WaitForKeyEvent(ui::VKEY_Z)) << failure_message_;
117
118 SendTaskSwitchKeys();
119
120 // Send key and check if it is received.
121 ASSERT_TRUE(SimulateKeyPress(ui::VKEY_Z)) << failure_message_;
122
123 ASSERT_TRUE(WaitForKeyEvent(ui::VKEY_Z)) << failure_message_;
124
125 if (disable_after_enabling) {
126 ASSERT_TRUE(command_listener.WaitUntilSatisfied());
127 command_listener.Reply("disable");
128 command_listener.Reset();
129 ASSERT_TRUE(command_listener.WaitUntilSatisfied());
130 }
131 }
132
133 protected:
134 std::string failure_message_;
135 base::Callback<void(void)> null_callback_;
136 const char* app_with_permission_ =
137 "window_api_intercept_all_keys/has_permission";
138 const char* app_without_permission_ =
139 "window_api_intercept_all_keys/no_permission";
140 };
141
142 // Currently this is implemented only for Windows.
143 #if defined(OS_WIN)
144 #define MAYBE_GetKeysAfterSwitchSequence GetKeysAfterSwitchSequence
145 #else
146 #define MAYBE_GetKeysAfterSwitchSequence DISABLED_GetKeysAfterSwitchSequence
147 #endif
148
149 // Tests a window continues to keep focus even after application switch key
150 // sequence is sent when setInterceptAllKeys() is enabled.
151 IN_PROC_BROWSER_TEST_F(AppWindowInterceptAllKeysTest,
152 MAYBE_GetKeysAfterSwitchSequence) {
153 ValidateInterceptKeys(false);
154 }
155
156 // Test to make sure that keys not received after disable.
157 #if defined(OS_WIN)
158 #define MAYBE_NoKeysAfterDisableIsCalled NoKeysAfterDisableIsCalled
159 #else
160 #define MAYBE_NoKeysAfterDisableIsCalled DISABLED_NoKeysAfterDisableIsCalled
161 #endif
162
163 IN_PROC_BROWSER_TEST_F(AppWindowInterceptAllKeysTest,
164 MAYBE_NoKeysAfterDisableIsCalled) {
165 ValidateInterceptKeys(true);
166
167 ASSERT_TRUE(WaitForKeyEvent(ui::VKEY_Z)) << failure_message_;
168
169 SendTaskSwitchKeys();
170
171 // Send key and check if it is received.
172 ASSERT_FALSE(SimulateKeyPress(ui::VKEY_Z)) << failure_message_;
173 }
174
175 // Test that calling just disable has no effect in retaining keyboard intercept.
176 // Currently this is implemented only for Windows.
177 #if defined(OS_WIN)
178 #define MAYBE_NoopCallingDisableInterceptAllKeys \
179 NoopCallingDisableInterceptAllKeys
180 #else
181 #define MAYBE_NoopCallingDisableInterceptAllKeys \
182 DISABLED_NoopCallingDisableInterceptAllKeys
183 #endif
184
185 IN_PROC_BROWSER_TEST_F(AppWindowInterceptAllKeysTest,
186 MAYBE_NoopCallingDisableInterceptAllKeys) {
187 ValidateCannotInterceptKeys(app_with_permission_, true, false);
188 }
189
190 // Test no effect when called without permissions
191 // Currently this is implemented only for Windows.
192 #if defined(OS_WIN)
193 #define MAYBE_NoopCallingEnableWithoutPermission \
194 NoopCallingEnableWithoutPermission
195 #else
196 #define MAYBE_NoopCallingEnableWithoutPermission \
197 DISABLED_NoopCallingEnableWithoutPermission
198 #endif
199
200 IN_PROC_BROWSER_TEST_F(AppWindowInterceptAllKeysTest,
201 MAYBE_NoopCallingEnableWithoutPermission) {
202 ValidateCannotInterceptKeys(app_without_permission_, true, true);
203 }
204
205 // Test that intercept is disabled by default
206 #if defined(OS_WIN)
207 #define MAYBE_InterceptDisabledByDefault InterceptDisabledByDefault
208 #else
209 #define MAYBE_InterceptDisabledByDefault DISABLED_InterceptDisabledByDefault
210 #endif
211
212 IN_PROC_BROWSER_TEST_F(AppWindowInterceptAllKeysTest,
213 MAYBE_InterceptDisabledByDefault) {
214 ValidateCannotInterceptKeys(app_with_permission_, false, false);
215 }
216
217 // Tests that the application cannot be loaded in stable.
218 IN_PROC_BROWSER_TEST_F(AppWindowInterceptAllKeysTest, CannotLoadOtherThanDev) {
219 chrome::VersionInfo::Channel version_info[] = {
220 chrome::VersionInfo::CHANNEL_BETA, chrome::VersionInfo::CHANNEL_STABLE};
221 for (unsigned int index = 0; index < arraysize(version_info); index++) {
222 extensions::ScopedCurrentChannel channel(version_info[index]);
223 const extensions::Extension* extension = NULL;
benwells 2014/11/21 00:52:01 nit: nullptr instead of NULL (here and elsewhere i
Sriram 2014/11/21 05:35:21 Done.
224 EXPECT_NONFATAL_FAILURE(
225 extension = LoadExtension(test_data_dir_.AppendASCII("platform_apps")
226 .AppendASCII(app_with_permission_)),
227 "");
228
229 DVLOG(1) << "Finished loading extension";
230
231 ASSERT_TRUE(extension == NULL) << "Application loaded in"
232 << version_info[index]
233 << " while permission does not exist";
234 }
235 }
236
237 // Inject different keyboard combos and make sure that the app get them all.
238 #if defined(OS_WIN)
239 #define MAYBE_ValidateKeyEvent ValidateKeyEvent
240 #else
241 #define MAYBE_ValidateKeyEvent DISABLED_ValidateKeyEvent
242 #endif
243
244 namespace {
245 // Maximum lenght of the result array in KeyEventTestData structure.
246 const size_t kMaxResultLength = 10;
247
248 // A structure holding test data of a keyboard event.
249 // Each keyboard event may generate multiple result strings representing
250 // the result of keydown, keypress, keyup and textInput events.
251 // For keydown, keypress and keyup events, the format of the result string is:
252 // <type> <keyCode> <charCode> <ctrlKey> <shiftKey> <altKey> <commandKey>
253 // where <type> may be 'D' (keydown), 'P' (keypress) or 'U' (keyup).
254 // <ctrlKey>, <shiftKey> <altKey> and <commandKey> are boolean value indicating
255 // the state of corresponding modifier key.
256 struct KeyEventTestData {
257 ui::KeyboardCode key;
258 bool control;
259 bool shift;
260 bool alt;
261 bool command;
262
263 int result_length;
264 const char* const result[kMaxResultLength];
265 };
266 } // namespace
267
268 IN_PROC_BROWSER_TEST_F(AppWindowInterceptAllKeysTest, MAYBE_ValidateKeyEvent) {
269 // Launch the app
270 ValidateInterceptKeys(false);
271
272 static const KeyEventTestData kValidateKeyEvents[] = {
273 // a
274 {ui::VKEY_A,
275 false,
276 false,
277 false,
278 false,
279 3,
280 {"D 65 0 false false false false",
281 "P 97 97 false false false false",
282 "U 65 0 false false false false"}},
283 // shift+a
284 {ui::VKEY_A,
285 false,
286 true,
287 false,
288 false,
289 5,
290 {"D 16 0 false true false false",
291 "D 65 0 false true false false",
292 "P 65 65 false true false false",
293 "U 65 0 false true false false",
294 "U 16 0 false true false false"}},
295 // ctrl+f which has accelerator binding should also result in all keys
296 // being
297 // sent.
298 {ui::VKEY_F,
299 true,
300 false,
301 false,
302 false,
303 5,
304 {"D 17 0 true false false false",
305 "D 70 0 true false false false",
306 "P 6 6 true false false false",
307 "U 70 0 true false false false",
308 "U 17 0 true false false false"}},
309 // ctrl+z
310 {ui::VKEY_Z,
311 true,
312 false,
313 false,
314 false,
315 5,
316 {"D 17 0 true false false false",
317 "D 90 0 true false false false",
318 "P 26 26 true false false false",
319 "U 90 0 true false false false",
320 "U 17 0 true false false false"}},
321 // alt+f
322 {ui::VKEY_F,
323 false,
324 false,
325 true,
326 false,
327 4,
328 {"D 18 0 false false true false",
329 "D 70 0 false false true false",
330 "U 70 0 false false true false",
331 "U 18 0 false false true false"}},
332 // make sure both left and right shift makes it across
333 {ui::VKEY_RSHIFT,
334 false,
335 false,
336 false,
337 false,
338 2,
339 {"D 16 0 false true false false", "U 16 0 false true false false"}},
340 };
341
342 DVLOG(1) << "Starting keyboard input test";
343
344 for (unsigned int index = 0; index < arraysize(kValidateKeyEvents); index++) {
345 // create all the event listeners needed
346 const KeyEventTestData* current_event = &kValidateKeyEvents[index];
347 scoped_ptr<ExtensionTestMessageListener> listeners[kMaxResultLength];
348 for (int i = 0; i < current_event->result_length; i++) {
349 listeners[i].reset(
350 new ExtensionTestMessageListener(current_event->result[i], false));
351 }
352 ASSERT_TRUE(SimulateKeyPress(current_event->key, current_event->control,
353 current_event->shift, current_event->alt,
354 current_event->command));
355 for (int i = 0; i < current_event->result_length; i++) {
356 EXPECT_TRUE(listeners[i]->WaitUntilSatisfied());
357 }
358 }
359 }
OLDNEW
« no previous file with comments | « chrome/app/generated_resources.grd ('k') | chrome/browser/ui/cocoa/apps/native_app_window_cocoa.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698