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