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