[M120 Migration]Fix for crash during chrome exit
[platform/framework/web/chromium-efl.git] / chrome / browser / browser_keyevents_browsertest.cc
1 // Copyright 2012 The Chromium Authors
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 <stddef.h>
6
7 #include "base/check.h"
8 #include "base/run_loop.h"
9 #include "base/strings/stringprintf.h"
10 #include "base/strings/utf_string_conversions.h"
11 #include "base/values.h"
12 #include "build/build_config.h"
13 #include "build/chromeos_buildflags.h"
14 #include "chrome/browser/ui/browser.h"
15 #include "chrome/browser/ui/tabs/tab_strip_model.h"
16 #include "chrome/common/chrome_paths.h"
17 #include "chrome/test/base/in_process_browser_test.h"
18 #include "chrome/test/base/interactive_test_utils.h"
19 #include "chrome/test/base/ui_test_utils.h"
20 #include "content/public/browser/render_widget_host_view.h"
21 #include "content/public/browser/web_contents.h"
22 #include "content/public/test/browser_test.h"
23 #include "content/public/test/browser_test_utils.h"
24 #include "net/test/embedded_test_server/embedded_test_server.h"
25 #include "third_party/blink/public/common/switches.h"
26 #include "ui/events/keycodes/keyboard_codes.h"
27
28 using content::NavigationController;
29
30 namespace {
31
32 constexpr char kTestingPage[] = "/keyevents_test.html";
33 constexpr char kSuppressEventJS[] = "setDefaultAction('%s', %s);";
34 constexpr char kGetResultJS[] = "keyEventResult[%d];";
35 constexpr char kGetResultLengthJS[] = "keyEventResult.length;";
36 constexpr char kGetFocusedElementJS[] = "focusedElement;";
37 constexpr char kSetFocusedElementJS[] = "setFocusedElement('%s');";
38 constexpr char kGetTextBoxValueJS[] = "document.getElementById('%s').value;";
39 constexpr char kSetTextBoxValueJS[] =
40     "document.getElementById('%s').value = '%s';";
41 constexpr char kStartTestJS[] = "startTest(%d);";
42
43 // Maximum length of the result array in KeyEventTestData structure.
44 constexpr size_t kMaxResultLength = 10;
45
46 // A structure holding test data of a keyboard event.
47 // Each keyboard event may generate multiple result strings representing
48 // the result of keydown, keypress, keyup and textInput events.
49 // For keydown, keypress and keyup events, the format of the result string is:
50 // <type> <keyCode> <charCode> <ctrlKey> <shiftKey> <altKey> <commandKey>
51 // where <type> may be 'D' (keydown), 'P' (keypress) or 'U' (keyup).
52 // <ctrlKey>, <shiftKey> <altKey> and <commandKey> are boolean value indicating
53 // the state of corresponding modifier key.
54 // For textInput event, the format is: T <text>, where <text> is the text to be
55 // input.
56 // Please refer to chrome/test/data/keyevents_test.html for details.
57 struct KeyEventTestData {
58   ui::KeyboardCode key;
59   bool ctrl;
60   bool shift;
61   bool alt;
62   bool command;
63
64   bool suppress_keydown;
65   bool suppress_keypress;
66   bool suppress_keyup;
67   bool suppress_textinput;
68
69   int result_length;
70   const char* const result[kMaxResultLength];
71 };
72
73 // A class to help wait for the finish of a key event test.
74 class TestFinishObserver : public content::WebContentsObserver {
75  public:
76   explicit TestFinishObserver(content::WebContents* web_contents)
77       : content::WebContentsObserver(web_contents),
78         finished_(false),
79         waiting_(false) {}
80
81   TestFinishObserver(const TestFinishObserver&) = delete;
82   TestFinishObserver& operator=(const TestFinishObserver&) = delete;
83
84   bool WaitForFinish() {
85     if (!finished_) {
86       waiting_ = true;
87       content::RunMessageLoop();
88       waiting_ = false;
89     }
90     return finished_;
91   }
92
93   void DomOperationResponse(content::RenderFrameHost* render_frame_host,
94                             const std::string& dom_op_result) override {
95     // We might receive responses for other script execution, but we only
96     // care about the test finished message.
97     if (dom_op_result == "\"FINISHED\"") {
98       finished_ = true;
99       if (waiting_)
100         base::RunLoop::QuitCurrentWhenIdleDeprecated();
101     }
102   }
103
104  private:
105   bool finished_;
106   bool waiting_;
107 };
108
109 class BrowserKeyEventsTest : public InProcessBrowserTest {
110  public:
111   BrowserKeyEventsTest() {}
112
113   void SetUpCommandLine(base::CommandLine* command_line) override {
114     // Some builders are flaky due to slower loading interacting with
115     // deferred commits.
116     command_line->AppendSwitch(blink::switches::kAllowPreCommitInput);
117   }
118
119   bool IsViewFocused(ViewID vid) {
120     return ui_test_utils::IsViewFocused(browser(), vid);
121   }
122
123   void ClickOnView(ViewID vid) {
124     ui_test_utils::ClickOnView(browser(), vid);
125   }
126
127   // Set the suppress flag of an event specified by |type|. If |suppress| is
128   // true then the web page will suppress all events with |type|. Following
129   // event types are supported: keydown, keypress, keyup and textInput.
130   void SuppressEventByType(int tab_index, const char* type, bool suppress) {
131     ASSERT_LT(tab_index, browser()->tab_strip_model()->count());
132     ASSERT_EQ(!suppress,
133               content::EvalJs(
134                   browser()->tab_strip_model()->GetWebContentsAt(tab_index),
135                   base::StringPrintf(kSuppressEventJS, type,
136                                      suppress ? "false" : "true")));
137   }
138
139   void SuppressEvents(int tab_index, bool keydown, bool keypress,
140                       bool keyup, bool textinput) {
141     ASSERT_NO_FATAL_FAILURE(SuppressEventByType(tab_index, "keydown", keydown));
142     ASSERT_NO_FATAL_FAILURE(
143         SuppressEventByType(tab_index, "keypress", keypress));
144     ASSERT_NO_FATAL_FAILURE(SuppressEventByType(tab_index, "keyup", keyup));
145     ASSERT_NO_FATAL_FAILURE(
146         SuppressEventByType(tab_index, "textInput", textinput));
147   }
148
149   void SuppressAllEvents(int tab_index, bool suppress) {
150     SuppressEvents(tab_index, suppress, suppress, suppress, suppress);
151   }
152
153   int GetResultLength(int tab_index) {
154     CHECK_LT(tab_index, browser()->tab_strip_model()->count());
155     return content::EvalJs(
156                browser()->tab_strip_model()->GetWebContentsAt(tab_index),
157                kGetResultLengthJS)
158         .ExtractInt();
159   }
160
161   void CheckResult(int tab_index, int length, const char* const result[]) {
162     ASSERT_LT(tab_index, browser()->tab_strip_model()->count());
163     int actual_length = GetResultLength(tab_index);
164     ASSERT_GE(actual_length, length);
165     for (int i = 0; i < actual_length; ++i) {
166       std::string actual =
167           content::EvalJs(
168               browser()->tab_strip_model()->GetWebContentsAt(tab_index),
169               base::StringPrintf(kGetResultJS, i))
170               .ExtractString();
171
172       // If more events were received than expected, then the additional events
173       // must be keyup events.
174       if (i < length)
175         ASSERT_STREQ(result[i], actual.c_str());
176       else
177         ASSERT_EQ('U', actual[0]);
178     }
179   }
180
181   void CheckFocusedElement(int tab_index, const char* focused) {
182     ASSERT_LT(tab_index, browser()->tab_strip_model()->count());
183     ASSERT_EQ(focused,
184               content::EvalJs(
185                   browser()->tab_strip_model()->GetWebContentsAt(tab_index),
186                   kGetFocusedElementJS));
187   }
188
189   void SetFocusedElement(int tab_index, const char* focused) {
190     ASSERT_LT(tab_index, browser()->tab_strip_model()->count());
191     ASSERT_EQ(true,
192               content::EvalJs(
193                   browser()->tab_strip_model()->GetWebContentsAt(tab_index),
194                   base::StringPrintf(kSetFocusedElementJS, focused)));
195   }
196
197   void CheckTextBoxValue(int tab_index, const char* id, const char* value) {
198     ASSERT_LT(tab_index, browser()->tab_strip_model()->count());
199     ASSERT_EQ(value,
200               content::EvalJs(
201                   browser()->tab_strip_model()->GetWebContentsAt(tab_index),
202                   base::StringPrintf(kGetTextBoxValueJS, id)));
203   }
204
205   void SetTextBoxValue(int tab_index, const char* id, const char* value) {
206     ASSERT_LT(tab_index, browser()->tab_strip_model()->count());
207     ASSERT_EQ(value,
208               content::EvalJs(
209                   browser()->tab_strip_model()->GetWebContentsAt(tab_index),
210                   base::StringPrintf(kSetTextBoxValueJS, id, value)));
211   }
212
213   void StartTest(int tab_index, int result_length) {
214     ASSERT_LT(tab_index, browser()->tab_strip_model()->count());
215     ASSERT_EQ(true,
216               content::EvalJs(
217                   browser()->tab_strip_model()->GetWebContentsAt(tab_index),
218                   base::StringPrintf(kStartTestJS, result_length)));
219   }
220
221   void TestKeyEvent(int tab_index, const KeyEventTestData& test) {
222     ASSERT_LT(tab_index, browser()->tab_strip_model()->count());
223     ASSERT_EQ(tab_index, browser()->tab_strip_model()->active_index());
224
225     // Inform our testing web page that we are about to start testing a key
226     // event.
227     ASSERT_NO_FATAL_FAILURE(StartTest(tab_index, test.result_length));
228     ASSERT_NO_FATAL_FAILURE(SuppressEvents(
229         tab_index, test.suppress_keydown, test.suppress_keypress,
230         test.suppress_keyup, test.suppress_textinput));
231
232     // We need to create a finish observer before sending the key event,
233     // because the test finished message might be arrived before returning
234     // from the SendKeyPressSync() method.
235     TestFinishObserver finish_observer(
236         browser()->tab_strip_model()->GetWebContentsAt(tab_index));
237
238     ASSERT_TRUE(ui_test_utils::SendKeyPressSync(
239         browser(), test.key, test.ctrl, test.shift, test.alt, test.command));
240     ASSERT_TRUE(finish_observer.WaitForFinish());
241     ASSERT_NO_FATAL_FAILURE(CheckResult(
242         tab_index, test.result_length, test.result));
243   }
244
245   std::string GetTestDataDescription(const KeyEventTestData& data) {
246     std::string desc = base::StringPrintf(
247         " VKEY:0x%02x, ctrl:%d, shift:%d, alt:%d, command:%d\n"
248         " Suppress: keydown:%d, keypress:%d, keyup:%d, textInput:%d\n"
249         " Expected results(%d):\n",
250         data.key, data.ctrl, data.shift, data.alt, data.command,
251         data.suppress_keydown, data.suppress_keypress, data.suppress_keyup,
252         data.suppress_textinput, data.result_length);
253     for (int i = 0; i < data.result_length; ++i) {
254       desc.append("  ");
255       desc.append(data.result[i]);
256       desc.append("\n");
257     }
258     return desc;
259   }
260 };
261
262 // TODO(crbug.com/1338416): Re-enable this test
263 IN_PROC_BROWSER_TEST_F(BrowserKeyEventsTest, DISABLED_NormalKeyEvents) {
264   static const KeyEventTestData kTestNoInput[] = {
265     // a
266     { ui::VKEY_A, false, false, false, false,
267       false, false, false, false, 3,
268       { "D 65 0 false false false false",
269         "P 97 97 false false false false",
270         "U 65 0 false false false false" } },
271     // shift-a
272     { ui::VKEY_A, false, true, false, false,
273       false, false, false, false, 5,
274       { "D 16 0 false true false false",
275         "D 65 0 false true false false",
276         "P 65 65 false true false false",
277         "U 65 0 false true false false",
278         "U 16 0 false true false false" } },
279     // a, suppress keydown
280     { ui::VKEY_A, false, false, false, false,
281       true, false, false, false, 2,
282       { "D 65 0 false false false false",
283         "U 65 0 false false false false" } },
284   };
285
286   static const KeyEventTestData kTestWithInput[] = {
287     // a
288     { ui::VKEY_A, false, false, false, false,
289       false, false, false, false, 4,
290       { "D 65 0 false false false false",
291         "P 97 97 false false false false",
292         "T a",
293         "U 65 0 false false false false" } },
294     // shift-a
295     { ui::VKEY_A, false, true, false, false,
296       false, false, false, false, 6,
297       { "D 16 0 false true false false",
298         "D 65 0 false true false false",
299         "P 65 65 false true false false",
300         "T A",
301         "U 65 0 false true false false",
302         "U 16 0 false true false false" } },
303     // a, suppress keydown
304     { ui::VKEY_A, false, false, false, false,
305       true, false, false, false, 2,
306       { "D 65 0 false false false false",
307         "U 65 0 false false false false" } },
308     // a, suppress keypress
309     { ui::VKEY_A, false, false, false, false,
310       false, true, false, false, 3,
311       { "D 65 0 false false false false",
312         "P 97 97 false false false false",
313         "U 65 0 false false false false" } },
314     // a, suppress textInput
315     { ui::VKEY_A, false, false, false, false,
316       false, false, false, true, 4,
317       { "D 65 0 false false false false",
318         "P 97 97 false false false false",
319         "T a",
320         "U 65 0 false false false false" } },
321   };
322
323   ASSERT_TRUE(embedded_test_server()->Start());
324
325   ASSERT_TRUE(ui_test_utils::BringBrowserWindowToFront(browser()));
326   GURL url = embedded_test_server()->GetURL(kTestingPage);
327   ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), url));
328
329   ASSERT_NO_FATAL_FAILURE(ClickOnView(VIEW_ID_TAB_CONTAINER));
330   ASSERT_TRUE(IsViewFocused(VIEW_ID_TAB_CONTAINER));
331
332   int tab_index = browser()->tab_strip_model()->active_index();
333   for (size_t i = 0; i < std::size(kTestNoInput); ++i) {
334     EXPECT_NO_FATAL_FAILURE(TestKeyEvent(tab_index, kTestNoInput[i]))
335         << "kTestNoInput[" << i << "] failed:\n"
336         << GetTestDataDescription(kTestNoInput[i]);
337   }
338
339   // Input in normal text box.
340   ASSERT_NO_FATAL_FAILURE(SetFocusedElement(tab_index, "A"));
341   for (size_t i = 0; i < std::size(kTestWithInput); ++i) {
342     EXPECT_NO_FATAL_FAILURE(TestKeyEvent(tab_index, kTestWithInput[i]))
343         << "kTestWithInput[" << i << "] in text box failed:\n"
344         << GetTestDataDescription(kTestWithInput[i]);
345   }
346   EXPECT_NO_FATAL_FAILURE(CheckTextBoxValue(tab_index, "A", "aA"));
347
348   // Input in password box.
349   ASSERT_NO_FATAL_FAILURE(SetFocusedElement(tab_index, "B"));
350   for (size_t i = 0; i < std::size(kTestWithInput); ++i) {
351     EXPECT_NO_FATAL_FAILURE(TestKeyEvent(tab_index, kTestWithInput[i]))
352         << "kTestWithInput[" << i << "] in password box failed:\n"
353         << GetTestDataDescription(kTestWithInput[i]);
354   }
355   EXPECT_NO_FATAL_FAILURE(CheckTextBoxValue(tab_index, "B", "aA"));
356 }
357
358 #if BUILDFLAG(IS_WIN) || BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS)
359
360 IN_PROC_BROWSER_TEST_F(BrowserKeyEventsTest, CtrlKeyEvents) {
361   static const KeyEventTestData kTestCtrlF = {
362     ui::VKEY_F, true, false, false, false,
363     false, false, false, false, 2,
364     { "D 17 0 true false false false",
365       "D 70 0 true false false false" }
366   };
367
368   static const KeyEventTestData kTestCtrlFSuppressKeyDown = {
369     ui::VKEY_F, true, false, false, false,
370     true, false, false, false, 4,
371     { "D 17 0 true false false false",
372       "D 70 0 true false false false",
373       "U 70 0 true false false false",
374       "U 17 0 true false false false" }
375   };
376
377   // Ctrl+Z doesn't bind to any accelerators, which then should generate a
378   // keypress event with charCode=26.
379   static const KeyEventTestData kTestCtrlZ = {
380     ui::VKEY_Z, true, false, false, false,
381     false, false, false, false, 5,
382     { "D 17 0 true false false false",
383       "D 90 0 true false false false",
384       "P 26 26 true false false false",
385       "U 90 0 true false false false",
386       "U 17 0 true false false false" }
387   };
388
389   static const KeyEventTestData kTestCtrlZSuppressKeyDown = {
390     ui::VKEY_Z, true, false, false, false,
391     true, false, false, false, 4,
392     { "D 17 0 true false false false",
393       "D 90 0 true false false false",
394       "U 90 0 true false false false",
395       "U 17 0 true false false false" }
396   };
397
398   // Ctrl+Enter shall generate a keypress event with charCode=10 (LF).
399   static const KeyEventTestData kTestCtrlEnter = {
400     ui::VKEY_RETURN, true, false, false, false,
401     false, false, false, false, 5,
402     { "D 17 0 true false false false",
403       "D 13 0 true false false false",
404       "P 10 10 true false false false",
405       "U 13 0 true false false false",
406       "U 17 0 true false false false" }
407   };
408
409   static const KeyEventTestData kTestEscape = {
410       ui::VKEY_ESCAPE, false, false, false, false, false,
411       false,           false, false, 0,     {}};
412
413   ASSERT_TRUE(embedded_test_server()->Start());
414
415   ASSERT_TRUE(ui_test_utils::BringBrowserWindowToFront(browser()));
416   GURL url = embedded_test_server()->GetURL(kTestingPage);
417   ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), url));
418
419   ASSERT_NO_FATAL_FAILURE(ClickOnView(VIEW_ID_TAB_CONTAINER));
420   ASSERT_TRUE(IsViewFocused(VIEW_ID_TAB_CONTAINER));
421
422   int tab_index = browser()->tab_strip_model()->active_index();
423   // Press Ctrl+F, which will make the Find box open and request focus.
424   EXPECT_NO_FATAL_FAILURE(TestKeyEvent(tab_index, kTestCtrlF));
425   EXPECT_TRUE(IsViewFocused(VIEW_ID_FIND_IN_PAGE_TEXT_FIELD));
426
427   // Press Escape to close the Find box and move the focus back to the web page.
428   EXPECT_NO_FATAL_FAILURE(TestKeyEvent(tab_index, kTestEscape));
429   ASSERT_TRUE(IsViewFocused(VIEW_ID_TAB_CONTAINER));
430
431   // Press Ctrl+F with keydown suppressed shall not open the find box.
432   EXPECT_NO_FATAL_FAILURE(TestKeyEvent(tab_index, kTestCtrlFSuppressKeyDown));
433   ASSERT_TRUE(IsViewFocused(VIEW_ID_TAB_CONTAINER));
434
435   EXPECT_NO_FATAL_FAILURE(TestKeyEvent(tab_index, kTestCtrlZ));
436   EXPECT_NO_FATAL_FAILURE(TestKeyEvent(tab_index, kTestCtrlZSuppressKeyDown));
437   EXPECT_NO_FATAL_FAILURE(TestKeyEvent(tab_index, kTestCtrlEnter));
438 }
439 #elif BUILDFLAG(IS_MAC)
440 // http://crbug.com/81451
441 IN_PROC_BROWSER_TEST_F(BrowserKeyEventsTest, CommandKeyEvents) {
442   static const KeyEventTestData kTestCmdF = {
443     ui::VKEY_F, false, false, false, true,
444     false, false, false, false, 2,
445     { "D 91 0 false false false true",
446       "D 70 0 false false false true" }
447   };
448
449   // On Mac we don't send key up events when command modifier is down.
450   static const KeyEventTestData kTestCmdFSuppressKeyDown = {
451     ui::VKEY_F, false, false, false, true,
452     true, false, false, false, 3,
453     { "D 91 0 false false false true",
454       "D 70 0 false false false true",
455       "U 91 0 false false false true" }
456   };
457
458   ASSERT_TRUE(embedded_test_server()->Start());
459
460   ASSERT_TRUE(ui_test_utils::BringBrowserWindowToFront(browser()));
461   GURL url = embedded_test_server()->GetURL(kTestingPage);
462   ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), url));
463
464   ASSERT_NO_FATAL_FAILURE(ClickOnView(VIEW_ID_TAB_CONTAINER));
465   ASSERT_TRUE(IsViewFocused(VIEW_ID_TAB_CONTAINER));
466
467   int tab_index = browser()->tab_strip_model()->active_index();
468   // Press Cmd+F, which will make the Find box open and request focus.
469   EXPECT_NO_FATAL_FAILURE(TestKeyEvent(tab_index, kTestCmdF));
470   EXPECT_TRUE(IsViewFocused(VIEW_ID_FIND_IN_PAGE_TEXT_FIELD));
471
472   // Press Escape to close the Find box and move the focus back to the web page.
473   ASSERT_TRUE(ui_test_utils::SendKeyPressSync(
474       browser(), ui::VKEY_ESCAPE, false, false, false, false));
475   ASSERT_TRUE(IsViewFocused(VIEW_ID_TAB_CONTAINER));
476
477   // Press Cmd+F with keydown suppressed shall not open the find box.
478   EXPECT_NO_FATAL_FAILURE(TestKeyEvent(tab_index, kTestCmdFSuppressKeyDown));
479   ASSERT_TRUE(IsViewFocused(VIEW_ID_TAB_CONTAINER));
480 }
481 #endif
482
483 // https://crbug.com/81451 for mac
484 // https://crbug.com/1249688 for Lacros
485 #if BUILDFLAG(IS_MAC) || BUILDFLAG(IS_CHROMEOS_LACROS)
486 #define MAYBE_AccessKeys DISABLED_AccessKeys
487 #else
488 #define MAYBE_AccessKeys AccessKeys
489 #endif
490 IN_PROC_BROWSER_TEST_F(BrowserKeyEventsTest, MAYBE_AccessKeys) {
491 #if BUILDFLAG(IS_MAC)
492   // On Mac, access keys use ctrl+alt modifiers.
493   static const KeyEventTestData kTestAccessA = {
494     ui::VKEY_A, true, false, true, false,
495     false, false, false, false, 6,
496     { "D 17 0 true false false false",
497       "D 18 0 true false true false",
498       "D 65 0 true false true false",
499       "U 65 0 true false true false",
500       "U 18 0 true false true false",
501       "U 17 0 true false false false" }
502   };
503
504   static const KeyEventTestData kTestAccessDSuppress = {
505     ui::VKEY_D, true, false, true, false,
506     true, true, true, false, 6,
507     { "D 17 0 true false false false",
508       "D 18 0 true false true false",
509       "D 68 0 true false true false",
510       "U 68 0 true false true false",
511       "U 18 0 true false true false",
512       "U 17 0 true false false false" }
513   };
514 #else
515   static const KeyEventTestData kTestAccessA = {
516     ui::VKEY_A, false, false, true, false,
517     false, false, false, false, 4,
518     { "D 18 0 false false true false",
519       "D 65 0 false false true false",
520       "U 65 0 false false true false",
521       "U 18 0 false false true false" }
522   };
523
524   static const KeyEventTestData kTestAccessD = {
525     ui::VKEY_D, false, false, true, false,
526     false, false, false, false, 2,
527     { "D 18 0 false false true false",
528       "D 68 0 false false true false" }
529   };
530
531   static const KeyEventTestData kTestAccessDSuppress = {
532     ui::VKEY_D, false, false, true, false,
533     true, true, true, false, 4,
534     { "D 18 0 false false true false",
535       "D 68 0 false false true false",
536       "U 68 0 false false true false",
537       "U 18 0 false false true false" }
538   };
539
540 #endif
541
542   ASSERT_TRUE(embedded_test_server()->Start());
543
544   ASSERT_TRUE(ui_test_utils::BringBrowserWindowToFront(browser()));
545   GURL url = embedded_test_server()->GetURL(kTestingPage);
546   ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), url));
547
548   content::RunAllPendingInMessageLoop();
549   ASSERT_NO_FATAL_FAILURE(ClickOnView(VIEW_ID_TAB_CONTAINER));
550   ASSERT_TRUE(IsViewFocused(VIEW_ID_TAB_CONTAINER));
551
552   int tab_index = browser()->tab_strip_model()->active_index();
553   // Make sure no element is focused.
554   EXPECT_NO_FATAL_FAILURE(CheckFocusedElement(tab_index, ""));
555   // Alt+A should focus the element with accesskey = "A".
556   EXPECT_NO_FATAL_FAILURE(TestKeyEvent(tab_index, kTestAccessA));
557   EXPECT_NO_FATAL_FAILURE(CheckFocusedElement(tab_index, "A"));
558
559   // Blur the focused element.
560   EXPECT_NO_FATAL_FAILURE(SetFocusedElement(tab_index, ""));
561   // Make sure no element is focused.
562   EXPECT_NO_FATAL_FAILURE(CheckFocusedElement(tab_index, ""));
563
564 #if !BUILDFLAG(IS_MAC)
565   // Alt+D should move the focus to the location entry.
566   EXPECT_NO_FATAL_FAILURE(TestKeyEvent(tab_index, kTestAccessD));
567
568   // TODO(isherman): This is an experimental change to help diagnose
569   // http://crbug.com/55713
570   content::RunAllPendingInMessageLoop();
571   EXPECT_TRUE(IsViewFocused(VIEW_ID_OMNIBOX));
572   // No element should be focused, as Alt+D was handled by the browser.
573   EXPECT_NO_FATAL_FAILURE(CheckFocusedElement(tab_index, ""));
574
575   // Move the focus back to the web page.
576   ASSERT_NO_FATAL_FAILURE(ClickOnView(VIEW_ID_TAB_CONTAINER));
577   ASSERT_TRUE(IsViewFocused(VIEW_ID_TAB_CONTAINER));
578
579   // Make sure no element is focused.
580   EXPECT_NO_FATAL_FAILURE(CheckFocusedElement(tab_index, ""));
581 #endif
582
583   // If the keydown event is suppressed, then Alt+D should be handled as an
584   // accesskey rather than an accelerator key. Activation of an accesskey is not
585   // a part of the default action of the key event, so it should not be
586   // suppressed at all.
587   EXPECT_NO_FATAL_FAILURE(TestKeyEvent(tab_index, kTestAccessDSuppress));
588   ASSERT_TRUE(IsViewFocused(VIEW_ID_TAB_CONTAINER));
589   EXPECT_NO_FATAL_FAILURE(CheckFocusedElement(tab_index, "D"));
590
591   // Blur the focused element.
592   EXPECT_NO_FATAL_FAILURE(SetFocusedElement(tab_index, ""));
593   // Make sure no element is focused.
594   EXPECT_NO_FATAL_FAILURE(CheckFocusedElement(tab_index, ""));
595 }
596
597 IN_PROC_BROWSER_TEST_F(BrowserKeyEventsTest, ReservedAccelerators) {
598   ASSERT_TRUE(embedded_test_server()->Start());
599
600   ASSERT_TRUE(ui_test_utils::BringBrowserWindowToFront(browser()));
601   GURL url = embedded_test_server()->GetURL(kTestingPage);
602   ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), url));
603
604   ASSERT_NO_FATAL_FAILURE(ClickOnView(VIEW_ID_TAB_CONTAINER));
605   ASSERT_TRUE(IsViewFocused(VIEW_ID_TAB_CONTAINER));
606
607   ASSERT_EQ(1, browser()->tab_strip_model()->count());
608
609   static const KeyEventTestData kTestCtrlOrCmdT = {
610 #if BUILDFLAG(IS_MAC)
611     ui::VKEY_T,
612     false,
613     false,
614     false,
615     true,
616     true,
617     false,
618     false,
619     false,
620     1,
621     {"D 91 0 false false false true"}
622 #else
623     ui::VKEY_T, true, false, false, false,
624     true, false, false, false, 1,
625     { "D 17 0 true false false false" }
626 #endif
627   };
628
629   ui_test_utils::TabAddedWaiter wait_for_new_tab(browser());
630
631   // Press Ctrl/Cmd+T, which will open a new tab. It cannot be suppressed.
632   EXPECT_NO_FATAL_FAILURE(TestKeyEvent(0, kTestCtrlOrCmdT));
633   wait_for_new_tab.Wait();
634
635   EXPECT_EQ(1, GetResultLength(0));
636
637   EXPECT_EQ(2, browser()->tab_strip_model()->count());
638   ASSERT_EQ(1, browser()->tab_strip_model()->active_index());
639
640   // Because of issue <http://crbug.com/65375>, switching back to the first tab
641   // may cause the focus to be grabbed by omnibox. So instead, we load our
642   // testing page in the newly created tab and try Cmd-W here.
643   ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), url));
644
645   // Make sure the focus is in the testing page.
646   ASSERT_NO_FATAL_FAILURE(ClickOnView(VIEW_ID_TAB_CONTAINER));
647   ASSERT_TRUE(IsViewFocused(VIEW_ID_TAB_CONTAINER));
648
649   // Reserved accelerators can't be suppressed.
650   ASSERT_NO_FATAL_FAILURE(SuppressAllEvents(1, true));
651
652   content::WebContentsDestroyedWatcher destroyed_watcher(
653       browser()->tab_strip_model()->GetWebContentsAt(1));
654
655   // Press Ctrl/Cmd+W, which will close the tab.
656 #if BUILDFLAG(IS_MAC)
657   ASSERT_TRUE(ui_test_utils::SendKeyPressSync(
658       browser(), ui::VKEY_W, false, false, false, true));
659 #else
660   ASSERT_TRUE(ui_test_utils::SendKeyPressSync(
661       browser(), ui::VKEY_W, true, false, false, false));
662 #endif
663
664   ASSERT_NO_FATAL_FAILURE(destroyed_watcher.Wait());
665
666   EXPECT_EQ(1, browser()->tab_strip_model()->count());
667 }
668
669 #if BUILDFLAG(IS_MAC)
670 IN_PROC_BROWSER_TEST_F(BrowserKeyEventsTest, EditorKeyBindings) {
671   static const KeyEventTestData kTestCtrlA = {
672     ui::VKEY_A, true, false, false, false,
673     false, false, false, false, 4,
674     { "D 17 0 true false false false",
675       "D 65 0 true false false false",
676       "U 65 0 true false false false",
677       "U 17 0 true false false false" }
678   };
679
680   static const KeyEventTestData kTestCtrlF = {
681     ui::VKEY_F, true, false, false, false,
682     false, false, false, false, 4,
683     { "D 17 0 true false false false",
684       "D 70 0 true false false false",
685       "U 70 0 true false false false",
686       "U 17 0 true false false false" }
687   };
688
689   static const KeyEventTestData kTestCtrlK = {
690     ui::VKEY_K, true, false, false, false,
691     false, false, false, false, 4,
692     { "D 17 0 true false false false",
693       "D 75 0 true false false false",
694       "U 75 0 true false false false",
695       "U 17 0 true false false false" }
696   };
697
698   ASSERT_TRUE(embedded_test_server()->Start());
699
700   ASSERT_TRUE(ui_test_utils::BringBrowserWindowToFront(browser()));
701   GURL url = embedded_test_server()->GetURL(kTestingPage);
702   ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), url));
703
704   ASSERT_NO_FATAL_FAILURE(ClickOnView(VIEW_ID_TAB_CONTAINER));
705   ASSERT_TRUE(IsViewFocused(VIEW_ID_TAB_CONTAINER));
706
707   int tab_index = browser()->tab_strip_model()->active_index();
708   ASSERT_NO_FATAL_FAILURE(SetFocusedElement(tab_index, "A"));
709   ASSERT_NO_FATAL_FAILURE(SetTextBoxValue(tab_index, "A", "Hello"));
710   // Move the caret to the beginning of the line.
711   EXPECT_NO_FATAL_FAILURE(TestKeyEvent(tab_index, kTestCtrlA));
712   // Forward one character
713   EXPECT_NO_FATAL_FAILURE(TestKeyEvent(tab_index, kTestCtrlF));
714   // Delete to the end of the line.
715   EXPECT_NO_FATAL_FAILURE(TestKeyEvent(tab_index, kTestCtrlK));
716   EXPECT_NO_FATAL_FAILURE(CheckTextBoxValue(tab_index, "A", "H"));
717 }
718 #endif
719
720 IN_PROC_BROWSER_TEST_F(BrowserKeyEventsTest, PageUpDownKeys) {
721   static const KeyEventTestData kTestPageUp = {
722     ui::VKEY_PRIOR, false, false, false, false,
723     false, false, false, false, 2,
724     { "D 33 0 false false false false",
725       "U 33 0 false false false false" }
726   };
727
728   static const KeyEventTestData kTestPageDown = {
729     ui::VKEY_NEXT, false, false, false, false,
730     false, false, false, false, 2,
731     { "D 34 0 false false false false",
732       "U 34 0 false false false false" }
733   };
734
735   ASSERT_TRUE(embedded_test_server()->Start());
736
737   ASSERT_TRUE(ui_test_utils::BringBrowserWindowToFront(browser()));
738   GURL url = embedded_test_server()->GetURL(kTestingPage);
739   ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), url));
740
741   ASSERT_NO_FATAL_FAILURE(ClickOnView(VIEW_ID_TAB_CONTAINER));
742   ASSERT_TRUE(IsViewFocused(VIEW_ID_TAB_CONTAINER));
743
744   int tab_index = browser()->tab_strip_model()->active_index();
745   ASSERT_NO_FATAL_FAILURE(SetFocusedElement(tab_index, "A"));
746   EXPECT_NO_FATAL_FAILURE(TestKeyEvent(tab_index, kTestPageUp));
747   EXPECT_NO_FATAL_FAILURE(TestKeyEvent(tab_index, kTestPageDown));
748   EXPECT_NO_FATAL_FAILURE(CheckTextBoxValue(tab_index, "A", ""));
749 }
750
751 // AltKey is enabled only on Windows. See crbug.com/114537.
752 #if BUILDFLAG(IS_WIN)
753 // If this flakes, disable and log details in http://crbug.com/523255.
754 // TODO(sky): remove comment if proves stable and reenable other tests.
755 IN_PROC_BROWSER_TEST_F(BrowserKeyEventsTest, FocusMenuBarByAltKey) {
756   static const KeyEventTestData kTestAltKey = {
757     ui::VKEY_MENU, false, false, false, false,
758     false, false, false, false, 2,
759     { "D 18 0 false false true false",
760       "U 18 0 false false true false" }
761   };
762
763   static const KeyEventTestData kTestAltKeySuppress = {
764     ui::VKEY_MENU, false, false, false, false,
765     true, false, false, false, 2,
766     { "D 18 0 false false true false",
767       "U 18 0 false false true false" }
768   };
769
770   static const KeyEventTestData kTestCtrlAltKey = {
771     ui::VKEY_MENU, true, false, false, false,
772     false, false, false, false, 4,
773     { "D 17 0 true false false false",
774       "D 18 0 true false true false",
775       "U 18 0 true false true false",
776       "U 17 0 true false false false" }
777   };
778
779   ASSERT_TRUE(embedded_test_server()->Start());
780
781   ASSERT_TRUE(ui_test_utils::BringBrowserWindowToFront(browser()));
782   GURL url = embedded_test_server()->GetURL(kTestingPage);
783   ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), url));
784
785   ASSERT_NO_FATAL_FAILURE(ClickOnView(VIEW_ID_TAB_CONTAINER));
786   ASSERT_TRUE(IsViewFocused(VIEW_ID_TAB_CONTAINER));
787
788   int tab_index = browser()->tab_strip_model()->active_index();
789   // Press and release Alt key to focus wrench menu button.
790   EXPECT_NO_FATAL_FAILURE(TestKeyEvent(tab_index, kTestAltKey));
791   EXPECT_TRUE(IsViewFocused(VIEW_ID_APP_MENU));
792
793   ASSERT_NO_FATAL_FAILURE(ClickOnView(VIEW_ID_TAB_CONTAINER));
794   ASSERT_TRUE(IsViewFocused(VIEW_ID_TAB_CONTAINER));
795
796   // Alt key can be suppressed.
797   EXPECT_NO_FATAL_FAILURE(TestKeyEvent(tab_index, kTestAltKeySuppress));
798   ASSERT_TRUE(IsViewFocused(VIEW_ID_TAB_CONTAINER));
799
800   // Ctrl+Alt should have no effect.
801   EXPECT_NO_FATAL_FAILURE(TestKeyEvent(tab_index, kTestCtrlAltKey));
802   ASSERT_TRUE(IsViewFocused(VIEW_ID_TAB_CONTAINER));
803 }
804 #endif
805
806 }  // namespace