blob: ee1bbc5e44b5ba26a905fd3358c90ffd2fec3480 [file] [log] [blame]
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001// Copyright (c) 2012 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 "build/build_config.h"
6
7#include "base/basictypes.h"
8#include "base/logging.h"
Ben Murdoch9ab55632013-07-18 11:57:30 +01009#include "base/message_loop/message_loop.h"
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +010010#include "base/strings/stringprintf.h"
11#include "base/strings/utf_string_conversions.h"
Torne (Richard Coles)58218062012-11-14 11:43:16 +000012#include "base/values.h"
Ben Murdoch7dbb3d52013-07-17 14:55:54 +010013#include "chrome/browser/chrome_notification_types.h"
Torne (Richard Coles)58218062012-11-14 11:43:16 +000014#include "chrome/browser/ui/browser.h"
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +000015#include "chrome/browser/ui/tabs/tab_strip_model.h"
Torne (Richard Coles)58218062012-11-14 11:43:16 +000016#include "chrome/common/chrome_paths.h"
17#include "chrome/test/base/in_process_browser_test.h"
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +010018#include "chrome/test/base/interactive_test_utils.h"
Torne (Richard Coles)58218062012-11-14 11:43:16 +000019#include "chrome/test/base/ui_test_utils.h"
20#include "content/public/browser/dom_operation_notification_details.h"
21#include "content/public/browser/notification_registrar.h"
22#include "content/public/browser/notification_service.h"
23#include "content/public/browser/render_view_host.h"
24#include "content/public/browser/render_widget_host_view.h"
25#include "content/public/browser/web_contents.h"
26#include "content/public/browser/web_contents_view.h"
27#include "content/public/test/browser_test_utils.h"
Ben Murdocheb525c52013-07-10 11:40:50 +010028#include "net/test/embedded_test_server/embedded_test_server.h"
Torne (Richard Coles)58218062012-11-14 11:43:16 +000029#include "ui/base/keycodes/keyboard_codes.h"
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +000030#include "ui/views/controls/textfield/textfield.h"
31
32// TODO(kbr): remove: http://crbug.com/222296
33#if defined(OS_MACOSX)
34#import "base/mac/mac_util.h"
35#endif
Torne (Richard Coles)58218062012-11-14 11:43:16 +000036
37using content::DomOperationNotificationDetails;
38using content::NavigationController;
39using content::RenderViewHost;
40
41namespace {
42
Ben Murdocheb525c52013-07-10 11:40:50 +010043const char kTestingPage[] = "/keyevents_test.html";
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +000044const char kSuppressEventJS[] =
45 "window.domAutomationController.send(setDefaultAction('%ls', %ls));";
46const char kGetResultJS[] =
47 "window.domAutomationController.send(keyEventResult[%d]);";
48const char kGetResultLengthJS[] =
49 "window.domAutomationController.send(keyEventResult.length);";
50const char kGetFocusedElementJS[] =
51 "window.domAutomationController.send(focusedElement);";
52const char kSetFocusedElementJS[] =
53 "window.domAutomationController.send(setFocusedElement('%ls'));";
54const char kGetTextBoxValueJS[] =
55 "window.domAutomationController.send("
56 " document.getElementById('%ls').value);";
57const char kSetTextBoxValueJS[] =
58 "window.domAutomationController.send("
59 " document.getElementById('%ls').value = '%ls');";
60const char kStartTestJS[] =
61 "window.domAutomationController.send(startTest(%d));";
Torne (Richard Coles)58218062012-11-14 11:43:16 +000062
63// Maximum lenght of the result array in KeyEventTestData structure.
64const size_t kMaxResultLength = 10;
65
66// A structure holding test data of a keyboard event.
67// Each keyboard event may generate multiple result strings representing
68// the result of keydown, keypress, keyup and textInput events.
69// For keydown, keypress and keyup events, the format of the result string is:
70// <type> <keyCode> <charCode> <ctrlKey> <shiftKey> <altKey> <commandKey>
71// where <type> may be 'D' (keydown), 'P' (keypress) or 'U' (keyup).
72// <ctrlKey>, <shiftKey> <altKey> and <commandKey> are boolean value indicating
73// the state of corresponding modifier key.
74// For textInput event, the format is: T <text>, where <text> is the text to be
75// input.
76// Please refer to chrome/test/data/keyevents_test.html for details.
77struct KeyEventTestData {
78 ui::KeyboardCode key;
79 bool ctrl;
80 bool shift;
81 bool alt;
82 bool command;
83
84 bool suppress_keydown;
85 bool suppress_keypress;
86 bool suppress_keyup;
87 bool suppress_textinput;
88
89 int result_length;
90 const char* const result[kMaxResultLength];
91};
92
93const wchar_t* GetBoolString(bool value) {
94 return value ? L"true" : L"false";
95}
96
97// A class to help wait for the finish of a key event test.
98class TestFinishObserver : public content::NotificationObserver {
99 public:
100 explicit TestFinishObserver(RenderViewHost* render_view_host)
101 : finished_(false), waiting_(false) {
102 registrar_.Add(this, content::NOTIFICATION_DOM_OPERATION_RESPONSE,
103 content::Source<RenderViewHost>(render_view_host));
104 }
105
106 bool WaitForFinish() {
107 if (!finished_) {
108 waiting_ = true;
109 content::RunMessageLoop();
110 waiting_ = false;
111 }
112 return finished_;
113 }
114
115 virtual void Observe(int type,
116 const content::NotificationSource& source,
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000117 const content::NotificationDetails& details) OVERRIDE {
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000118 DCHECK(type == content::NOTIFICATION_DOM_OPERATION_RESPONSE);
119 content::Details<DomOperationNotificationDetails> dom_op_details(details);
120 // We might receive responses for other script execution, but we only
121 // care about the test finished message.
122 if (dom_op_details->json == "\"FINISHED\"") {
123 finished_ = true;
124 if (waiting_)
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +0100125 base::MessageLoopForUI::current()->Quit();
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000126 }
127 }
128
129 private:
130 bool finished_;
131 bool waiting_;
132 content::NotificationRegistrar registrar_;
133
134 DISALLOW_COPY_AND_ASSIGN(TestFinishObserver);
135};
136
137class BrowserKeyEventsTest : public InProcessBrowserTest {
138 public:
139 BrowserKeyEventsTest() {}
140
141 bool IsViewFocused(ViewID vid) {
142 return ui_test_utils::IsViewFocused(browser(), vid);
143 }
144
145 void ClickOnView(ViewID vid) {
146 ui_test_utils::ClickOnView(browser(), vid);
147 }
148
149 // Set the suppress flag of an event specified by |type|. If |suppress| is
150 // true then the web page will suppress all events with |type|. Following
151 // event types are supported: keydown, keypress, keyup and textInput.
152 void SuppressEventByType(int tab_index, const wchar_t* type, bool suppress) {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000153 ASSERT_LT(tab_index, browser()->tab_strip_model()->count());
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000154 bool actual;
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000155 ASSERT_TRUE(content::ExecuteScriptAndExtractBool(
156 browser()->tab_strip_model()->GetWebContentsAt(tab_index),
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000157 base::StringPrintf(kSuppressEventJS, type, GetBoolString(!suppress)),
158 &actual));
159 ASSERT_EQ(!suppress, actual);
160 }
161
162 void SuppressEvents(int tab_index, bool keydown, bool keypress,
163 bool keyup, bool textinput) {
164 ASSERT_NO_FATAL_FAILURE(
165 SuppressEventByType(tab_index, L"keydown", keydown));
166 ASSERT_NO_FATAL_FAILURE(
167 SuppressEventByType(tab_index, L"keypress", keypress));
168 ASSERT_NO_FATAL_FAILURE(
169 SuppressEventByType(tab_index, L"keyup", keyup));
170 ASSERT_NO_FATAL_FAILURE(
171 SuppressEventByType(tab_index, L"textInput", textinput));
172 }
173
174 void SuppressAllEvents(int tab_index, bool suppress) {
175 SuppressEvents(tab_index, suppress, suppress, suppress, suppress);
176 }
177
178 void GetResultLength(int tab_index, int* length) {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000179 ASSERT_LT(tab_index, browser()->tab_strip_model()->count());
180 ASSERT_TRUE(content::ExecuteScriptAndExtractInt(
181 browser()->tab_strip_model()->GetWebContentsAt(tab_index),
182 kGetResultLengthJS,
183 length));
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000184 }
185
186 void CheckResult(int tab_index, int length, const char* const result[]) {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000187 ASSERT_LT(tab_index, browser()->tab_strip_model()->count());
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000188 int actual_length;
189 ASSERT_NO_FATAL_FAILURE(GetResultLength(tab_index, &actual_length));
190 ASSERT_GE(actual_length, length);
191 for (int i = 0; i < actual_length; ++i) {
192 std::string actual;
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000193 ASSERT_TRUE(content::ExecuteScriptAndExtractString(
194 browser()->tab_strip_model()->GetWebContentsAt(tab_index),
195 base::StringPrintf(kGetResultJS, i),
196 &actual));
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000197
198 // If more events were received than expected, then the additional events
199 // must be keyup events.
200 if (i < length)
201 ASSERT_STREQ(result[i], actual.c_str());
202 else
203 ASSERT_EQ('U', actual[0]);
204 }
205 }
206
207 void CheckFocusedElement(int tab_index, const wchar_t* focused) {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000208 ASSERT_LT(tab_index, browser()->tab_strip_model()->count());
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000209 std::string actual;
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000210 ASSERT_TRUE(content::ExecuteScriptAndExtractString(
211 browser()->tab_strip_model()->GetWebContentsAt(tab_index),
212 kGetFocusedElementJS,
213 &actual));
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000214 ASSERT_EQ(WideToUTF8(focused), actual);
215 }
216
217 void SetFocusedElement(int tab_index, const wchar_t* focused) {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000218 ASSERT_LT(tab_index, browser()->tab_strip_model()->count());
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000219 bool actual;
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000220 ASSERT_TRUE(content::ExecuteScriptAndExtractBool(
221 browser()->tab_strip_model()->GetWebContentsAt(tab_index),
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000222 base::StringPrintf(kSetFocusedElementJS, focused),
223 &actual));
224 ASSERT_TRUE(actual);
225 }
226
227 void CheckTextBoxValue(int tab_index, const wchar_t* id,
228 const wchar_t* value) {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000229 ASSERT_LT(tab_index, browser()->tab_strip_model()->count());
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000230 std::string actual;
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000231 ASSERT_TRUE(content::ExecuteScriptAndExtractString(
232 browser()->tab_strip_model()->GetWebContentsAt(tab_index),
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000233 base::StringPrintf(kGetTextBoxValueJS, id),
234 &actual));
235 ASSERT_EQ(WideToUTF8(value), actual);
236 }
237
238 void SetTextBoxValue(int tab_index, const wchar_t* id,
239 const wchar_t* value) {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000240 ASSERT_LT(tab_index, browser()->tab_strip_model()->count());
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000241 std::string actual;
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000242 ASSERT_TRUE(content::ExecuteScriptAndExtractString(
243 browser()->tab_strip_model()->GetWebContentsAt(tab_index),
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000244 base::StringPrintf(kSetTextBoxValueJS, id, value),
245 &actual));
246 ASSERT_EQ(WideToUTF8(value), actual);
247 }
248
249 void StartTest(int tab_index, int result_length) {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000250 ASSERT_LT(tab_index, browser()->tab_strip_model()->count());
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000251 bool actual;
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000252 ASSERT_TRUE(content::ExecuteScriptAndExtractBool(
253 browser()->tab_strip_model()->GetWebContentsAt(tab_index),
254 base::StringPrintf(kStartTestJS, result_length),
255 &actual));
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000256 ASSERT_TRUE(actual);
257 }
258
259 void TestKeyEvent(int tab_index, const KeyEventTestData& test) {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000260 ASSERT_LT(tab_index, browser()->tab_strip_model()->count());
261 ASSERT_EQ(tab_index, browser()->tab_strip_model()->active_index());
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000262
263 // Inform our testing web page that we are about to start testing a key
264 // event.
265 ASSERT_NO_FATAL_FAILURE(StartTest(tab_index, test.result_length));
266 ASSERT_NO_FATAL_FAILURE(SuppressEvents(
267 tab_index, test.suppress_keydown, test.suppress_keypress,
268 test.suppress_keyup, test.suppress_textinput));
269
270 // We need to create a finish observer before sending the key event,
271 // because the test finished message might be arrived before returning
272 // from the SendKeyPressSync() method.
273 TestFinishObserver finish_observer(
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000274 browser()->tab_strip_model()->GetWebContentsAt(tab_index)->
275 GetRenderViewHost());
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000276
277 ASSERT_TRUE(ui_test_utils::SendKeyPressSync(
278 browser(), test.key, test.ctrl, test.shift, test.alt, test.command));
279 ASSERT_TRUE(finish_observer.WaitForFinish());
280 ASSERT_NO_FATAL_FAILURE(CheckResult(
281 tab_index, test.result_length, test.result));
282 }
283
284 std::string GetTestDataDescription(const KeyEventTestData& data) {
285 std::string desc = base::StringPrintf(
286 " VKEY:0x%02x, ctrl:%d, shift:%d, alt:%d, command:%d\n"
287 " Suppress: keydown:%d, keypress:%d, keyup:%d, textInput:%d\n"
288 " Expected results(%d):\n",
289 data.key, data.ctrl, data.shift, data.alt, data.command,
290 data.suppress_keydown, data.suppress_keypress, data.suppress_keyup,
291 data.suppress_textinput, data.result_length);
292 for (int i = 0; i < data.result_length; ++i) {
293 desc.append(" ");
294 desc.append(data.result[i]);
295 desc.append("\n");
296 }
297 return desc;
298 }
299};
300
301#if defined(OS_MACOSX)
302// http://crbug.com/81451
303#define MAYBE_NormalKeyEvents DISABLED_NormalKeyEvents
304#elif defined(OS_LINUX)
305// http://crbug.com/129235
306#define MAYBE_NormalKeyEvents DISABLED_NormalKeyEvents
307#else
308#define MAYBE_NormalKeyEvents NormalKeyEvents
309#endif
310
311IN_PROC_BROWSER_TEST_F(BrowserKeyEventsTest, MAYBE_NormalKeyEvents) {
312 static const KeyEventTestData kTestNoInput[] = {
313 // a
314 { ui::VKEY_A, false, false, false, false,
315 false, false, false, false, 3,
316 { "D 65 0 false false false false",
317 "P 97 97 false false false false",
318 "U 65 0 false false false false" } },
319 // shift-a
320 { ui::VKEY_A, false, true, false, false,
321 false, false, false, false, 5,
322 { "D 16 0 false true false false",
323 "D 65 0 false true false false",
324 "P 65 65 false true false false",
325 "U 65 0 false true false false",
326 "U 16 0 false true false false" } },
327 // a, suppress keydown
328 { ui::VKEY_A, false, false, false, false,
329 true, false, false, false, 2,
330 { "D 65 0 false false false false",
331 "U 65 0 false false false false" } },
332 };
333
334 static const KeyEventTestData kTestWithInput[] = {
335 // a
336 { ui::VKEY_A, false, false, false, false,
337 false, false, false, false, 4,
338 { "D 65 0 false false false false",
339 "P 97 97 false false false false",
340 "T a",
341 "U 65 0 false false false false" } },
342 // shift-a
343 { ui::VKEY_A, false, true, false, false,
344 false, false, false, false, 6,
345 { "D 16 0 false true false false",
346 "D 65 0 false true false false",
347 "P 65 65 false true false false",
348 "T A",
349 "U 65 0 false true false false",
350 "U 16 0 false true false false" } },
351 // a, suppress keydown
352 { ui::VKEY_A, false, false, false, false,
353 true, false, false, false, 2,
354 { "D 65 0 false false false false",
355 "U 65 0 false false false false" } },
356 // a, suppress keypress
357 { ui::VKEY_A, false, false, false, false,
358 false, true, false, false, 3,
359 { "D 65 0 false false false false",
360 "P 97 97 false false false false",
361 "U 65 0 false false false false" } },
362 // a, suppress textInput
363 { ui::VKEY_A, false, false, false, false,
364 false, false, false, true, 4,
365 { "D 65 0 false false false false",
366 "P 97 97 false false false false",
367 "T a",
368 "U 65 0 false false false false" } },
369 };
370
Ben Murdocheb525c52013-07-10 11:40:50 +0100371 ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000372
373 ASSERT_TRUE(ui_test_utils::BringBrowserWindowToFront(browser()));
Ben Murdocheb525c52013-07-10 11:40:50 +0100374 GURL url = embedded_test_server()->GetURL(kTestingPage);
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000375 ui_test_utils::NavigateToURL(browser(), url);
376
377 ASSERT_NO_FATAL_FAILURE(ClickOnView(VIEW_ID_TAB_CONTAINER));
378 ASSERT_TRUE(IsViewFocused(VIEW_ID_TAB_CONTAINER));
379
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000380 int tab_index = browser()->tab_strip_model()->active_index();
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000381 for (size_t i = 0; i < arraysize(kTestNoInput); ++i) {
382 EXPECT_NO_FATAL_FAILURE(TestKeyEvent(tab_index, kTestNoInput[i]))
383 << "kTestNoInput[" << i << "] failed:\n"
384 << GetTestDataDescription(kTestNoInput[i]);
385 }
386
387 // Input in normal text box.
388 ASSERT_NO_FATAL_FAILURE(SetFocusedElement(tab_index, L"A"));
389 for (size_t i = 0; i < arraysize(kTestWithInput); ++i) {
390 EXPECT_NO_FATAL_FAILURE(TestKeyEvent(tab_index, kTestWithInput[i]))
391 << "kTestWithInput[" << i << "] in text box failed:\n"
392 << GetTestDataDescription(kTestWithInput[i]);
393 }
394 EXPECT_NO_FATAL_FAILURE(CheckTextBoxValue(tab_index, L"A", L"aA"));
395
396 // Input in password box.
397 ASSERT_NO_FATAL_FAILURE(SetFocusedElement(tab_index, L"B"));
398 for (size_t i = 0; i < arraysize(kTestWithInput); ++i) {
399 EXPECT_NO_FATAL_FAILURE(TestKeyEvent(tab_index, kTestWithInput[i]))
400 << "kTestWithInput[" << i << "] in password box failed:\n"
401 << GetTestDataDescription(kTestWithInput[i]);
402 }
403 EXPECT_NO_FATAL_FAILURE(CheckTextBoxValue(tab_index, L"B", L"aA"));
404}
405
406#if defined(OS_WIN) || defined(OS_LINUX)
407
Ben Murdochbb1529c2013-08-08 10:24:53 +0100408#if defined(OS_LINUX) || (defined(OS_WIN) && defined(USE_AURA))
409// Linux: http://crbug.com/129235
410// Win Aura: crbug.com/269564
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000411#define MAYBE_CtrlKeyEvents DISABLED_CtrlKeyEvents
412#else
413#define MAYBE_CtrlKeyEvents CtrlKeyEvents
414#endif
415
416IN_PROC_BROWSER_TEST_F(BrowserKeyEventsTest, MAYBE_CtrlKeyEvents) {
417 static const KeyEventTestData kTestCtrlF = {
418 ui::VKEY_F, true, false, false, false,
419 false, false, false, false, 2,
420 { "D 17 0 true false false false",
421 "D 70 0 true false false false" }
422 };
423
424 static const KeyEventTestData kTestCtrlFSuppressKeyDown = {
425 ui::VKEY_F, true, false, false, false,
426 true, false, false, false, 4,
427 { "D 17 0 true false false false",
428 "D 70 0 true false false false",
429 "U 70 0 true false false false",
430 "U 17 0 true false false false" }
431 };
432
433 // Ctrl+Z doesn't bind to any accelerators, which then should generate a
434 // keypress event with charCode=26.
435 static const KeyEventTestData kTestCtrlZ = {
436 ui::VKEY_Z, true, false, false, false,
437 false, false, false, false, 5,
438 { "D 17 0 true false false false",
439 "D 90 0 true false false false",
440 "P 26 26 true false false false",
441 "U 90 0 true false false false",
442 "U 17 0 true false false false" }
443 };
444
445 static const KeyEventTestData kTestCtrlZSuppressKeyDown = {
446 ui::VKEY_Z, true, false, false, false,
447 true, false, false, false, 4,
448 { "D 17 0 true false false false",
449 "D 90 0 true false false false",
450 "U 90 0 true false false false",
451 "U 17 0 true false false false" }
452 };
453
454 // Ctrl+Enter shall generate a keypress event with charCode=10 (LF).
455 static const KeyEventTestData kTestCtrlEnter = {
456 ui::VKEY_RETURN, true, false, false, false,
457 false, false, false, false, 5,
458 { "D 17 0 true false false false",
459 "D 13 0 true false false false",
460 "P 10 10 true false false false",
461 "U 13 0 true false false false",
462 "U 17 0 true false false false" }
463 };
464
Ben Murdocheb525c52013-07-10 11:40:50 +0100465 ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000466
467 ASSERT_TRUE(ui_test_utils::BringBrowserWindowToFront(browser()));
Ben Murdocheb525c52013-07-10 11:40:50 +0100468 GURL url = embedded_test_server()->GetURL(kTestingPage);
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000469 ui_test_utils::NavigateToURL(browser(), url);
470
471 ASSERT_NO_FATAL_FAILURE(ClickOnView(VIEW_ID_TAB_CONTAINER));
472 ASSERT_TRUE(IsViewFocused(VIEW_ID_TAB_CONTAINER));
473
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000474 int tab_index = browser()->tab_strip_model()->active_index();
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000475 // Press Ctrl+F, which will make the Find box open and request focus.
476 EXPECT_NO_FATAL_FAILURE(TestKeyEvent(tab_index, kTestCtrlF));
477 EXPECT_TRUE(IsViewFocused(VIEW_ID_FIND_IN_PAGE_TEXT_FIELD));
478
479 // Press Escape to close the Find box and move the focus back to the web page.
480 ASSERT_TRUE(ui_test_utils::SendKeyPressSync(
481 browser(), ui::VKEY_ESCAPE, false, false, false, false));
482 ASSERT_TRUE(IsViewFocused(VIEW_ID_TAB_CONTAINER));
483
484 // Press Ctrl+F with keydown suppressed shall not open the find box.
485 EXPECT_NO_FATAL_FAILURE(TestKeyEvent(tab_index, kTestCtrlFSuppressKeyDown));
486 ASSERT_TRUE(IsViewFocused(VIEW_ID_TAB_CONTAINER));
487
488 EXPECT_NO_FATAL_FAILURE(TestKeyEvent(tab_index, kTestCtrlZ));
489 EXPECT_NO_FATAL_FAILURE(TestKeyEvent(tab_index, kTestCtrlZSuppressKeyDown));
490 EXPECT_NO_FATAL_FAILURE(TestKeyEvent(tab_index, kTestCtrlEnter));
491}
492#elif defined(OS_MACOSX)
493// http://crbug.com/81451
494IN_PROC_BROWSER_TEST_F(BrowserKeyEventsTest, DISABLED_CommandKeyEvents) {
495 static const KeyEventTestData kTestCmdF = {
496 ui::VKEY_F, false, false, false, true,
497 false, false, false, false, 2,
498 { "D 91 0 false false false true",
499 "D 70 0 false false false true" }
500 };
501
502 // On Mac we don't send key up events when command modifier is down.
503 static const KeyEventTestData kTestCmdFSuppressKeyDown = {
504 ui::VKEY_F, false, false, false, true,
505 true, false, false, false, 3,
506 { "D 91 0 false false false true",
507 "D 70 0 false false false true",
508 "U 91 0 false false false true" }
509 };
510
Ben Murdocheb525c52013-07-10 11:40:50 +0100511 ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000512
513 ASSERT_TRUE(ui_test_utils::BringBrowserWindowToFront(browser()));
Ben Murdocheb525c52013-07-10 11:40:50 +0100514 GURL url = embedded_test_server()->GetURL(kTestingPage);
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000515 ui_test_utils::NavigateToURL(browser(), url);
516
517 ASSERT_NO_FATAL_FAILURE(ClickOnView(VIEW_ID_TAB_CONTAINER));
518 ASSERT_TRUE(IsViewFocused(VIEW_ID_TAB_CONTAINER));
519
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000520 int tab_index = browser()->tab_strip_model()->active_index();
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000521 // Press Cmd+F, which will make the Find box open and request focus.
522 EXPECT_NO_FATAL_FAILURE(TestKeyEvent(tab_index, kTestCmdF));
523 EXPECT_TRUE(IsViewFocused(VIEW_ID_FIND_IN_PAGE_TEXT_FIELD));
524
525 // Press Escape to close the Find box and move the focus back to the web page.
526 ASSERT_TRUE(ui_test_utils::SendKeyPressSync(
527 browser(), ui::VKEY_ESCAPE, false, false, false, false));
528 ASSERT_TRUE(IsViewFocused(VIEW_ID_TAB_CONTAINER));
529
530 // Press Cmd+F with keydown suppressed shall not open the find box.
531 EXPECT_NO_FATAL_FAILURE(TestKeyEvent(tab_index, kTestCmdFSuppressKeyDown));
532 ASSERT_TRUE(IsViewFocused(VIEW_ID_TAB_CONTAINER));
533}
534#endif
535
Torne (Richard Coles)a93a17c2013-05-15 11:34:50 +0100536// Flaky: http://crbug.com/81451 , http://crbug.com/129235 ,
537// also fails on Windows.
538IN_PROC_BROWSER_TEST_F(BrowserKeyEventsTest, DISABLED_AccessKeys) {
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000539#if defined(OS_MACOSX)
540 // On Mac, access keys use ctrl+alt modifiers.
541 static const KeyEventTestData kTestAccessA = {
542 ui::VKEY_A, true, false, true, false,
543 false, false, false, false, 6,
544 { "D 17 0 true false false false",
545 "D 18 0 true false true false",
546 "D 65 0 true false true false",
547 "U 65 0 true false true false",
548 "U 18 0 true false true false",
549 "U 17 0 true false false false" }
550 };
551
552 static const KeyEventTestData kTestAccessDSuppress = {
553 ui::VKEY_D, true, false, true, false,
554 true, true, true, false, 6,
555 { "D 17 0 true false false false",
556 "D 18 0 true false true false",
557 "D 68 0 true false true false",
558 "U 68 0 true false true false",
559 "U 18 0 true false true false",
560 "U 17 0 true false false false" }
561 };
562
563 static const KeyEventTestData kTestAccess1 = {
564 ui::VKEY_1, true, false, true, false,
565 false, false, false, false, 6,
566 { "D 17 0 true false false false",
567 "D 18 0 true false true false",
568 "D 49 0 true false true false",
569 "U 49 0 true false true false",
570 "U 18 0 true false true false",
571 "U 17 0 true false false false" }
572 };
573#else
574 static const KeyEventTestData kTestAccessA = {
575 ui::VKEY_A, false, false, true, false,
576 false, false, false, false, 4,
577 { "D 18 0 false false true false",
578 "D 65 0 false false true false",
579 "U 65 0 false false true false",
580 "U 18 0 false false true false" }
581 };
582
583 static const KeyEventTestData kTestAccessD = {
584 ui::VKEY_D, false, false, true, false,
585 false, false, false, false, 2,
586 { "D 18 0 false false true false",
587 "D 68 0 false false true false" }
588 };
589
590 static const KeyEventTestData kTestAccessDSuppress = {
591 ui::VKEY_D, false, false, true, false,
592 true, true, true, false, 4,
593 { "D 18 0 false false true false",
594 "D 68 0 false false true false",
595 "U 68 0 false false true false",
596 "U 18 0 false false true false" }
597 };
598
599#if !defined(USE_ASH)
600 static const KeyEventTestData kTestAccess1 = {
601 ui::VKEY_1, false, false, true, false,
602 false, false, false, false, 4,
603 { "D 18 0 false false true false",
604 "D 49 0 false false true false",
605 "U 49 0 false false true false",
606 "U 18 0 false false true false" }
607 };
608#endif
609#endif
610
Ben Murdocheb525c52013-07-10 11:40:50 +0100611 ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000612
613 ASSERT_TRUE(ui_test_utils::BringBrowserWindowToFront(browser()));
Ben Murdocheb525c52013-07-10 11:40:50 +0100614 GURL url = embedded_test_server()->GetURL(kTestingPage);
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000615 ui_test_utils::NavigateToURL(browser(), url);
616
617 content::RunAllPendingInMessageLoop();
618 ASSERT_NO_FATAL_FAILURE(ClickOnView(VIEW_ID_TAB_CONTAINER));
619 ASSERT_TRUE(IsViewFocused(VIEW_ID_TAB_CONTAINER));
620
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000621 int tab_index = browser()->tab_strip_model()->active_index();
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000622 // Make sure no element is focused.
623 EXPECT_NO_FATAL_FAILURE(CheckFocusedElement(tab_index, L""));
624 // Alt+A should focus the element with accesskey = "A".
625 EXPECT_NO_FATAL_FAILURE(TestKeyEvent(tab_index, kTestAccessA));
626 EXPECT_NO_FATAL_FAILURE(CheckFocusedElement(tab_index, L"A"));
627
628 // Blur the focused element.
629 EXPECT_NO_FATAL_FAILURE(SetFocusedElement(tab_index, L""));
630 // Make sure no element is focused.
631 EXPECT_NO_FATAL_FAILURE(CheckFocusedElement(tab_index, L""));
632
633#if !defined(OS_MACOSX)
634 // Alt+D should move the focus to the location entry.
635 EXPECT_NO_FATAL_FAILURE(TestKeyEvent(tab_index, kTestAccessD));
636
637 // TODO(isherman): This is an experimental change to help diagnose
638 // http://crbug.com/55713
639 content::RunAllPendingInMessageLoop();
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000640 EXPECT_TRUE(IsViewFocused(VIEW_ID_OMNIBOX));
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000641 // No element should be focused, as Alt+D was handled by the browser.
642 EXPECT_NO_FATAL_FAILURE(CheckFocusedElement(tab_index, L""));
643
644 // Move the focus back to the web page.
645 ASSERT_NO_FATAL_FAILURE(ClickOnView(VIEW_ID_TAB_CONTAINER));
646 ASSERT_TRUE(IsViewFocused(VIEW_ID_TAB_CONTAINER));
647
648 // Make sure no element is focused.
649 EXPECT_NO_FATAL_FAILURE(CheckFocusedElement(tab_index, L""));
650#endif
651
652 // If the keydown event is suppressed, then Alt+D should be handled as an
653 // accesskey rather than an accelerator key. Activation of an accesskey is not
654 // a part of the default action of the key event, so it should not be
655 // suppressed at all.
656 EXPECT_NO_FATAL_FAILURE(TestKeyEvent(tab_index, kTestAccessDSuppress));
657 ASSERT_TRUE(IsViewFocused(VIEW_ID_TAB_CONTAINER));
658 EXPECT_NO_FATAL_FAILURE(CheckFocusedElement(tab_index, L"D"));
659
660 // Blur the focused element.
661 EXPECT_NO_FATAL_FAILURE(SetFocusedElement(tab_index, L""));
662 // Make sure no element is focused.
663 EXPECT_NO_FATAL_FAILURE(CheckFocusedElement(tab_index, L""));
664#if !defined(USE_ASH)
665 // On Ash, alt-1..9 are assigned as window selection global accelerators, so
666 // they can not be used as accesskeys.
667 EXPECT_NO_FATAL_FAILURE(TestKeyEvent(tab_index, kTestAccess1));
668#if defined(TOOLKIT_GTK)
669 // On GTK, alt-0..9 are assigned as tab selection accelerators, so they can
670 // not be used as accesskeys.
671 EXPECT_NO_FATAL_FAILURE(CheckFocusedElement(tab_index, L""));
672#else
673 EXPECT_NO_FATAL_FAILURE(CheckFocusedElement(tab_index, L"1"));
674#endif
675#endif
676}
677
678// Flaky, http://crbug.com/69475.
679#if defined(OS_LINUX)
680#define MAYBE_ReservedAccelerators DISABLED_ReservedAccelerators
681#else
682#define MAYBE_ReservedAccelerators ReservedAccelerators
683#endif
684IN_PROC_BROWSER_TEST_F(BrowserKeyEventsTest, MAYBE_ReservedAccelerators) {
Ben Murdocheb525c52013-07-10 11:40:50 +0100685 ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000686
687 ASSERT_TRUE(ui_test_utils::BringBrowserWindowToFront(browser()));
Ben Murdocheb525c52013-07-10 11:40:50 +0100688 GURL url = embedded_test_server()->GetURL(kTestingPage);
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000689 ui_test_utils::NavigateToURL(browser(), url);
690
691 ASSERT_NO_FATAL_FAILURE(ClickOnView(VIEW_ID_TAB_CONTAINER));
692 ASSERT_TRUE(IsViewFocused(VIEW_ID_TAB_CONTAINER));
693
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000694 ASSERT_EQ(1, browser()->tab_strip_model()->count());
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000695
696 static const KeyEventTestData kTestCtrlOrCmdT = {
697#if defined(OS_MACOSX)
698 ui::VKEY_T, false, false, false, true,
699 true, false, false, false, 1,
700 { "D 91 0 false false false true" }
701#else
702 ui::VKEY_T, true, false, false, false,
703 true, false, false, false, 1,
704 { "D 17 0 true false false false" }
705#endif
706 };
707
708 content::WindowedNotificationObserver wait_for_new_tab(
709 chrome::NOTIFICATION_TAB_PARENTED,
710 content::NotificationService::AllSources());
711
712 // Press Ctrl/Cmd+T, which will open a new tab. It cannot be suppressed.
713 EXPECT_NO_FATAL_FAILURE(TestKeyEvent(0, kTestCtrlOrCmdT));
714 wait_for_new_tab.Wait();
715
716 int result_length;
717 ASSERT_NO_FATAL_FAILURE(GetResultLength(0, &result_length));
718 EXPECT_EQ(1, result_length);
719
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000720 EXPECT_EQ(2, browser()->tab_strip_model()->count());
721 ASSERT_EQ(1, browser()->tab_strip_model()->active_index());
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000722
723 // Because of issue <http://crbug.com/65375>, switching back to the first tab
724 // may cause the focus to be grabbed by omnibox. So instead, we load our
725 // testing page in the newly created tab and try Cmd-W here.
726 ui_test_utils::NavigateToURL(browser(), url);
727
728 // Make sure the focus is in the testing page.
729 ASSERT_NO_FATAL_FAILURE(ClickOnView(VIEW_ID_TAB_CONTAINER));
730 ASSERT_TRUE(IsViewFocused(VIEW_ID_TAB_CONTAINER));
731
732 // Reserved accelerators can't be suppressed.
733 ASSERT_NO_FATAL_FAILURE(SuppressAllEvents(1, true));
734
735 content::WindowedNotificationObserver wait_for_tab_closed(
736 content::NOTIFICATION_WEB_CONTENTS_DESTROYED,
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000737 content::Source<content::WebContents>(
738 browser()->tab_strip_model()->GetWebContentsAt(1)));
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000739
740 // Press Ctrl/Cmd+W, which will close the tab.
741#if defined(OS_MACOSX)
742 ASSERT_TRUE(ui_test_utils::SendKeyPressSync(
743 browser(), ui::VKEY_W, false, false, false, true));
744#else
745 ASSERT_TRUE(ui_test_utils::SendKeyPressSync(
746 browser(), ui::VKEY_W, true, false, false, false));
747#endif
748
749 ASSERT_NO_FATAL_FAILURE(wait_for_tab_closed.Wait());
750
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000751 EXPECT_EQ(1, browser()->tab_strip_model()->count());
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000752}
753
754#if defined(OS_MACOSX)
755IN_PROC_BROWSER_TEST_F(BrowserKeyEventsTest, EditorKeyBindings) {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000756 // TODO(kbr): re-enable: http://crbug.com/222296
757 if (base::mac::IsOSMountainLionOrLater())
758 return;
759
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000760 static const KeyEventTestData kTestCtrlA = {
761 ui::VKEY_A, true, false, false, false,
762 false, false, false, false, 4,
763 { "D 17 0 true false false false",
764 "D 65 0 true false false false",
765 "U 65 0 true false false false",
766 "U 17 0 true false false false" }
767 };
768
769 static const KeyEventTestData kTestCtrlF = {
770 ui::VKEY_F, true, false, false, false,
771 false, false, false, false, 4,
772 { "D 17 0 true false false false",
773 "D 70 0 true false false false",
774 "U 70 0 true false false false",
775 "U 17 0 true false false false" }
776 };
777
778 static const KeyEventTestData kTestCtrlK = {
779 ui::VKEY_K, true, false, false, false,
780 false, false, false, false, 4,
781 { "D 17 0 true false false false",
782 "D 75 0 true false false false",
783 "U 75 0 true false false false",
784 "U 17 0 true false false false" }
785 };
786
Ben Murdocheb525c52013-07-10 11:40:50 +0100787 ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000788
789 ASSERT_TRUE(ui_test_utils::BringBrowserWindowToFront(browser()));
Ben Murdocheb525c52013-07-10 11:40:50 +0100790 GURL url = embedded_test_server()->GetURL(kTestingPage);
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000791 ui_test_utils::NavigateToURL(browser(), url);
792
793 ASSERT_NO_FATAL_FAILURE(ClickOnView(VIEW_ID_TAB_CONTAINER));
794 ASSERT_TRUE(IsViewFocused(VIEW_ID_TAB_CONTAINER));
795
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000796 int tab_index = browser()->tab_strip_model()->active_index();
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000797 ASSERT_NO_FATAL_FAILURE(SetFocusedElement(tab_index, L"A"));
798 ASSERT_NO_FATAL_FAILURE(SetTextBoxValue(tab_index, L"A", L"Hello"));
799 // Move the caret to the beginning of the line.
800 EXPECT_NO_FATAL_FAILURE(TestKeyEvent(tab_index, kTestCtrlA));
801 // Forward one character
802 EXPECT_NO_FATAL_FAILURE(TestKeyEvent(tab_index, kTestCtrlF));
803 // Delete to the end of the line.
804 EXPECT_NO_FATAL_FAILURE(TestKeyEvent(tab_index, kTestCtrlK));
805 EXPECT_NO_FATAL_FAILURE(CheckTextBoxValue(tab_index, L"A", L"H"));
806}
807#endif
808
809// See http://crbug.com/147579
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000810IN_PROC_BROWSER_TEST_F(BrowserKeyEventsTest, DISABLED_PageUpDownKeys) {
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000811 static const KeyEventTestData kTestPageUp = {
812 ui::VKEY_PRIOR, false, false, false, false,
813 false, false, false, false, 2,
814 { "D 33 0 false false false false",
815 "U 33 0 false false false false" }
816 };
817
818 static const KeyEventTestData kTestPageDown = {
819 ui::VKEY_NEXT, false, false, false, false,
820 false, false, false, false, 2,
821 { "D 34 0 false false false false",
822 "U 34 0 false false false false" }
823 };
824
Ben Murdocheb525c52013-07-10 11:40:50 +0100825 ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000826
827 ASSERT_TRUE(ui_test_utils::BringBrowserWindowToFront(browser()));
Ben Murdocheb525c52013-07-10 11:40:50 +0100828 GURL url = embedded_test_server()->GetURL(kTestingPage);
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000829 ui_test_utils::NavigateToURL(browser(), url);
830
831 ASSERT_NO_FATAL_FAILURE(ClickOnView(VIEW_ID_TAB_CONTAINER));
832 ASSERT_TRUE(IsViewFocused(VIEW_ID_TAB_CONTAINER));
833
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000834 int tab_index = browser()->tab_strip_model()->active_index();
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000835 ASSERT_NO_FATAL_FAILURE(SetFocusedElement(tab_index, L"A"));
836 EXPECT_NO_FATAL_FAILURE(TestKeyEvent(tab_index, kTestPageUp));
837 EXPECT_NO_FATAL_FAILURE(TestKeyEvent(tab_index, kTestPageDown));
838 EXPECT_NO_FATAL_FAILURE(CheckTextBoxValue(tab_index, L"A", L""));
839}
840
841#if defined(OS_WIN)
842// AltKey is enabled only on Windows. See crbug.com/114537.
843IN_PROC_BROWSER_TEST_F(BrowserKeyEventsTest, FocusMenuBarByAltKey) {
844 static const KeyEventTestData kTestAltKey = {
845 ui::VKEY_MENU, false, false, false, false,
846 false, false, false, false, 2,
847 { "D 18 0 false false true false",
848 "U 18 0 false false true false" }
849 };
850
851 static const KeyEventTestData kTestAltKeySuppress = {
852 ui::VKEY_MENU, false, false, false, false,
853 true, false, false, false, 2,
854 { "D 18 0 false false true false",
855 "U 18 0 false false true false" }
856 };
857
858 static const KeyEventTestData kTestCtrlAltKey = {
859 ui::VKEY_MENU, true, false, false, false,
860 false, false, false, false, 4,
861 { "D 17 0 true false false false",
862 "D 18 0 true false true false",
863 "U 18 0 true false true false",
864 "U 17 0 true false false false" }
865 };
866
Ben Murdocheb525c52013-07-10 11:40:50 +0100867 ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000868
869 ASSERT_TRUE(ui_test_utils::BringBrowserWindowToFront(browser()));
Ben Murdocheb525c52013-07-10 11:40:50 +0100870 GURL url = embedded_test_server()->GetURL(kTestingPage);
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000871 ui_test_utils::NavigateToURL(browser(), url);
872
873 ASSERT_NO_FATAL_FAILURE(ClickOnView(VIEW_ID_TAB_CONTAINER));
874 ASSERT_TRUE(IsViewFocused(VIEW_ID_TAB_CONTAINER));
875
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000876 int tab_index = browser()->tab_strip_model()->active_index();
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000877 // Press and release Alt key to focus wrench menu button.
878 EXPECT_NO_FATAL_FAILURE(TestKeyEvent(tab_index, kTestAltKey));
879 EXPECT_TRUE(IsViewFocused(VIEW_ID_APP_MENU));
880
881 ASSERT_NO_FATAL_FAILURE(ClickOnView(VIEW_ID_TAB_CONTAINER));
882 ASSERT_TRUE(IsViewFocused(VIEW_ID_TAB_CONTAINER));
883
884 // Alt key can be suppressed.
885 EXPECT_NO_FATAL_FAILURE(TestKeyEvent(tab_index, kTestAltKeySuppress));
886 ASSERT_TRUE(IsViewFocused(VIEW_ID_TAB_CONTAINER));
887
888 // Ctrl+Alt should have no effect.
889 EXPECT_NO_FATAL_FAILURE(TestKeyEvent(tab_index, kTestCtrlAltKey));
890 ASSERT_TRUE(IsViewFocused(VIEW_ID_TAB_CONTAINER));
891}
892#endif
893
894} // namespace