browser_keyevents_browsertest.cc revision 8bcbed890bc3ce4d7a057a8f32cab53fa534672e
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_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/embedded_test_server/embedded_test_server.h" 29#include "ui/events/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[] = "/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 base::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// Flaky: http://crbug.com/129235, http://crbug.com/81451. 302IN_PROC_BROWSER_TEST_F(BrowserKeyEventsTest, DISABLED_NormalKeyEvents) { 303 static const KeyEventTestData kTestNoInput[] = { 304 // a 305 { ui::VKEY_A, false, false, false, false, 306 false, false, false, false, 3, 307 { "D 65 0 false false false false", 308 "P 97 97 false false false false", 309 "U 65 0 false false false false" } }, 310 // shift-a 311 { ui::VKEY_A, false, true, false, false, 312 false, false, false, false, 5, 313 { "D 16 0 false true false false", 314 "D 65 0 false true false false", 315 "P 65 65 false true false false", 316 "U 65 0 false true false false", 317 "U 16 0 false true false false" } }, 318 // a, suppress keydown 319 { ui::VKEY_A, false, false, false, false, 320 true, false, false, false, 2, 321 { "D 65 0 false false false false", 322 "U 65 0 false false false false" } }, 323 }; 324 325 static const KeyEventTestData kTestWithInput[] = { 326 // a 327 { ui::VKEY_A, false, false, false, false, 328 false, false, false, false, 4, 329 { "D 65 0 false false false false", 330 "P 97 97 false false false false", 331 "T a", 332 "U 65 0 false false false false" } }, 333 // shift-a 334 { ui::VKEY_A, false, true, false, false, 335 false, false, false, false, 6, 336 { "D 16 0 false true false false", 337 "D 65 0 false true false false", 338 "P 65 65 false true false false", 339 "T A", 340 "U 65 0 false true false false", 341 "U 16 0 false true false false" } }, 342 // a, suppress keydown 343 { ui::VKEY_A, false, false, false, false, 344 true, false, false, false, 2, 345 { "D 65 0 false false false false", 346 "U 65 0 false false false false" } }, 347 // a, suppress keypress 348 { ui::VKEY_A, false, false, false, false, 349 false, true, false, false, 3, 350 { "D 65 0 false false false false", 351 "P 97 97 false false false false", 352 "U 65 0 false false false false" } }, 353 // a, suppress textInput 354 { ui::VKEY_A, false, false, false, false, 355 false, false, false, true, 4, 356 { "D 65 0 false false false false", 357 "P 97 97 false false false false", 358 "T a", 359 "U 65 0 false false false false" } }, 360 }; 361 362 ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady()); 363 364 ASSERT_TRUE(ui_test_utils::BringBrowserWindowToFront(browser())); 365 GURL url = embedded_test_server()->GetURL(kTestingPage); 366 ui_test_utils::NavigateToURL(browser(), url); 367 368 ASSERT_NO_FATAL_FAILURE(ClickOnView(VIEW_ID_TAB_CONTAINER)); 369 ASSERT_TRUE(IsViewFocused(VIEW_ID_TAB_CONTAINER)); 370 371 int tab_index = browser()->tab_strip_model()->active_index(); 372 for (size_t i = 0; i < arraysize(kTestNoInput); ++i) { 373 EXPECT_NO_FATAL_FAILURE(TestKeyEvent(tab_index, kTestNoInput[i])) 374 << "kTestNoInput[" << i << "] failed:\n" 375 << GetTestDataDescription(kTestNoInput[i]); 376 } 377 378 // Input in normal text box. 379 ASSERT_NO_FATAL_FAILURE(SetFocusedElement(tab_index, L"A")); 380 for (size_t i = 0; i < arraysize(kTestWithInput); ++i) { 381 EXPECT_NO_FATAL_FAILURE(TestKeyEvent(tab_index, kTestWithInput[i])) 382 << "kTestWithInput[" << i << "] in text box failed:\n" 383 << GetTestDataDescription(kTestWithInput[i]); 384 } 385 EXPECT_NO_FATAL_FAILURE(CheckTextBoxValue(tab_index, L"A", L"aA")); 386 387 // Input in password box. 388 ASSERT_NO_FATAL_FAILURE(SetFocusedElement(tab_index, L"B")); 389 for (size_t i = 0; i < arraysize(kTestWithInput); ++i) { 390 EXPECT_NO_FATAL_FAILURE(TestKeyEvent(tab_index, kTestWithInput[i])) 391 << "kTestWithInput[" << i << "] in password box failed:\n" 392 << GetTestDataDescription(kTestWithInput[i]); 393 } 394 EXPECT_NO_FATAL_FAILURE(CheckTextBoxValue(tab_index, L"B", L"aA")); 395} 396 397#if defined(OS_WIN) || defined(OS_LINUX) 398 399#if defined(OS_LINUX) || (defined(OS_WIN) && defined(USE_AURA)) 400// Linux: http://crbug.com/129235 401// Win Aura: crbug.com/269564 402#define MAYBE_CtrlKeyEvents DISABLED_CtrlKeyEvents 403#else 404#define MAYBE_CtrlKeyEvents CtrlKeyEvents 405#endif 406 407IN_PROC_BROWSER_TEST_F(BrowserKeyEventsTest, MAYBE_CtrlKeyEvents) { 408 static const KeyEventTestData kTestCtrlF = { 409 ui::VKEY_F, true, false, false, false, 410 false, false, false, false, 2, 411 { "D 17 0 true false false false", 412 "D 70 0 true false false false" } 413 }; 414 415 static const KeyEventTestData kTestCtrlFSuppressKeyDown = { 416 ui::VKEY_F, true, false, false, false, 417 true, false, false, false, 4, 418 { "D 17 0 true false false false", 419 "D 70 0 true false false false", 420 "U 70 0 true false false false", 421 "U 17 0 true false false false" } 422 }; 423 424 // Ctrl+Z doesn't bind to any accelerators, which then should generate a 425 // keypress event with charCode=26. 426 static const KeyEventTestData kTestCtrlZ = { 427 ui::VKEY_Z, true, false, false, false, 428 false, false, false, false, 5, 429 { "D 17 0 true false false false", 430 "D 90 0 true false false false", 431 "P 26 26 true false false false", 432 "U 90 0 true false false false", 433 "U 17 0 true false false false" } 434 }; 435 436 static const KeyEventTestData kTestCtrlZSuppressKeyDown = { 437 ui::VKEY_Z, true, false, false, false, 438 true, false, false, false, 4, 439 { "D 17 0 true false false false", 440 "D 90 0 true false false false", 441 "U 90 0 true false false false", 442 "U 17 0 true false false false" } 443 }; 444 445 // Ctrl+Enter shall generate a keypress event with charCode=10 (LF). 446 static const KeyEventTestData kTestCtrlEnter = { 447 ui::VKEY_RETURN, true, false, false, false, 448 false, false, false, false, 5, 449 { "D 17 0 true false false false", 450 "D 13 0 true false false false", 451 "P 10 10 true false false false", 452 "U 13 0 true false false false", 453 "U 17 0 true false false false" } 454 }; 455 456 ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady()); 457 458 ASSERT_TRUE(ui_test_utils::BringBrowserWindowToFront(browser())); 459 GURL url = embedded_test_server()->GetURL(kTestingPage); 460 ui_test_utils::NavigateToURL(browser(), url); 461 462 ASSERT_NO_FATAL_FAILURE(ClickOnView(VIEW_ID_TAB_CONTAINER)); 463 ASSERT_TRUE(IsViewFocused(VIEW_ID_TAB_CONTAINER)); 464 465 int tab_index = browser()->tab_strip_model()->active_index(); 466 // Press Ctrl+F, which will make the Find box open and request focus. 467 EXPECT_NO_FATAL_FAILURE(TestKeyEvent(tab_index, kTestCtrlF)); 468 EXPECT_TRUE(IsViewFocused(VIEW_ID_FIND_IN_PAGE_TEXT_FIELD)); 469 470 // Press Escape to close the Find box and move the focus back to the web page. 471 ASSERT_TRUE(ui_test_utils::SendKeyPressSync( 472 browser(), ui::VKEY_ESCAPE, false, false, false, false)); 473 ASSERT_TRUE(IsViewFocused(VIEW_ID_TAB_CONTAINER)); 474 475 // Press Ctrl+F with keydown suppressed shall not open the find box. 476 EXPECT_NO_FATAL_FAILURE(TestKeyEvent(tab_index, kTestCtrlFSuppressKeyDown)); 477 ASSERT_TRUE(IsViewFocused(VIEW_ID_TAB_CONTAINER)); 478 479 EXPECT_NO_FATAL_FAILURE(TestKeyEvent(tab_index, kTestCtrlZ)); 480 EXPECT_NO_FATAL_FAILURE(TestKeyEvent(tab_index, kTestCtrlZSuppressKeyDown)); 481 EXPECT_NO_FATAL_FAILURE(TestKeyEvent(tab_index, kTestCtrlEnter)); 482} 483#elif defined(OS_MACOSX) 484// http://crbug.com/81451 485IN_PROC_BROWSER_TEST_F(BrowserKeyEventsTest, DISABLED_CommandKeyEvents) { 486 static const KeyEventTestData kTestCmdF = { 487 ui::VKEY_F, false, false, false, true, 488 false, false, false, false, 2, 489 { "D 91 0 false false false true", 490 "D 70 0 false false false true" } 491 }; 492 493 // On Mac we don't send key up events when command modifier is down. 494 static const KeyEventTestData kTestCmdFSuppressKeyDown = { 495 ui::VKEY_F, false, false, false, true, 496 true, false, false, false, 3, 497 { "D 91 0 false false false true", 498 "D 70 0 false false false true", 499 "U 91 0 false false false true" } 500 }; 501 502 ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady()); 503 504 ASSERT_TRUE(ui_test_utils::BringBrowserWindowToFront(browser())); 505 GURL url = embedded_test_server()->GetURL(kTestingPage); 506 ui_test_utils::NavigateToURL(browser(), url); 507 508 ASSERT_NO_FATAL_FAILURE(ClickOnView(VIEW_ID_TAB_CONTAINER)); 509 ASSERT_TRUE(IsViewFocused(VIEW_ID_TAB_CONTAINER)); 510 511 int tab_index = browser()->tab_strip_model()->active_index(); 512 // Press Cmd+F, which will make the Find box open and request focus. 513 EXPECT_NO_FATAL_FAILURE(TestKeyEvent(tab_index, kTestCmdF)); 514 EXPECT_TRUE(IsViewFocused(VIEW_ID_FIND_IN_PAGE_TEXT_FIELD)); 515 516 // Press Escape to close the Find box and move the focus back to the web page. 517 ASSERT_TRUE(ui_test_utils::SendKeyPressSync( 518 browser(), ui::VKEY_ESCAPE, false, false, false, false)); 519 ASSERT_TRUE(IsViewFocused(VIEW_ID_TAB_CONTAINER)); 520 521 // Press Cmd+F with keydown suppressed shall not open the find box. 522 EXPECT_NO_FATAL_FAILURE(TestKeyEvent(tab_index, kTestCmdFSuppressKeyDown)); 523 ASSERT_TRUE(IsViewFocused(VIEW_ID_TAB_CONTAINER)); 524} 525#endif 526 527// Flaky: http://crbug.com/81451 , http://crbug.com/129235 , 528// also fails on Windows. 529IN_PROC_BROWSER_TEST_F(BrowserKeyEventsTest, DISABLED_AccessKeys) { 530#if defined(OS_MACOSX) 531 // On Mac, access keys use ctrl+alt modifiers. 532 static const KeyEventTestData kTestAccessA = { 533 ui::VKEY_A, true, false, true, false, 534 false, false, false, false, 6, 535 { "D 17 0 true false false false", 536 "D 18 0 true false true false", 537 "D 65 0 true false true false", 538 "U 65 0 true false true false", 539 "U 18 0 true false true false", 540 "U 17 0 true false false false" } 541 }; 542 543 static const KeyEventTestData kTestAccessDSuppress = { 544 ui::VKEY_D, true, false, true, false, 545 true, true, true, false, 6, 546 { "D 17 0 true false false false", 547 "D 18 0 true false true false", 548 "D 68 0 true false true false", 549 "U 68 0 true false true false", 550 "U 18 0 true false true false", 551 "U 17 0 true false false false" } 552 }; 553 554 static const KeyEventTestData kTestAccess1 = { 555 ui::VKEY_1, true, false, true, false, 556 false, false, false, false, 6, 557 { "D 17 0 true false false false", 558 "D 18 0 true false true false", 559 "D 49 0 true false true false", 560 "U 49 0 true false true false", 561 "U 18 0 true false true false", 562 "U 17 0 true false false false" } 563 }; 564#else 565 static const KeyEventTestData kTestAccessA = { 566 ui::VKEY_A, false, false, true, false, 567 false, false, false, false, 4, 568 { "D 18 0 false false true false", 569 "D 65 0 false false true false", 570 "U 65 0 false false true false", 571 "U 18 0 false false true false" } 572 }; 573 574 static const KeyEventTestData kTestAccessD = { 575 ui::VKEY_D, false, false, true, false, 576 false, false, false, false, 2, 577 { "D 18 0 false false true false", 578 "D 68 0 false false true false" } 579 }; 580 581 static const KeyEventTestData kTestAccessDSuppress = { 582 ui::VKEY_D, false, false, true, false, 583 true, true, true, false, 4, 584 { "D 18 0 false false true false", 585 "D 68 0 false false true false", 586 "U 68 0 false false true false", 587 "U 18 0 false false true false" } 588 }; 589 590#if !defined(USE_ASH) 591 static const KeyEventTestData kTestAccess1 = { 592 ui::VKEY_1, false, false, true, false, 593 false, false, false, false, 4, 594 { "D 18 0 false false true false", 595 "D 49 0 false false true false", 596 "U 49 0 false false true false", 597 "U 18 0 false false true false" } 598 }; 599#endif 600#endif 601 602 ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady()); 603 604 ASSERT_TRUE(ui_test_utils::BringBrowserWindowToFront(browser())); 605 GURL url = embedded_test_server()->GetURL(kTestingPage); 606 ui_test_utils::NavigateToURL(browser(), url); 607 608 content::RunAllPendingInMessageLoop(); 609 ASSERT_NO_FATAL_FAILURE(ClickOnView(VIEW_ID_TAB_CONTAINER)); 610 ASSERT_TRUE(IsViewFocused(VIEW_ID_TAB_CONTAINER)); 611 612 int tab_index = browser()->tab_strip_model()->active_index(); 613 // Make sure no element is focused. 614 EXPECT_NO_FATAL_FAILURE(CheckFocusedElement(tab_index, L"")); 615 // Alt+A should focus the element with accesskey = "A". 616 EXPECT_NO_FATAL_FAILURE(TestKeyEvent(tab_index, kTestAccessA)); 617 EXPECT_NO_FATAL_FAILURE(CheckFocusedElement(tab_index, L"A")); 618 619 // Blur the focused element. 620 EXPECT_NO_FATAL_FAILURE(SetFocusedElement(tab_index, L"")); 621 // Make sure no element is focused. 622 EXPECT_NO_FATAL_FAILURE(CheckFocusedElement(tab_index, L"")); 623 624#if !defined(OS_MACOSX) 625 // Alt+D should move the focus to the location entry. 626 EXPECT_NO_FATAL_FAILURE(TestKeyEvent(tab_index, kTestAccessD)); 627 628 // TODO(isherman): This is an experimental change to help diagnose 629 // http://crbug.com/55713 630 content::RunAllPendingInMessageLoop(); 631 EXPECT_TRUE(IsViewFocused(VIEW_ID_OMNIBOX)); 632 // No element should be focused, as Alt+D was handled by the browser. 633 EXPECT_NO_FATAL_FAILURE(CheckFocusedElement(tab_index, L"")); 634 635 // Move the focus back to the web page. 636 ASSERT_NO_FATAL_FAILURE(ClickOnView(VIEW_ID_TAB_CONTAINER)); 637 ASSERT_TRUE(IsViewFocused(VIEW_ID_TAB_CONTAINER)); 638 639 // Make sure no element is focused. 640 EXPECT_NO_FATAL_FAILURE(CheckFocusedElement(tab_index, L"")); 641#endif 642 643 // If the keydown event is suppressed, then Alt+D should be handled as an 644 // accesskey rather than an accelerator key. Activation of an accesskey is not 645 // a part of the default action of the key event, so it should not be 646 // suppressed at all. 647 EXPECT_NO_FATAL_FAILURE(TestKeyEvent(tab_index, kTestAccessDSuppress)); 648 ASSERT_TRUE(IsViewFocused(VIEW_ID_TAB_CONTAINER)); 649 EXPECT_NO_FATAL_FAILURE(CheckFocusedElement(tab_index, L"D")); 650 651 // Blur the focused element. 652 EXPECT_NO_FATAL_FAILURE(SetFocusedElement(tab_index, L"")); 653 // Make sure no element is focused. 654 EXPECT_NO_FATAL_FAILURE(CheckFocusedElement(tab_index, L"")); 655#if !defined(USE_ASH) 656 // On Ash, alt-1..9 are assigned as window selection global accelerators, so 657 // they can not be used as accesskeys. 658 EXPECT_NO_FATAL_FAILURE(TestKeyEvent(tab_index, kTestAccess1)); 659#if defined(TOOLKIT_GTK) 660 // On GTK, alt-0..9 are assigned as tab selection accelerators, so they can 661 // not be used as accesskeys. 662 EXPECT_NO_FATAL_FAILURE(CheckFocusedElement(tab_index, L"")); 663#else 664 EXPECT_NO_FATAL_FAILURE(CheckFocusedElement(tab_index, L"1")); 665#endif 666#endif 667} 668 669// Flaky, http://crbug.com/69475. 670#if defined(OS_LINUX) || (defined(OS_WIN) && defined(USE_AURA)) 671#define MAYBE_ReservedAccelerators DISABLED_ReservedAccelerators 672#else 673#define MAYBE_ReservedAccelerators ReservedAccelerators 674#endif 675IN_PROC_BROWSER_TEST_F(BrowserKeyEventsTest, MAYBE_ReservedAccelerators) { 676 ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady()); 677 678 ASSERT_TRUE(ui_test_utils::BringBrowserWindowToFront(browser())); 679 GURL url = embedded_test_server()->GetURL(kTestingPage); 680 ui_test_utils::NavigateToURL(browser(), url); 681 682 ASSERT_NO_FATAL_FAILURE(ClickOnView(VIEW_ID_TAB_CONTAINER)); 683 ASSERT_TRUE(IsViewFocused(VIEW_ID_TAB_CONTAINER)); 684 685 ASSERT_EQ(1, browser()->tab_strip_model()->count()); 686 687 static const KeyEventTestData kTestCtrlOrCmdT = { 688#if defined(OS_MACOSX) 689 ui::VKEY_T, false, false, false, true, 690 true, false, false, false, 1, 691 { "D 91 0 false false false true" } 692#else 693 ui::VKEY_T, true, false, false, false, 694 true, false, false, false, 1, 695 { "D 17 0 true false false false" } 696#endif 697 }; 698 699 content::WindowedNotificationObserver wait_for_new_tab( 700 chrome::NOTIFICATION_TAB_PARENTED, 701 content::NotificationService::AllSources()); 702 703 // Press Ctrl/Cmd+T, which will open a new tab. It cannot be suppressed. 704 EXPECT_NO_FATAL_FAILURE(TestKeyEvent(0, kTestCtrlOrCmdT)); 705 wait_for_new_tab.Wait(); 706 707 int result_length; 708 ASSERT_NO_FATAL_FAILURE(GetResultLength(0, &result_length)); 709 EXPECT_EQ(1, result_length); 710 711 EXPECT_EQ(2, browser()->tab_strip_model()->count()); 712 ASSERT_EQ(1, browser()->tab_strip_model()->active_index()); 713 714 // Because of issue <http://crbug.com/65375>, switching back to the first tab 715 // may cause the focus to be grabbed by omnibox. So instead, we load our 716 // testing page in the newly created tab and try Cmd-W here. 717 ui_test_utils::NavigateToURL(browser(), url); 718 719 // Make sure the focus is in the testing page. 720 ASSERT_NO_FATAL_FAILURE(ClickOnView(VIEW_ID_TAB_CONTAINER)); 721 ASSERT_TRUE(IsViewFocused(VIEW_ID_TAB_CONTAINER)); 722 723 // Reserved accelerators can't be suppressed. 724 ASSERT_NO_FATAL_FAILURE(SuppressAllEvents(1, true)); 725 726 content::WebContentsDestroyedWatcher destroyed_watcher( 727 browser()->tab_strip_model()->GetWebContentsAt(1)); 728 729 // Press Ctrl/Cmd+W, which will close the tab. 730#if defined(OS_MACOSX) 731 ASSERT_TRUE(ui_test_utils::SendKeyPressSync( 732 browser(), ui::VKEY_W, false, false, false, true)); 733#else 734 ASSERT_TRUE(ui_test_utils::SendKeyPressSync( 735 browser(), ui::VKEY_W, true, false, false, false)); 736#endif 737 738 ASSERT_NO_FATAL_FAILURE(destroyed_watcher.Wait()); 739 740 EXPECT_EQ(1, browser()->tab_strip_model()->count()); 741} 742 743#if defined(OS_MACOSX) 744IN_PROC_BROWSER_TEST_F(BrowserKeyEventsTest, EditorKeyBindings) { 745 // TODO(kbr): re-enable: http://crbug.com/222296 746 if (base::mac::IsOSMountainLionOrLater()) 747 return; 748 749 static const KeyEventTestData kTestCtrlA = { 750 ui::VKEY_A, true, false, false, false, 751 false, false, false, false, 4, 752 { "D 17 0 true false false false", 753 "D 65 0 true false false false", 754 "U 65 0 true false false false", 755 "U 17 0 true false false false" } 756 }; 757 758 static const KeyEventTestData kTestCtrlF = { 759 ui::VKEY_F, true, false, false, false, 760 false, false, false, false, 4, 761 { "D 17 0 true false false false", 762 "D 70 0 true false false false", 763 "U 70 0 true false false false", 764 "U 17 0 true false false false" } 765 }; 766 767 static const KeyEventTestData kTestCtrlK = { 768 ui::VKEY_K, true, false, false, false, 769 false, false, false, false, 4, 770 { "D 17 0 true false false false", 771 "D 75 0 true false false false", 772 "U 75 0 true false false false", 773 "U 17 0 true false false false" } 774 }; 775 776 ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady()); 777 778 ASSERT_TRUE(ui_test_utils::BringBrowserWindowToFront(browser())); 779 GURL url = embedded_test_server()->GetURL(kTestingPage); 780 ui_test_utils::NavigateToURL(browser(), url); 781 782 ASSERT_NO_FATAL_FAILURE(ClickOnView(VIEW_ID_TAB_CONTAINER)); 783 ASSERT_TRUE(IsViewFocused(VIEW_ID_TAB_CONTAINER)); 784 785 int tab_index = browser()->tab_strip_model()->active_index(); 786 ASSERT_NO_FATAL_FAILURE(SetFocusedElement(tab_index, L"A")); 787 ASSERT_NO_FATAL_FAILURE(SetTextBoxValue(tab_index, L"A", L"Hello")); 788 // Move the caret to the beginning of the line. 789 EXPECT_NO_FATAL_FAILURE(TestKeyEvent(tab_index, kTestCtrlA)); 790 // Forward one character 791 EXPECT_NO_FATAL_FAILURE(TestKeyEvent(tab_index, kTestCtrlF)); 792 // Delete to the end of the line. 793 EXPECT_NO_FATAL_FAILURE(TestKeyEvent(tab_index, kTestCtrlK)); 794 EXPECT_NO_FATAL_FAILURE(CheckTextBoxValue(tab_index, L"A", L"H")); 795} 796#endif 797 798// See http://crbug.com/147579 799IN_PROC_BROWSER_TEST_F(BrowserKeyEventsTest, DISABLED_PageUpDownKeys) { 800 static const KeyEventTestData kTestPageUp = { 801 ui::VKEY_PRIOR, false, false, false, false, 802 false, false, false, false, 2, 803 { "D 33 0 false false false false", 804 "U 33 0 false false false false" } 805 }; 806 807 static const KeyEventTestData kTestPageDown = { 808 ui::VKEY_NEXT, false, false, false, false, 809 false, false, false, false, 2, 810 { "D 34 0 false false false false", 811 "U 34 0 false false false false" } 812 }; 813 814 ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady()); 815 816 ASSERT_TRUE(ui_test_utils::BringBrowserWindowToFront(browser())); 817 GURL url = embedded_test_server()->GetURL(kTestingPage); 818 ui_test_utils::NavigateToURL(browser(), url); 819 820 ASSERT_NO_FATAL_FAILURE(ClickOnView(VIEW_ID_TAB_CONTAINER)); 821 ASSERT_TRUE(IsViewFocused(VIEW_ID_TAB_CONTAINER)); 822 823 int tab_index = browser()->tab_strip_model()->active_index(); 824 ASSERT_NO_FATAL_FAILURE(SetFocusedElement(tab_index, L"A")); 825 EXPECT_NO_FATAL_FAILURE(TestKeyEvent(tab_index, kTestPageUp)); 826 EXPECT_NO_FATAL_FAILURE(TestKeyEvent(tab_index, kTestPageDown)); 827 EXPECT_NO_FATAL_FAILURE(CheckTextBoxValue(tab_index, L"A", L"")); 828} 829 830#if defined(OS_WIN) 831// AltKey is enabled only on Windows. See crbug.com/114537. 832IN_PROC_BROWSER_TEST_F(BrowserKeyEventsTest, FocusMenuBarByAltKey) { 833 static const KeyEventTestData kTestAltKey = { 834 ui::VKEY_MENU, false, false, false, false, 835 false, false, false, false, 2, 836 { "D 18 0 false false true false", 837 "U 18 0 false false true false" } 838 }; 839 840 static const KeyEventTestData kTestAltKeySuppress = { 841 ui::VKEY_MENU, false, false, false, false, 842 true, false, false, false, 2, 843 { "D 18 0 false false true false", 844 "U 18 0 false false true false" } 845 }; 846 847 static const KeyEventTestData kTestCtrlAltKey = { 848 ui::VKEY_MENU, true, false, false, false, 849 false, false, false, false, 4, 850 { "D 17 0 true false false false", 851 "D 18 0 true false true false", 852 "U 18 0 true false true false", 853 "U 17 0 true false false false" } 854 }; 855 856 ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady()); 857 858 ASSERT_TRUE(ui_test_utils::BringBrowserWindowToFront(browser())); 859 GURL url = embedded_test_server()->GetURL(kTestingPage); 860 ui_test_utils::NavigateToURL(browser(), url); 861 862 ASSERT_NO_FATAL_FAILURE(ClickOnView(VIEW_ID_TAB_CONTAINER)); 863 ASSERT_TRUE(IsViewFocused(VIEW_ID_TAB_CONTAINER)); 864 865 int tab_index = browser()->tab_strip_model()->active_index(); 866 // Press and release Alt key to focus wrench menu button. 867 EXPECT_NO_FATAL_FAILURE(TestKeyEvent(tab_index, kTestAltKey)); 868 EXPECT_TRUE(IsViewFocused(VIEW_ID_APP_MENU)); 869 870 ASSERT_NO_FATAL_FAILURE(ClickOnView(VIEW_ID_TAB_CONTAINER)); 871 ASSERT_TRUE(IsViewFocused(VIEW_ID_TAB_CONTAINER)); 872 873 // Alt key can be suppressed. 874 EXPECT_NO_FATAL_FAILURE(TestKeyEvent(tab_index, kTestAltKeySuppress)); 875 ASSERT_TRUE(IsViewFocused(VIEW_ID_TAB_CONTAINER)); 876 877 // Ctrl+Alt should have no effect. 878 EXPECT_NO_FATAL_FAILURE(TestKeyEvent(tab_index, kTestCtrlAltKey)); 879 ASSERT_TRUE(IsViewFocused(VIEW_ID_TAB_CONTAINER)); 880} 881#endif 882 883} // namespace 884