Switch global error menu icon to vectorized MD asset
[chromium-blink-merge.git] / chrome / browser / apps / app_window_intercept_all_keys_uitest.cc
blobfd79de53f0c7d3bb52d836bdf724b5d09d4e3a68
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 "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 "components/version_info/version_info.h"
12 #include "extensions/browser/app_window/native_app_window.h"
13 #include "extensions/test/extension_test_message_listener.h"
14 #include "testing/gtest/include/gtest/gtest-spi.h"
16 using extensions::NativeAppWindow;
18 class AppWindowInterceptAllKeysTest
19 : public extensions::PlatformAppBrowserTest {
20 public:
21 // Send key to window but does not wait till the key is actually in the input
22 // queue (like ui_test_utils::SendKeyPressToWindowSync()) as key will not be
23 // sent to hook when keyboard is intercepted.
24 bool SimulateKeyPress(ui::KeyboardCode key,
25 bool control,
26 bool shift,
27 bool alt,
28 bool command) {
29 DVLOG(1) << "Sending: " << key << " control = " << control
30 << " shift = " << shift << " alt = " << alt
31 << " command = " << command;
32 if (!ui_controls::SendKeyPressNotifyWhenDone(
33 GetFirstAppWindow()->GetNativeWindow(), key, control, shift, alt,
34 command, null_callback_)) {
35 LOG(WARNING) << "Failed to send key to app";
36 failure_message_ = "Failed to send key to app.";
37 return false;
40 base::RunLoop().RunUntilIdle();
41 return !testing::Test::HasFatalFailure();
44 bool SimulateKeyPress(ui::KeyboardCode key) {
45 return SimulateKeyPress(key, false, false, false, false);
48 bool WaitForKeyEvent(ui::KeyboardCode code) {
49 std::string key_event = base::StringPrintf("KeyReceived: %d", code);
50 ExtensionTestMessageListener key_listener(key_event, false);
52 if (!SimulateKeyPress(code)) {
53 failure_message_ = "Failed to send key to app";
54 return false;
57 key_listener.WaitUntilSatisfied();
59 DVLOG(1) << "Application ACK-ed keypress";
60 return true;
63 bool LoadApplication(const char* app_path) {
64 DVLOG(1) << "Launching app = " << app_path;
65 LoadAndLaunchPlatformApp(app_path, "Launched");
67 DVLOG(1) << "Validating that application is in focus";
68 // We start by making sure the window is actually focused.
69 if (!ui_test_utils::ShowAndFocusNativeWindow(
70 GetFirstAppWindow()->GetNativeWindow())) {
71 failure_message_ = "App did not get focus.";
72 return false;
75 DVLOG(1) << "Launched application";
76 return true;
79 void SendTaskSwitchKeys() {
80 // Send switch sequence (currently just for windows - will have to update as
81 // more platform support is added).
82 SimulateKeyPress(ui::VKEY_TAB, false, false, true, false);
85 void ValidateCannotInterceptKeys(const char* app_path,
86 bool change_intercept,
87 bool enable_intercept) {
88 ExtensionTestMessageListener command_listener("readyForCommand", true);
89 ASSERT_TRUE(LoadApplication(app_path)) << failure_message_;
91 const char* message = "";
92 if (change_intercept) {
93 message = enable_intercept ? "enable" : "disable";
95 ASSERT_TRUE(command_listener.WaitUntilSatisfied());
96 command_listener.Reply(message);
97 command_listener.Reset();
99 ASSERT_TRUE(WaitForKeyEvent(ui::VKEY_Z)) << failure_message_;
101 SendTaskSwitchKeys();
103 // Send key and check if it is received.
104 ASSERT_FALSE(SimulateKeyPress(ui::VKEY_Z)) << failure_message_;
107 void ValidateInterceptKeys(bool disable_after_enabling) {
108 ExtensionTestMessageListener command_listener("readyForCommand", true);
109 ASSERT_TRUE(LoadApplication(app_with_permission_)) << failure_message_;
111 // setInterceptAllKeys() is asynchronous so wait for response and receiving
112 // a key back.
113 ASSERT_TRUE(command_listener.WaitUntilSatisfied());
114 command_listener.Reply("enable");
115 command_listener.Reset();
117 ASSERT_TRUE(WaitForKeyEvent(ui::VKEY_Z)) << failure_message_;
119 SendTaskSwitchKeys();
121 // Send key and check if it is received.
122 ASSERT_TRUE(SimulateKeyPress(ui::VKEY_Z)) << failure_message_;
124 ASSERT_TRUE(WaitForKeyEvent(ui::VKEY_Z)) << failure_message_;
126 if (disable_after_enabling) {
127 ASSERT_TRUE(command_listener.WaitUntilSatisfied());
128 command_listener.Reply("disable");
129 command_listener.Reset();
130 ASSERT_TRUE(command_listener.WaitUntilSatisfied());
134 protected:
135 std::string failure_message_;
136 base::Callback<void(void)> null_callback_;
137 const char* app_with_permission_ =
138 "window_api_intercept_all_keys/has_permission";
139 const char* app_without_permission_ =
140 "window_api_intercept_all_keys/no_permission";
143 // Currently this is implemented only for Windows.
144 // Disabled test http://crbug.com/438209
145 #if defined(OS_WIN)
146 #define MAYBE_GetKeysAfterSwitchSequence DISABLED_GetKeysAfterSwitchSequence
147 #else
148 #define MAYBE_GetKeysAfterSwitchSequence DISABLED_GetKeysAfterSwitchSequence
149 #endif
151 // Tests a window continues to keep focus even after application switch key
152 // sequence is sent when setInterceptAllKeys() is enabled.
153 IN_PROC_BROWSER_TEST_F(AppWindowInterceptAllKeysTest,
154 MAYBE_GetKeysAfterSwitchSequence) {
155 ValidateInterceptKeys(false);
158 // Test to make sure that keys not received after disable.
159 // Disabled test http://crbug.com/438209
160 #if defined(OS_WIN)
161 #define MAYBE_NoKeysAfterDisableIsCalled DISABLED_NoKeysAfterDisableIsCalled
162 #else
163 #define MAYBE_NoKeysAfterDisableIsCalled DISABLED_NoKeysAfterDisableIsCalled
164 #endif
166 IN_PROC_BROWSER_TEST_F(AppWindowInterceptAllKeysTest,
167 MAYBE_NoKeysAfterDisableIsCalled) {
168 ValidateInterceptKeys(true);
170 ASSERT_TRUE(WaitForKeyEvent(ui::VKEY_Z)) << failure_message_;
172 SendTaskSwitchKeys();
174 // Send key and check if it is received.
175 ASSERT_FALSE(SimulateKeyPress(ui::VKEY_Z)) << failure_message_;
178 // Test that calling just disable has no effect in retaining keyboard intercept.
179 // Currently this is implemented only for Windows.
180 // Disabled test http://crbug.com/438209
181 #if defined(OS_WIN)
182 #define MAYBE_NoopCallingDisableInterceptAllKeys \
183 DISABLED_NoopCallingDisableInterceptAllKeys
184 #else
185 #define MAYBE_NoopCallingDisableInterceptAllKeys \
186 DISABLED_NoopCallingDisableInterceptAllKeys
187 #endif
189 IN_PROC_BROWSER_TEST_F(AppWindowInterceptAllKeysTest,
190 MAYBE_NoopCallingDisableInterceptAllKeys) {
191 ValidateCannotInterceptKeys(app_with_permission_, true, false);
194 // Test no effect when called without permissions
195 // Currently this is implemented only for Windows.
196 #if defined(OS_WIN)
197 #define MAYBE_NoopCallingEnableWithoutPermission \
198 DISABLED_NoopCallingEnableWithoutPermission
199 #else
200 #define MAYBE_NoopCallingEnableWithoutPermission \
201 DISABLED_NoopCallingEnableWithoutPermission
202 #endif
204 IN_PROC_BROWSER_TEST_F(AppWindowInterceptAllKeysTest,
205 MAYBE_NoopCallingEnableWithoutPermission) {
206 ValidateCannotInterceptKeys(app_without_permission_, true, true);
209 // Test that intercept is disabled by default
210 #if defined(OS_WIN)
211 // Disabled test http://crbug.com/438209
212 #define MAYBE_InterceptDisabledByDefault DISABLED_InterceptDisabledByDefault
213 #else
214 #define MAYBE_InterceptDisabledByDefault DISABLED_InterceptDisabledByDefault
215 #endif
217 IN_PROC_BROWSER_TEST_F(AppWindowInterceptAllKeysTest,
218 MAYBE_InterceptDisabledByDefault) {
219 ValidateCannotInterceptKeys(app_with_permission_, false, false);
222 // Tests that the application cannot be loaded in stable.
223 IN_PROC_BROWSER_TEST_F(AppWindowInterceptAllKeysTest, CannotLoadOtherThanDev) {
224 version_info::Channel version_info[] = {
225 version_info::Channel::BETA, version_info::Channel::STABLE};
226 for (unsigned int index = 0; index < arraysize(version_info); index++) {
227 extensions::ScopedCurrentChannel channel(version_info[index]);
228 const extensions::Extension* extension = nullptr;
229 EXPECT_NONFATAL_FAILURE(
230 extension = LoadExtension(test_data_dir_.AppendASCII("platform_apps")
231 .AppendASCII(app_with_permission_)),
232 "");
234 DVLOG(1) << "Finished loading extension";
236 ASSERT_TRUE(extension == nullptr) << "Application loaded in"
237 << static_cast<int>(version_info[index])
238 << " while permission does not exist";
242 // Inject different keyboard combos and make sure that the app get them all.
243 // Disabled test http://crbug.com/438209
244 #if defined(OS_WIN)
245 #define MAYBE_ValidateKeyEvent DISABLED_ValidateKeyEvent
246 #else
247 #define MAYBE_ValidateKeyEvent DISABLED_ValidateKeyEvent
248 #endif
250 namespace {
251 // Maximum lenght of the result array in KeyEventTestData structure.
252 const size_t kMaxResultLength = 10;
254 // A structure holding test data of a keyboard event.
255 // Each keyboard event may generate multiple result strings representing
256 // the result of keydown, keypress, keyup and textInput events.
257 // For keydown, keypress and keyup events, the format of the result string is:
258 // <type> <keyCode> <charCode> <ctrlKey> <shiftKey> <altKey> <commandKey>
259 // where <type> may be 'D' (keydown), 'P' (keypress) or 'U' (keyup).
260 // <ctrlKey>, <shiftKey> <altKey> and <commandKey> are boolean value indicating
261 // the state of corresponding modifier key.
262 struct KeyEventTestData {
263 ui::KeyboardCode key;
264 bool control;
265 bool shift;
266 bool alt;
267 bool command;
269 int result_length;
270 const char* const result[kMaxResultLength];
272 } // namespace
274 IN_PROC_BROWSER_TEST_F(AppWindowInterceptAllKeysTest, MAYBE_ValidateKeyEvent) {
275 // Launch the app
276 ValidateInterceptKeys(false);
278 static const KeyEventTestData kValidateKeyEvents[] = {
279 // a
280 {ui::VKEY_A,
281 false,
282 false,
283 false,
284 false,
286 {"D 65 0 false false false false",
287 "P 97 97 false false false false",
288 "U 65 0 false false false false"}},
289 // shift+a
290 {ui::VKEY_A,
291 false,
292 true,
293 false,
294 false,
296 {"D 16 0 false true false false",
297 "D 65 0 false true false false",
298 "P 65 65 false true false false",
299 "U 65 0 false true false false",
300 "U 16 0 false true false false"}},
301 // ctrl+f which has accelerator binding should also result in all keys
302 // being
303 // sent.
304 {ui::VKEY_F,
305 true,
306 false,
307 false,
308 false,
310 {"D 17 0 true false false false",
311 "D 70 0 true false false false",
312 "P 6 6 true false false false",
313 "U 70 0 true false false false",
314 "U 17 0 true false false false"}},
315 // ctrl+z
316 {ui::VKEY_Z,
317 true,
318 false,
319 false,
320 false,
322 {"D 17 0 true false false false",
323 "D 90 0 true false false false",
324 "P 26 26 true false false false",
325 "U 90 0 true false false false",
326 "U 17 0 true false false false"}},
327 // alt+f
328 {ui::VKEY_F,
329 false,
330 false,
331 true,
332 false,
334 {"D 18 0 false false true false",
335 "D 70 0 false false true false",
336 "U 70 0 false false true false",
337 "U 18 0 false false true false"}},
338 // make sure both left and right shift makes it across
339 {ui::VKEY_RSHIFT,
340 false,
341 false,
342 false,
343 false,
345 {"D 16 0 false true false false", "U 16 0 false true false false"}},
348 DVLOG(1) << "Starting keyboard input test";
350 for (unsigned int index = 0; index < arraysize(kValidateKeyEvents); index++) {
351 // create all the event listeners needed
352 const KeyEventTestData* current_event = &kValidateKeyEvents[index];
353 scoped_ptr<ExtensionTestMessageListener> listeners[kMaxResultLength];
354 for (int i = 0; i < current_event->result_length; i++) {
355 listeners[i].reset(
356 new ExtensionTestMessageListener(current_event->result[i], false));
358 ASSERT_TRUE(SimulateKeyPress(current_event->key, current_event->control,
359 current_event->shift, current_event->alt,
360 current_event->command));
361 for (int i = 0; i < current_event->result_length; i++) {
362 EXPECT_TRUE(listeners[i]->WaitUntilSatisfied());