browser_keyevents_browsertest.cc revision a93a17c8d99d686bd4a1511e5504e5e6cc9fcadf
1// 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" 9#include "base/message_loop.h" 10#include "base/stringprintf.h" 11#include "base/utf_string_conversions.h" 12#include "base/values.h" 13#include "chrome/browser/ui/browser.h" 14#include "chrome/browser/ui/tabs/tab_strip_model.h" 15#include "chrome/common/chrome_notification_types.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/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" 28#include "net/test/spawned_test_server/spawned_test_server.h" 29#include "ui/base/keycodes/keyboard_codes.h" 30#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 36 37using content::DomOperationNotificationDetails; 38using content::NavigationController; 39using content::RenderViewHost; 40 41namespace { 42 43const char kTestingPage[] = "files/keyevents_test.html"; 44const 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));"; 62 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, 117 const content::NotificationDetails& details) OVERRIDE { 118 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_) 125 MessageLoopForUI::current()->Quit(); 126 } 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) { 153 ASSERT_LT(tab_index, browser()->tab_strip_model()->count()); 154 bool actual; 155 ASSERT_TRUE(content::ExecuteScriptAndExtractBool( 156 browser()->tab_strip_model()->GetWebContentsAt(tab_index), 157 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) { 179 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)); 184 } 185 186 void CheckResult(int tab_index, int length, const char* const result[]) { 187 ASSERT_LT(tab_index, browser()->tab_strip_model()->count()); 188 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; 193 ASSERT_TRUE(content::ExecuteScriptAndExtractString( 194 browser()->tab_strip_model()->GetWebContentsAt(tab_index), 195 base::StringPrintf(kGetResultJS, i), 196 &actual)); 197 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) { 208 ASSERT_LT(tab_index, browser()->tab_strip_model()->count()); 209 std::string actual; 210 ASSERT_TRUE(content::ExecuteScriptAndExtractString( 211 browser()->tab_strip_model()->GetWebContentsAt(tab_index), 212 kGetFocusedElementJS, 213 &actual)); 214 ASSERT_EQ(WideToUTF8(focused), actual); 215 } 216 217 void SetFocusedElement(int tab_index, const wchar_t* focused) { 218 ASSERT_LT(tab_index, browser()->tab_strip_model()->count()); 219 bool actual; 220 ASSERT_TRUE(content::ExecuteScriptAndExtractBool( 221 browser()->tab_strip_model()->GetWebContentsAt(tab_index), 222 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) { 229 ASSERT_LT(tab_index, browser()->tab_strip_model()->count()); 230 std::string actual; 231 ASSERT_TRUE(content::ExecuteScriptAndExtractString( 232 browser()->tab_strip_model()->GetWebContentsAt(tab_index), 233 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) { 240 ASSERT_LT(tab_index, browser()->tab_strip_model()->count()); 241 std::string actual; 242 ASSERT_TRUE(content::ExecuteScriptAndExtractString( 243 browser()->tab_strip_model()->GetWebContentsAt(tab_index), 244 base::StringPrintf(kSetTextBoxValueJS, id, value), 245 &actual)); 246 ASSERT_EQ(WideToUTF8(value), actual); 247 } 248 249 void StartTest(int tab_index, int result_length) { 250 ASSERT_LT(tab_index, browser()->tab_strip_model()->count()); 251 bool actual; 252 ASSERT_TRUE(content::ExecuteScriptAndExtractBool( 253 browser()->tab_strip_model()->GetWebContentsAt(tab_index), 254 base::StringPrintf(kStartTestJS, result_length), 255 &actual)); 256 ASSERT_TRUE(actual); 257 } 258 259 void TestKeyEvent(int tab_index, const KeyEventTestData& test) { 260 ASSERT_LT(tab_index, browser()->tab_strip_model()->count()); 261 ASSERT_EQ(tab_index, browser()->tab_strip_model()->active_index()); 262 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( 274 browser()->tab_strip_model()->GetWebContentsAt(tab_index)-> 275 GetRenderViewHost()); 276 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 371 ASSERT_TRUE(test_server()->Start()); 372 373 ASSERT_TRUE(ui_test_utils::BringBrowserWindowToFront(browser())); 374 GURL url = test_server()->GetURL(kTestingPage); 375 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 380 int tab_index = browser()->tab_strip_model()->active_index(); 381 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 408#if defined(OS_LINUX) 409// http://crbug.com/129235 410#define MAYBE_CtrlKeyEvents DISABLED_CtrlKeyEvents 411#else 412#define MAYBE_CtrlKeyEvents CtrlKeyEvents 413#endif 414 415IN_PROC_BROWSER_TEST_F(BrowserKeyEventsTest, MAYBE_CtrlKeyEvents) { 416 static const KeyEventTestData kTestCtrlF = { 417 ui::VKEY_F, true, false, false, false, 418 false, false, false, false, 2, 419 { "D 17 0 true false false false", 420 "D 70 0 true false false false" } 421 }; 422 423 static const KeyEventTestData kTestCtrlFSuppressKeyDown = { 424 ui::VKEY_F, true, false, false, false, 425 true, false, false, false, 4, 426 { "D 17 0 true false false false", 427 "D 70 0 true false false false", 428 "U 70 0 true false false false", 429 "U 17 0 true false false false" } 430 }; 431 432 // Ctrl+Z doesn't bind to any accelerators, which then should generate a 433 // keypress event with charCode=26. 434 static const KeyEventTestData kTestCtrlZ = { 435 ui::VKEY_Z, true, false, false, false, 436 false, false, false, false, 5, 437 { "D 17 0 true false false false", 438 "D 90 0 true false false false", 439 "P 26 26 true false false false", 440 "U 90 0 true false false false", 441 "U 17 0 true false false false" } 442 }; 443 444 static const KeyEventTestData kTestCtrlZSuppressKeyDown = { 445 ui::VKEY_Z, true, false, false, false, 446 true, false, false, false, 4, 447 { "D 17 0 true false false false", 448 "D 90 0 true false false false", 449 "U 90 0 true false false false", 450 "U 17 0 true false false false" } 451 }; 452 453 // Ctrl+Enter shall generate a keypress event with charCode=10 (LF). 454 static const KeyEventTestData kTestCtrlEnter = { 455 ui::VKEY_RETURN, true, false, false, false, 456 false, false, false, false, 5, 457 { "D 17 0 true false false false", 458 "D 13 0 true false false false", 459 "P 10 10 true false false false", 460 "U 13 0 true false false false", 461 "U 17 0 true false false false" } 462 }; 463 464 ASSERT_TRUE(test_server()->Start()); 465 466 ASSERT_TRUE(ui_test_utils::BringBrowserWindowToFront(browser())); 467 GURL url = test_server()->GetURL(kTestingPage); 468 ui_test_utils::NavigateToURL(browser(), url); 469 470 ASSERT_NO_FATAL_FAILURE(ClickOnView(VIEW_ID_TAB_CONTAINER)); 471 ASSERT_TRUE(IsViewFocused(VIEW_ID_TAB_CONTAINER)); 472 473 int tab_index = browser()->tab_strip_model()->active_index(); 474 // Press Ctrl+F, which will make the Find box open and request focus. 475 EXPECT_NO_FATAL_FAILURE(TestKeyEvent(tab_index, kTestCtrlF)); 476 EXPECT_TRUE(IsViewFocused(VIEW_ID_FIND_IN_PAGE_TEXT_FIELD)); 477 478 // Press Escape to close the Find box and move the focus back to the web page. 479 ASSERT_TRUE(ui_test_utils::SendKeyPressSync( 480 browser(), ui::VKEY_ESCAPE, false, false, false, false)); 481 ASSERT_TRUE(IsViewFocused(VIEW_ID_TAB_CONTAINER)); 482 483 // Press Ctrl+F with keydown suppressed shall not open the find box. 484 EXPECT_NO_FATAL_FAILURE(TestKeyEvent(tab_index, kTestCtrlFSuppressKeyDown)); 485 ASSERT_TRUE(IsViewFocused(VIEW_ID_TAB_CONTAINER)); 486 487 EXPECT_NO_FATAL_FAILURE(TestKeyEvent(tab_index, kTestCtrlZ)); 488 EXPECT_NO_FATAL_FAILURE(TestKeyEvent(tab_index, kTestCtrlZSuppressKeyDown)); 489 EXPECT_NO_FATAL_FAILURE(TestKeyEvent(tab_index, kTestCtrlEnter)); 490} 491#elif defined(OS_MACOSX) 492// http://crbug.com/81451 493IN_PROC_BROWSER_TEST_F(BrowserKeyEventsTest, DISABLED_CommandKeyEvents) { 494 static const KeyEventTestData kTestCmdF = { 495 ui::VKEY_F, false, false, false, true, 496 false, false, false, false, 2, 497 { "D 91 0 false false false true", 498 "D 70 0 false false false true" } 499 }; 500 501 // On Mac we don't send key up events when command modifier is down. 502 static const KeyEventTestData kTestCmdFSuppressKeyDown = { 503 ui::VKEY_F, false, false, false, true, 504 true, false, false, false, 3, 505 { "D 91 0 false false false true", 506 "D 70 0 false false false true", 507 "U 91 0 false false false true" } 508 }; 509 510 ASSERT_TRUE(test_server()->Start()); 511 512 ASSERT_TRUE(ui_test_utils::BringBrowserWindowToFront(browser())); 513 GURL url = test_server()->GetURL(kTestingPage); 514 ui_test_utils::NavigateToURL(browser(), url); 515 516 ASSERT_NO_FATAL_FAILURE(ClickOnView(VIEW_ID_TAB_CONTAINER)); 517 ASSERT_TRUE(IsViewFocused(VIEW_ID_TAB_CONTAINER)); 518 519 int tab_index = browser()->tab_strip_model()->active_index(); 520 // Press Cmd+F, which will make the Find box open and request focus. 521 EXPECT_NO_FATAL_FAILURE(TestKeyEvent(tab_index, kTestCmdF)); 522 EXPECT_TRUE(IsViewFocused(VIEW_ID_FIND_IN_PAGE_TEXT_FIELD)); 523 524 // Press Escape to close the Find box and move the focus back to the web page. 525 ASSERT_TRUE(ui_test_utils::SendKeyPressSync( 526 browser(), ui::VKEY_ESCAPE, false, false, false, false)); 527 ASSERT_TRUE(IsViewFocused(VIEW_ID_TAB_CONTAINER)); 528 529 // Press Cmd+F with keydown suppressed shall not open the find box. 530 EXPECT_NO_FATAL_FAILURE(TestKeyEvent(tab_index, kTestCmdFSuppressKeyDown)); 531 ASSERT_TRUE(IsViewFocused(VIEW_ID_TAB_CONTAINER)); 532} 533#endif 534 535// Flaky: http://crbug.com/81451 , http://crbug.com/129235 , 536// also fails on Windows. 537IN_PROC_BROWSER_TEST_F(BrowserKeyEventsTest, DISABLED_AccessKeys) { 538#if defined(OS_MACOSX) 539 // On Mac, access keys use ctrl+alt modifiers. 540 static const KeyEventTestData kTestAccessA = { 541 ui::VKEY_A, true, false, true, false, 542 false, false, false, false, 6, 543 { "D 17 0 true false false false", 544 "D 18 0 true false true false", 545 "D 65 0 true false true false", 546 "U 65 0 true false true false", 547 "U 18 0 true false true false", 548 "U 17 0 true false false false" } 549 }; 550 551 static const KeyEventTestData kTestAccessDSuppress = { 552 ui::VKEY_D, true, false, true, false, 553 true, true, true, false, 6, 554 { "D 17 0 true false false false", 555 "D 18 0 true false true false", 556 "D 68 0 true false true false", 557 "U 68 0 true false true false", 558 "U 18 0 true false true false", 559 "U 17 0 true false false false" } 560 }; 561 562 static const KeyEventTestData kTestAccess1 = { 563 ui::VKEY_1, true, false, true, false, 564 false, false, false, false, 6, 565 { "D 17 0 true false false false", 566 "D 18 0 true false true false", 567 "D 49 0 true false true false", 568 "U 49 0 true false true false", 569 "U 18 0 true false true false", 570 "U 17 0 true false false false" } 571 }; 572#else 573 static const KeyEventTestData kTestAccessA = { 574 ui::VKEY_A, false, false, true, false, 575 false, false, false, false, 4, 576 { "D 18 0 false false true false", 577 "D 65 0 false false true false", 578 "U 65 0 false false true false", 579 "U 18 0 false false true false" } 580 }; 581 582 static const KeyEventTestData kTestAccessD = { 583 ui::VKEY_D, false, false, true, false, 584 false, false, false, false, 2, 585 { "D 18 0 false false true false", 586 "D 68 0 false false true false" } 587 }; 588 589 static const KeyEventTestData kTestAccessDSuppress = { 590 ui::VKEY_D, false, false, true, false, 591 true, true, true, false, 4, 592 { "D 18 0 false false true false", 593 "D 68 0 false false true false", 594 "U 68 0 false false true false", 595 "U 18 0 false false true false" } 596 }; 597 598#if !defined(USE_ASH) 599 static const KeyEventTestData kTestAccess1 = { 600 ui::VKEY_1, false, false, true, false, 601 false, false, false, false, 4, 602 { "D 18 0 false false true false", 603 "D 49 0 false false true false", 604 "U 49 0 false false true false", 605 "U 18 0 false false true false" } 606 }; 607#endif 608#endif 609 610 ASSERT_TRUE(test_server()->Start()); 611 612 ASSERT_TRUE(ui_test_utils::BringBrowserWindowToFront(browser())); 613 GURL url = test_server()->GetURL(kTestingPage); 614 ui_test_utils::NavigateToURL(browser(), url); 615 616 content::RunAllPendingInMessageLoop(); 617 ASSERT_NO_FATAL_FAILURE(ClickOnView(VIEW_ID_TAB_CONTAINER)); 618 ASSERT_TRUE(IsViewFocused(VIEW_ID_TAB_CONTAINER)); 619 620 int tab_index = browser()->tab_strip_model()->active_index(); 621 // Make sure no element is focused. 622 EXPECT_NO_FATAL_FAILURE(CheckFocusedElement(tab_index, L"")); 623 // Alt+A should focus the element with accesskey = "A". 624 EXPECT_NO_FATAL_FAILURE(TestKeyEvent(tab_index, kTestAccessA)); 625 EXPECT_NO_FATAL_FAILURE(CheckFocusedElement(tab_index, L"A")); 626 627 // Blur the focused element. 628 EXPECT_NO_FATAL_FAILURE(SetFocusedElement(tab_index, L"")); 629 // Make sure no element is focused. 630 EXPECT_NO_FATAL_FAILURE(CheckFocusedElement(tab_index, L"")); 631 632#if !defined(OS_MACOSX) 633 // Alt+D should move the focus to the location entry. 634 EXPECT_NO_FATAL_FAILURE(TestKeyEvent(tab_index, kTestAccessD)); 635 636 // TODO(isherman): This is an experimental change to help diagnose 637 // http://crbug.com/55713 638 content::RunAllPendingInMessageLoop(); 639 EXPECT_TRUE(IsViewFocused(VIEW_ID_OMNIBOX)); 640 // No element should be focused, as Alt+D was handled by the browser. 641 EXPECT_NO_FATAL_FAILURE(CheckFocusedElement(tab_index, L"")); 642 643 // Move the focus back to the web page. 644 ASSERT_NO_FATAL_FAILURE(ClickOnView(VIEW_ID_TAB_CONTAINER)); 645 ASSERT_TRUE(IsViewFocused(VIEW_ID_TAB_CONTAINER)); 646 647 // Make sure no element is focused. 648 EXPECT_NO_FATAL_FAILURE(CheckFocusedElement(tab_index, L"")); 649#endif 650 651 // If the keydown event is suppressed, then Alt+D should be handled as an 652 // accesskey rather than an accelerator key. Activation of an accesskey is not 653 // a part of the default action of the key event, so it should not be 654 // suppressed at all. 655 EXPECT_NO_FATAL_FAILURE(TestKeyEvent(tab_index, kTestAccessDSuppress)); 656 ASSERT_TRUE(IsViewFocused(VIEW_ID_TAB_CONTAINER)); 657 EXPECT_NO_FATAL_FAILURE(CheckFocusedElement(tab_index, L"D")); 658 659 // Blur the focused element. 660 EXPECT_NO_FATAL_FAILURE(SetFocusedElement(tab_index, L"")); 661 // Make sure no element is focused. 662 EXPECT_NO_FATAL_FAILURE(CheckFocusedElement(tab_index, L"")); 663#if !defined(USE_ASH) 664 // On Ash, alt-1..9 are assigned as window selection global accelerators, so 665 // they can not be used as accesskeys. 666 EXPECT_NO_FATAL_FAILURE(TestKeyEvent(tab_index, kTestAccess1)); 667#if defined(TOOLKIT_GTK) 668 // On GTK, alt-0..9 are assigned as tab selection accelerators, so they can 669 // not be used as accesskeys. 670 EXPECT_NO_FATAL_FAILURE(CheckFocusedElement(tab_index, L"")); 671#else 672 EXPECT_NO_FATAL_FAILURE(CheckFocusedElement(tab_index, L"1")); 673#endif 674#endif 675} 676 677// Flaky, http://crbug.com/69475. 678#if defined(OS_LINUX) 679#define MAYBE_ReservedAccelerators DISABLED_ReservedAccelerators 680#else 681#define MAYBE_ReservedAccelerators ReservedAccelerators 682#endif 683IN_PROC_BROWSER_TEST_F(BrowserKeyEventsTest, MAYBE_ReservedAccelerators) { 684 ASSERT_TRUE(test_server()->Start()); 685 686 ASSERT_TRUE(ui_test_utils::BringBrowserWindowToFront(browser())); 687 GURL url = test_server()->GetURL(kTestingPage); 688 ui_test_utils::NavigateToURL(browser(), url); 689 690 ASSERT_NO_FATAL_FAILURE(ClickOnView(VIEW_ID_TAB_CONTAINER)); 691 ASSERT_TRUE(IsViewFocused(VIEW_ID_TAB_CONTAINER)); 692 693 ASSERT_EQ(1, browser()->tab_strip_model()->count()); 694 695 static const KeyEventTestData kTestCtrlOrCmdT = { 696#if defined(OS_MACOSX) 697 ui::VKEY_T, false, false, false, true, 698 true, false, false, false, 1, 699 { "D 91 0 false false false true" } 700#else 701 ui::VKEY_T, true, false, false, false, 702 true, false, false, false, 1, 703 { "D 17 0 true false false false" } 704#endif 705 }; 706 707 content::WindowedNotificationObserver wait_for_new_tab( 708 chrome::NOTIFICATION_TAB_PARENTED, 709 content::NotificationService::AllSources()); 710 711 // Press Ctrl/Cmd+T, which will open a new tab. It cannot be suppressed. 712 EXPECT_NO_FATAL_FAILURE(TestKeyEvent(0, kTestCtrlOrCmdT)); 713 wait_for_new_tab.Wait(); 714 715 int result_length; 716 ASSERT_NO_FATAL_FAILURE(GetResultLength(0, &result_length)); 717 EXPECT_EQ(1, result_length); 718 719 EXPECT_EQ(2, browser()->tab_strip_model()->count()); 720 ASSERT_EQ(1, browser()->tab_strip_model()->active_index()); 721 722 // Because of issue <http://crbug.com/65375>, switching back to the first tab 723 // may cause the focus to be grabbed by omnibox. So instead, we load our 724 // testing page in the newly created tab and try Cmd-W here. 725 ui_test_utils::NavigateToURL(browser(), url); 726 727 // Make sure the focus is in the testing page. 728 ASSERT_NO_FATAL_FAILURE(ClickOnView(VIEW_ID_TAB_CONTAINER)); 729 ASSERT_TRUE(IsViewFocused(VIEW_ID_TAB_CONTAINER)); 730 731 // Reserved accelerators can't be suppressed. 732 ASSERT_NO_FATAL_FAILURE(SuppressAllEvents(1, true)); 733 734 content::WindowedNotificationObserver wait_for_tab_closed( 735 content::NOTIFICATION_WEB_CONTENTS_DESTROYED, 736 content::Source<content::WebContents>( 737 browser()->tab_strip_model()->GetWebContentsAt(1))); 738 739 // Press Ctrl/Cmd+W, which will close the tab. 740#if defined(OS_MACOSX) 741 ASSERT_TRUE(ui_test_utils::SendKeyPressSync( 742 browser(), ui::VKEY_W, false, false, false, true)); 743#else 744 ASSERT_TRUE(ui_test_utils::SendKeyPressSync( 745 browser(), ui::VKEY_W, true, false, false, false)); 746#endif 747 748 ASSERT_NO_FATAL_FAILURE(wait_for_tab_closed.Wait()); 749 750 EXPECT_EQ(1, browser()->tab_strip_model()->count()); 751} 752 753#if defined(OS_MACOSX) 754IN_PROC_BROWSER_TEST_F(BrowserKeyEventsTest, EditorKeyBindings) { 755 // TODO(kbr): re-enable: http://crbug.com/222296 756 if (base::mac::IsOSMountainLionOrLater()) 757 return; 758 759 static const KeyEventTestData kTestCtrlA = { 760 ui::VKEY_A, true, false, false, false, 761 false, false, false, false, 4, 762 { "D 17 0 true false false false", 763 "D 65 0 true false false false", 764 "U 65 0 true false false false", 765 "U 17 0 true false false false" } 766 }; 767 768 static const KeyEventTestData kTestCtrlF = { 769 ui::VKEY_F, true, false, false, false, 770 false, false, false, false, 4, 771 { "D 17 0 true false false false", 772 "D 70 0 true false false false", 773 "U 70 0 true false false false", 774 "U 17 0 true false false false" } 775 }; 776 777 static const KeyEventTestData kTestCtrlK = { 778 ui::VKEY_K, true, false, false, false, 779 false, false, false, false, 4, 780 { "D 17 0 true false false false", 781 "D 75 0 true false false false", 782 "U 75 0 true false false false", 783 "U 17 0 true false false false" } 784 }; 785 786 ASSERT_TRUE(test_server()->Start()); 787 788 ASSERT_TRUE(ui_test_utils::BringBrowserWindowToFront(browser())); 789 GURL url = test_server()->GetURL(kTestingPage); 790 ui_test_utils::NavigateToURL(browser(), url); 791 792 ASSERT_NO_FATAL_FAILURE(ClickOnView(VIEW_ID_TAB_CONTAINER)); 793 ASSERT_TRUE(IsViewFocused(VIEW_ID_TAB_CONTAINER)); 794 795 int tab_index = browser()->tab_strip_model()->active_index(); 796 ASSERT_NO_FATAL_FAILURE(SetFocusedElement(tab_index, L"A")); 797 ASSERT_NO_FATAL_FAILURE(SetTextBoxValue(tab_index, L"A", L"Hello")); 798 // Move the caret to the beginning of the line. 799 EXPECT_NO_FATAL_FAILURE(TestKeyEvent(tab_index, kTestCtrlA)); 800 // Forward one character 801 EXPECT_NO_FATAL_FAILURE(TestKeyEvent(tab_index, kTestCtrlF)); 802 // Delete to the end of the line. 803 EXPECT_NO_FATAL_FAILURE(TestKeyEvent(tab_index, kTestCtrlK)); 804 EXPECT_NO_FATAL_FAILURE(CheckTextBoxValue(tab_index, L"A", L"H")); 805} 806#endif 807 808// See http://crbug.com/147579 809IN_PROC_BROWSER_TEST_F(BrowserKeyEventsTest, DISABLED_PageUpDownKeys) { 810 static const KeyEventTestData kTestPageUp = { 811 ui::VKEY_PRIOR, false, false, false, false, 812 false, false, false, false, 2, 813 { "D 33 0 false false false false", 814 "U 33 0 false false false false" } 815 }; 816 817 static const KeyEventTestData kTestPageDown = { 818 ui::VKEY_NEXT, false, false, false, false, 819 false, false, false, false, 2, 820 { "D 34 0 false false false false", 821 "U 34 0 false false false false" } 822 }; 823 824 ASSERT_TRUE(test_server()->Start()); 825 826 ASSERT_TRUE(ui_test_utils::BringBrowserWindowToFront(browser())); 827 GURL url = test_server()->GetURL(kTestingPage); 828 ui_test_utils::NavigateToURL(browser(), url); 829 830 ASSERT_NO_FATAL_FAILURE(ClickOnView(VIEW_ID_TAB_CONTAINER)); 831 ASSERT_TRUE(IsViewFocused(VIEW_ID_TAB_CONTAINER)); 832 833 int tab_index = browser()->tab_strip_model()->active_index(); 834 ASSERT_NO_FATAL_FAILURE(SetFocusedElement(tab_index, L"A")); 835 EXPECT_NO_FATAL_FAILURE(TestKeyEvent(tab_index, kTestPageUp)); 836 EXPECT_NO_FATAL_FAILURE(TestKeyEvent(tab_index, kTestPageDown)); 837 EXPECT_NO_FATAL_FAILURE(CheckTextBoxValue(tab_index, L"A", L"")); 838} 839 840#if defined(OS_WIN) 841// AltKey is enabled only on Windows. See crbug.com/114537. 842IN_PROC_BROWSER_TEST_F(BrowserKeyEventsTest, FocusMenuBarByAltKey) { 843 static const KeyEventTestData kTestAltKey = { 844 ui::VKEY_MENU, false, false, false, false, 845 false, false, false, false, 2, 846 { "D 18 0 false false true false", 847 "U 18 0 false false true false" } 848 }; 849 850 static const KeyEventTestData kTestAltKeySuppress = { 851 ui::VKEY_MENU, false, false, false, false, 852 true, false, false, false, 2, 853 { "D 18 0 false false true false", 854 "U 18 0 false false true false" } 855 }; 856 857 static const KeyEventTestData kTestCtrlAltKey = { 858 ui::VKEY_MENU, true, false, false, false, 859 false, false, false, false, 4, 860 { "D 17 0 true false false false", 861 "D 18 0 true false true false", 862 "U 18 0 true false true false", 863 "U 17 0 true false false false" } 864 }; 865 866 ASSERT_TRUE(test_server()->Start()); 867 868 ASSERT_TRUE(ui_test_utils::BringBrowserWindowToFront(browser())); 869 GURL url = test_server()->GetURL(kTestingPage); 870 ui_test_utils::NavigateToURL(browser(), url); 871 872 ASSERT_NO_FATAL_FAILURE(ClickOnView(VIEW_ID_TAB_CONTAINER)); 873 ASSERT_TRUE(IsViewFocused(VIEW_ID_TAB_CONTAINER)); 874 875 int tab_index = browser()->tab_strip_model()->active_index(); 876 // Press and release Alt key to focus wrench menu button. 877 EXPECT_NO_FATAL_FAILURE(TestKeyEvent(tab_index, kTestAltKey)); 878 EXPECT_TRUE(IsViewFocused(VIEW_ID_APP_MENU)); 879 880 ASSERT_NO_FATAL_FAILURE(ClickOnView(VIEW_ID_TAB_CONTAINER)); 881 ASSERT_TRUE(IsViewFocused(VIEW_ID_TAB_CONTAINER)); 882 883 // Alt key can be suppressed. 884 EXPECT_NO_FATAL_FAILURE(TestKeyEvent(tab_index, kTestAltKeySuppress)); 885 ASSERT_TRUE(IsViewFocused(VIEW_ID_TAB_CONTAINER)); 886 887 // Ctrl+Alt should have no effect. 888 EXPECT_NO_FATAL_FAILURE(TestKeyEvent(tab_index, kTestCtrlAltKey)); 889 ASSERT_TRUE(IsViewFocused(VIEW_ID_TAB_CONTAINER)); 890} 891#endif 892 893} // namespace 894