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 "base/command_line.h" 6 #include "chrome/browser/extensions/active_tab_permission_granter.h" 7 #include "chrome/browser/extensions/api/commands/command_service.h" 8 #include "chrome/browser/extensions/browser_action_test_util.h" 9 #include "chrome/browser/extensions/extension_action.h" 10 #include "chrome/browser/extensions/extension_action_manager.h" 11 #include "chrome/browser/extensions/extension_apitest.h" 12 #include "chrome/browser/extensions/tab_helper.h" 13 #include "chrome/browser/sessions/session_tab_helper.h" 14 #include "chrome/browser/ui/browser.h" 15 #include "chrome/browser/ui/tabs/tab_strip_model.h" 16 #include "chrome/test/base/interactive_test_utils.h" 17 #include "chrome/test/base/ui_test_utils.h" 18 #include "content/public/browser/notification_service.h" 19 #include "content/public/browser/web_contents.h" 20 #include "content/public/test/browser_test_utils.h" 21 #include "extensions/browser/extension_registry.h" 22 #include "extensions/common/extension.h" 23 #include "extensions/common/feature_switch.h" 24 #include "extensions/common/manifest_constants.h" 25 #include "extensions/common/permissions/permissions_data.h" 26 #include "extensions/test/result_catcher.h" 27 28 using content::WebContents; 29 30 namespace extensions { 31 32 namespace { 33 // This extension ID is used for tests require a stable ID over multiple 34 // extension installs. 35 const char kId[] = "pgoakhfeplldmjheffidklpoklkppipp"; 36 37 // Default keybinding to use for emulating user-defined shortcut overrides. The 38 // test extensions use Alt+Shift+F and Alt+Shift+H. 39 const char kAltShiftG[] = "Alt+Shift+G"; 40 } 41 42 class CommandsApiTest : public ExtensionApiTest { 43 public: 44 CommandsApiTest() {} 45 virtual ~CommandsApiTest() {} 46 47 protected: 48 BrowserActionTestUtil GetBrowserActionsBar() { 49 return BrowserActionTestUtil(browser()); 50 } 51 52 bool IsGrantedForTab(const Extension* extension, 53 const content::WebContents* web_contents) { 54 return extension->permissions_data()->HasAPIPermissionForTab( 55 SessionTabHelper::IdForTab(web_contents), APIPermission::kTab); 56 } 57 58 #if defined(OS_CHROMEOS) 59 void RunChromeOSConversionTest(const std::string& extension_path) { 60 // Setup the environment. 61 ASSERT_TRUE(test_server()->Start()); 62 ASSERT_TRUE(ui_test_utils::BringBrowserWindowToFront(browser())); 63 ASSERT_TRUE(RunExtensionTest(extension_path)) << message_; 64 ui_test_utils::NavigateToURL( 65 browser(), test_server()->GetURL("files/extensions/test_file.txt")); 66 67 ResultCatcher catcher; 68 69 // Send all expected keys (Search+Shift+{Left, Up, Right, Down}). 70 ASSERT_TRUE(ui_test_utils::SendKeyPressSync( 71 browser(), ui::VKEY_LEFT, false, true, false, true)); 72 ASSERT_TRUE(ui_test_utils::SendKeyPressSync( 73 browser(), ui::VKEY_UP, false, true, false, true)); 74 ASSERT_TRUE(ui_test_utils::SendKeyPressSync( 75 browser(), ui::VKEY_RIGHT, false, true, false, true)); 76 ASSERT_TRUE(ui_test_utils::SendKeyPressSync( 77 browser(), ui::VKEY_DOWN, false, true, false, true)); 78 79 ASSERT_TRUE(catcher.GetNextResult()); 80 } 81 #endif // OS_CHROMEOS 82 }; 83 84 // Test the basic functionality of the Keybinding API: 85 // - That pressing the shortcut keys should perform actions (activate the 86 // browser action or send an event). 87 // - Note: Page action keybindings are tested in PageAction test below. 88 // - The shortcut keys taken by one extension are not overwritten by the last 89 // installed extension. 90 IN_PROC_BROWSER_TEST_F(CommandsApiTest, Basic) { 91 ASSERT_TRUE(test_server()->Start()); 92 ASSERT_TRUE(RunExtensionTest("keybinding/basics")) << message_; 93 const Extension* extension = GetSingleLoadedExtension(); 94 ASSERT_TRUE(extension) << message_; 95 96 // Load this extension, which uses the same keybindings but sets the page 97 // to different colors. This is so we can see that it doesn't interfere. We 98 // don't test this extension in any other way (it should otherwise be 99 // immaterial to this test). 100 ASSERT_TRUE(RunExtensionTest("keybinding/conflicting")) << message_; 101 102 // Test that there are two browser actions in the toolbar. 103 ASSERT_EQ(2, GetBrowserActionsBar().NumberOfBrowserActions()); 104 105 ui_test_utils::NavigateToURL(browser(), 106 test_server()->GetURL("files/extensions/test_file.txt")); 107 108 // activeTab shouldn't have been granted yet. 109 WebContents* tab = browser()->tab_strip_model()->GetActiveWebContents(); 110 ASSERT_TRUE(tab); 111 112 EXPECT_FALSE(IsGrantedForTab(extension, tab)); 113 114 // Activate the shortcut (Ctrl+Shift+F). 115 ASSERT_TRUE(ui_test_utils::SendKeyPressSync( 116 browser(), ui::VKEY_F, true, true, false, false)); 117 118 // activeTab should now be granted. 119 EXPECT_TRUE(IsGrantedForTab(extension, tab)); 120 121 // Verify the command worked. 122 bool result = false; 123 ASSERT_TRUE(content::ExecuteScriptAndExtractBool( 124 tab, 125 "setInterval(function(){" 126 " if(document.body.bgColor == 'red'){" 127 " window.domAutomationController.send(true)}}, 100)", 128 &result)); 129 ASSERT_TRUE(result); 130 131 // Activate the shortcut (Ctrl+Shift+Y). 132 ASSERT_TRUE(ui_test_utils::SendKeyPressSync( 133 browser(), ui::VKEY_Y, true, true, false, false)); 134 135 result = false; 136 ASSERT_TRUE(content::ExecuteScriptAndExtractBool( 137 tab, 138 "setInterval(function(){" 139 " if(document.body.bgColor == 'blue'){" 140 " window.domAutomationController.send(true)}}, 100)", 141 &result)); 142 ASSERT_TRUE(result); 143 } 144 145 // Flaky on linux and chromeos, http://crbug.com/165825 146 #if defined(OS_MACOSX) || defined(OS_WIN) 147 #define MAYBE_PageAction PageAction 148 #else 149 #define MAYBE_PageAction DISABLED_PageAction 150 #endif 151 IN_PROC_BROWSER_TEST_F(CommandsApiTest, MAYBE_PageAction) { 152 ASSERT_TRUE(test_server()->Start()); 153 ASSERT_TRUE(RunExtensionTest("keybinding/page_action")) << message_; 154 const Extension* extension = GetSingleLoadedExtension(); 155 ASSERT_TRUE(extension) << message_; 156 157 { 158 // Load a page, the extension will detect the navigation and request to show 159 // the page action icon. 160 ResultCatcher catcher; 161 ui_test_utils::NavigateToURL(browser(), 162 test_server()->GetURL("files/extensions/test_file.txt")); 163 ASSERT_TRUE(catcher.GetNextResult()); 164 } 165 166 // Make sure it appears and is the right one. 167 ASSERT_TRUE(WaitForPageActionVisibilityChangeTo(1)); 168 int tab_id = SessionTabHelper::FromWebContents( 169 browser()->tab_strip_model()->GetActiveWebContents())->session_id().id(); 170 ExtensionAction* action = 171 ExtensionActionManager::Get(browser()->profile())-> 172 GetPageAction(*extension); 173 ASSERT_TRUE(action); 174 EXPECT_EQ("Make this page red", action->GetTitle(tab_id)); 175 176 // Activate the shortcut (Alt+Shift+F). 177 ASSERT_TRUE(ui_test_utils::SendKeyPressSync( 178 browser(), ui::VKEY_F, false, true, true, false)); 179 180 // Verify the command worked (the page action turns the page red). 181 WebContents* tab = browser()->tab_strip_model()->GetActiveWebContents(); 182 bool result = false; 183 ASSERT_TRUE(content::ExecuteScriptAndExtractBool( 184 tab, 185 "setInterval(function(){" 186 " if(document.body.bgColor == 'red'){" 187 " window.domAutomationController.send(true)}}, 100)", 188 &result)); 189 ASSERT_TRUE(result); 190 } 191 192 // This test validates that the getAll query API function returns registered 193 // commands as well as synthesized ones and that inactive commands (like the 194 // synthesized ones are in nature) have no shortcuts. 195 IN_PROC_BROWSER_TEST_F(CommandsApiTest, SynthesizedCommand) { 196 ASSERT_TRUE(test_server()->Start()); 197 ASSERT_TRUE(RunExtensionTest("keybinding/synthesized")) << message_; 198 } 199 200 // This test validates that an extension cannot request a shortcut that is 201 // already in use by Chrome. 202 IN_PROC_BROWSER_TEST_F(CommandsApiTest, DontOverwriteSystemShortcuts) { 203 ASSERT_TRUE(test_server()->Start()); 204 205 ASSERT_TRUE(ui_test_utils::BringBrowserWindowToFront(browser())); 206 207 ASSERT_TRUE(RunExtensionTest("keybinding/dont_overwrite_system")) << message_; 208 209 ui_test_utils::NavigateToURL(browser(), 210 test_server()->GetURL("files/extensions/test_file.txt")); 211 212 WebContents* tab = browser()->tab_strip_model()->GetActiveWebContents(); 213 ASSERT_TRUE(tab); 214 215 // Activate the shortcut (Alt+Shift+F) to make the page blue. 216 { 217 ResultCatcher catcher; 218 ASSERT_TRUE(ui_test_utils::SendKeyPressSync( 219 browser(), ui::VKEY_F, false, true, true, false)); 220 ASSERT_TRUE(catcher.GetNextResult()); 221 } 222 223 bool result = false; 224 ASSERT_TRUE(content::ExecuteScriptAndExtractBool( 225 tab, 226 "setInterval(function() {" 227 " if (document.body.bgColor == 'blue') {" 228 " window.domAutomationController.send(true)}}, 100)", 229 &result)); 230 ASSERT_TRUE(result); 231 232 // Activate the bookmark shortcut (Ctrl+D) to make the page green (should not 233 // work without requesting via chrome_settings_overrides). 234 #if defined(OS_MACOSX) 235 ASSERT_TRUE(ui_test_utils::SendKeyPressSync( 236 browser(), ui::VKEY_D, false, false, false, true)); 237 #else 238 ASSERT_TRUE(ui_test_utils::SendKeyPressSync( 239 browser(), ui::VKEY_D, true, false, false, false)); 240 #endif 241 242 // The page should still be blue. 243 result = false; 244 ASSERT_TRUE(content::ExecuteScriptAndExtractBool( 245 tab, 246 "setInterval(function() {" 247 " if (document.body.bgColor == 'blue') {" 248 " window.domAutomationController.send(true)}}, 100)", 249 &result)); 250 ASSERT_TRUE(result); 251 252 // Activate the shortcut (Ctrl+F) to make the page red (should not work). 253 ASSERT_TRUE(ui_test_utils::SendKeyPressSync( 254 browser(), ui::VKEY_F, true, false, false, false)); 255 256 // The page should still be blue. 257 result = false; 258 ASSERT_TRUE(content::ExecuteScriptAndExtractBool( 259 tab, 260 "setInterval(function() {" 261 " if (document.body.bgColor == 'blue') {" 262 " window.domAutomationController.send(true)}}, 100)", 263 &result)); 264 ASSERT_TRUE(result); 265 } 266 267 // This test validates that an extension can override the Chrome bookmark 268 // shortcut if it has requested to do so. 269 IN_PROC_BROWSER_TEST_F(CommandsApiTest, OverwriteBookmarkShortcut) { 270 ASSERT_TRUE(test_server()->Start()); 271 272 ASSERT_TRUE(ui_test_utils::BringBrowserWindowToFront(browser())); 273 274 // This functionality requires a feature flag. 275 CommandLine::ForCurrentProcess()->AppendSwitchASCII( 276 "--enable-override-bookmarks-ui", 277 "1"); 278 279 ASSERT_TRUE(RunExtensionTest("keybinding/overwrite_bookmark_shortcut")) 280 << message_; 281 282 ui_test_utils::NavigateToURL(browser(), 283 test_server()->GetURL("files/extensions/test_file.txt")); 284 285 WebContents* tab = browser()->tab_strip_model()->GetActiveWebContents(); 286 ASSERT_TRUE(tab); 287 288 // Activate the shortcut (Ctrl+D) to make the page green. 289 { 290 ResultCatcher catcher; 291 #if defined(OS_MACOSX) 292 ASSERT_TRUE(ui_test_utils::SendKeyPressSync( 293 browser(), ui::VKEY_D, false, false, false, true)); 294 #else 295 ASSERT_TRUE(ui_test_utils::SendKeyPressSync( 296 browser(), ui::VKEY_D, true, false, false, false)); 297 #endif 298 ASSERT_TRUE(catcher.GetNextResult()); 299 } 300 301 bool result = false; 302 ASSERT_TRUE(content::ExecuteScriptAndExtractBool( 303 tab, 304 "setInterval(function() {" 305 " if (document.body.bgColor == 'green') {" 306 " window.domAutomationController.send(true)}}, 100)", 307 &result)); 308 ASSERT_TRUE(result); 309 } 310 311 // This test validates that an extension override of the Chrome bookmark 312 // shortcut does not supersede the same keybinding by web pages. 313 IN_PROC_BROWSER_TEST_F(CommandsApiTest, 314 OverwriteBookmarkShortcutDoesNotOverrideWebKeybinding) { 315 ASSERT_TRUE(test_server()->Start()); 316 317 ASSERT_TRUE(ui_test_utils::BringBrowserWindowToFront(browser())); 318 319 // This functionality requires a feature flag. 320 CommandLine::ForCurrentProcess()->AppendSwitchASCII( 321 "--enable-override-bookmarks-ui", 322 "1"); 323 324 ASSERT_TRUE(RunExtensionTest("keybinding/overwrite_bookmark_shortcut")) 325 << message_; 326 327 ui_test_utils::NavigateToURL(browser(), 328 test_server()->GetURL( 329 "files/extensions/test_file_with_ctrl-d_keybinding.html")); 330 331 WebContents* tab = browser()->tab_strip_model()->GetActiveWebContents(); 332 ASSERT_TRUE(tab); 333 334 // Activate the shortcut (Ctrl+D) which should be handled by the page and make 335 // the background color magenta. 336 #if defined(OS_MACOSX) 337 ASSERT_TRUE(ui_test_utils::SendKeyPressSync( 338 browser(), ui::VKEY_D, false, false, false, true)); 339 #else 340 ASSERT_TRUE(ui_test_utils::SendKeyPressSync( 341 browser(), ui::VKEY_D, true, false, false, false)); 342 #endif 343 344 bool result = false; 345 ASSERT_TRUE(content::ExecuteScriptAndExtractBool( 346 tab, 347 "setInterval(function() {" 348 " if (document.body.bgColor == 'magenta') {" 349 " window.domAutomationController.send(true)}}, 100)", 350 &result)); 351 ASSERT_TRUE(result); 352 } 353 354 // This test validates that user-set override of the Chrome bookmark shortcut in 355 // an extension that does not request it does supersede the same keybinding by 356 // web pages. 357 IN_PROC_BROWSER_TEST_F(CommandsApiTest, 358 OverwriteBookmarkShortcutByUserOverridesWebKeybinding) { 359 ASSERT_TRUE(test_server()->Start()); 360 361 ASSERT_TRUE(ui_test_utils::BringBrowserWindowToFront(browser())); 362 363 // This functionality requires a feature flag. 364 CommandLine::ForCurrentProcess()->AppendSwitchASCII( 365 "--enable-override-bookmarks-ui", 366 "1"); 367 368 ASSERT_TRUE(RunExtensionTest("keybinding/basics")) 369 << message_; 370 371 CommandService* command_service = CommandService::Get(browser()->profile()); 372 373 const Extension* extension = GetSingleLoadedExtension(); 374 // Simulate the user setting the keybinding to Ctrl+D. 375 #if defined(OS_MACOSX) 376 const char* hotkey = "Command+D"; 377 #else 378 const char* hotkey = "Ctrl+D"; 379 #endif // defined(OS_MACOSX) 380 command_service->UpdateKeybindingPrefs( 381 extension->id(), manifest_values::kBrowserActionCommandEvent, hotkey); 382 383 ui_test_utils::NavigateToURL(browser(), 384 test_server()->GetURL( 385 "files/extensions/test_file_with_ctrl-d_keybinding.html")); 386 387 WebContents* tab = browser()->tab_strip_model()->GetActiveWebContents(); 388 ASSERT_TRUE(tab); 389 390 // Activate the shortcut (Ctrl+D) which should be handled by the extension and 391 // make the background color red. 392 #if defined(OS_MACOSX) 393 ASSERT_TRUE(ui_test_utils::SendKeyPressSync( 394 browser(), ui::VKEY_D, false, false, false, true)); 395 #else 396 ASSERT_TRUE(ui_test_utils::SendKeyPressSync( 397 browser(), ui::VKEY_D, true, false, false, false)); 398 #endif 399 400 bool result = false; 401 ASSERT_TRUE(content::ExecuteScriptAndExtractBool( 402 tab, 403 "setInterval(function() {" 404 " if (document.body.bgColor == 'red') {" 405 " window.domAutomationController.send(true)}}, 100)", 406 &result)); 407 ASSERT_TRUE(result); 408 } 409 410 #if defined(OS_WIN) 411 // Currently this feature is implemented on Windows only. 412 #define MAYBE_AllowDuplicatedMediaKeys AllowDuplicatedMediaKeys 413 #else 414 #define MAYBE_AllowDuplicatedMediaKeys DISABLED_AllowDuplicatedMediaKeys 415 #endif 416 417 // Test that media keys go to all extensions that register for them. 418 IN_PROC_BROWSER_TEST_F(CommandsApiTest, MAYBE_AllowDuplicatedMediaKeys) { 419 ResultCatcher catcher; 420 ASSERT_TRUE(RunExtensionTest("keybinding/non_global_media_keys_0")) 421 << message_; 422 ASSERT_TRUE(catcher.GetNextResult()); 423 ASSERT_TRUE(RunExtensionTest("keybinding/non_global_media_keys_1")) 424 << message_; 425 ASSERT_TRUE(catcher.GetNextResult()); 426 427 // Activate the Media Stop key. 428 ASSERT_TRUE(ui_test_utils::SendKeyPressSync( 429 browser(), ui::VKEY_MEDIA_STOP, false, false, false, false)); 430 431 // We should get two success result. 432 ASSERT_TRUE(catcher.GetNextResult()); 433 ASSERT_TRUE(catcher.GetNextResult()); 434 } 435 436 IN_PROC_BROWSER_TEST_F(CommandsApiTest, ShortcutAddedOnUpdate) { 437 base::ScopedTempDir scoped_temp_dir; 438 EXPECT_TRUE(scoped_temp_dir.CreateUniqueTempDir()); 439 base::FilePath pem_path = test_data_dir_. 440 AppendASCII("keybinding").AppendASCII("keybinding.pem"); 441 base::FilePath path_v1_unassigned = PackExtensionWithOptions( 442 test_data_dir_.AppendASCII("keybinding").AppendASCII("update") 443 .AppendASCII("v1_unassigned"), 444 scoped_temp_dir.path().AppendASCII("v1_unassigned.crx"), 445 pem_path, 446 base::FilePath()); 447 base::FilePath path_v2 = PackExtensionWithOptions( 448 test_data_dir_.AppendASCII("keybinding").AppendASCII("update") 449 .AppendASCII("v2"), 450 scoped_temp_dir.path().AppendASCII("v2.crx"), 451 pem_path, 452 base::FilePath()); 453 454 ExtensionRegistry* registry = ExtensionRegistry::Get(browser()->profile()); 455 CommandService* command_service = CommandService::Get(browser()->profile()); 456 457 // Install v1 of the extension without keybinding assigned. 458 ASSERT_TRUE(InstallExtension(path_v1_unassigned, 1)); 459 EXPECT_TRUE(registry->GetExtensionById(kId, ExtensionRegistry::ENABLED) != 460 NULL); 461 462 // Verify it is set to nothing. 463 ui::Accelerator accelerator = command_service->FindCommandByName( 464 kId, manifest_values::kBrowserActionCommandEvent).accelerator(); 465 EXPECT_EQ(ui::VKEY_UNKNOWN, accelerator.key_code()); 466 467 // Update to version 2 with keybinding. 468 EXPECT_TRUE(UpdateExtension(kId, path_v2, 0)); 469 EXPECT_TRUE(registry->GetExtensionById(kId, ExtensionRegistry::ENABLED) != 470 NULL); 471 472 // Verify it has a command of Alt+Shift+F. 473 accelerator = command_service->FindCommandByName( 474 kId, manifest_values::kBrowserActionCommandEvent).accelerator(); 475 EXPECT_EQ(ui::VKEY_F, accelerator.key_code()); 476 EXPECT_FALSE(accelerator.IsCtrlDown()); 477 EXPECT_TRUE(accelerator.IsShiftDown()); 478 EXPECT_TRUE(accelerator.IsAltDown()); 479 } 480 481 IN_PROC_BROWSER_TEST_F(CommandsApiTest, ShortcutChangedOnUpdate) { 482 base::ScopedTempDir scoped_temp_dir; 483 EXPECT_TRUE(scoped_temp_dir.CreateUniqueTempDir()); 484 base::FilePath pem_path = test_data_dir_. 485 AppendASCII("keybinding").AppendASCII("keybinding.pem"); 486 base::FilePath path_v1 = PackExtensionWithOptions( 487 test_data_dir_.AppendASCII("keybinding").AppendASCII("update") 488 .AppendASCII("v1"), 489 scoped_temp_dir.path().AppendASCII("v1.crx"), 490 pem_path, 491 base::FilePath()); 492 base::FilePath path_v2_reassigned = PackExtensionWithOptions( 493 test_data_dir_.AppendASCII("keybinding").AppendASCII("update") 494 .AppendASCII("v2_reassigned"), 495 scoped_temp_dir.path().AppendASCII("v2_reassigned.crx"), 496 pem_path, 497 base::FilePath()); 498 499 ExtensionRegistry* registry = ExtensionRegistry::Get(browser()->profile()); 500 CommandService* command_service = CommandService::Get(browser()->profile()); 501 502 // Install v1 of the extension. 503 ASSERT_TRUE(InstallExtension(path_v1, 1)); 504 EXPECT_TRUE(registry->GetExtensionById(kId, ExtensionRegistry::ENABLED) != 505 NULL); 506 507 // Verify it has a command of Alt+Shift+F. 508 ui::Accelerator accelerator = command_service->FindCommandByName( 509 kId, manifest_values::kBrowserActionCommandEvent).accelerator(); 510 EXPECT_EQ(ui::VKEY_F, accelerator.key_code()); 511 EXPECT_FALSE(accelerator.IsCtrlDown()); 512 EXPECT_TRUE(accelerator.IsShiftDown()); 513 EXPECT_TRUE(accelerator.IsAltDown()); 514 515 // Update to version 2 with different keybinding assigned. 516 EXPECT_TRUE(UpdateExtension(kId, path_v2_reassigned, 0)); 517 EXPECT_TRUE(registry->GetExtensionById(kId, ExtensionRegistry::ENABLED) != 518 NULL); 519 520 // Verify it has a command of Alt+Shift+H. 521 accelerator = command_service->FindCommandByName( 522 kId, manifest_values::kBrowserActionCommandEvent).accelerator(); 523 EXPECT_EQ(ui::VKEY_H, accelerator.key_code()); 524 EXPECT_FALSE(accelerator.IsCtrlDown()); 525 EXPECT_TRUE(accelerator.IsShiftDown()); 526 EXPECT_TRUE(accelerator.IsAltDown()); 527 } 528 529 IN_PROC_BROWSER_TEST_F(CommandsApiTest, ShortcutRemovedOnUpdate) { 530 base::ScopedTempDir scoped_temp_dir; 531 EXPECT_TRUE(scoped_temp_dir.CreateUniqueTempDir()); 532 base::FilePath pem_path = test_data_dir_. 533 AppendASCII("keybinding").AppendASCII("keybinding.pem"); 534 base::FilePath path_v1 = PackExtensionWithOptions( 535 test_data_dir_.AppendASCII("keybinding").AppendASCII("update") 536 .AppendASCII("v1"), 537 scoped_temp_dir.path().AppendASCII("v1.crx"), 538 pem_path, 539 base::FilePath()); 540 base::FilePath path_v2_unassigned = PackExtensionWithOptions( 541 test_data_dir_.AppendASCII("keybinding").AppendASCII("update") 542 .AppendASCII("v2_unassigned"), 543 scoped_temp_dir.path().AppendASCII("v2_unassigned.crx"), 544 pem_path, 545 base::FilePath()); 546 547 ExtensionRegistry* registry = ExtensionRegistry::Get(browser()->profile()); 548 CommandService* command_service = CommandService::Get(browser()->profile()); 549 550 // Install v1 of the extension. 551 ASSERT_TRUE(InstallExtension(path_v1, 1)); 552 EXPECT_TRUE(registry->GetExtensionById(kId, ExtensionRegistry::ENABLED) != 553 NULL); 554 555 // Verify it has a command of Alt+Shift+F. 556 ui::Accelerator accelerator = command_service->FindCommandByName( 557 kId, manifest_values::kBrowserActionCommandEvent).accelerator(); 558 EXPECT_EQ(ui::VKEY_F, accelerator.key_code()); 559 EXPECT_FALSE(accelerator.IsCtrlDown()); 560 EXPECT_TRUE(accelerator.IsShiftDown()); 561 EXPECT_TRUE(accelerator.IsAltDown()); 562 563 // Update to version 2 without keybinding assigned. 564 EXPECT_TRUE(UpdateExtension(kId, path_v2_unassigned, 0)); 565 EXPECT_TRUE(registry->GetExtensionById(kId, ExtensionRegistry::ENABLED) != 566 NULL); 567 568 // Verify the keybinding gets set to nothing. 569 accelerator = command_service->FindCommandByName( 570 kId, manifest_values::kBrowserActionCommandEvent).accelerator(); 571 EXPECT_EQ(ui::VKEY_UNKNOWN, accelerator.key_code()); 572 } 573 574 IN_PROC_BROWSER_TEST_F(CommandsApiTest, 575 ShortcutAddedOnUpdateAfterBeingAssignedByUser) { 576 base::ScopedTempDir scoped_temp_dir; 577 EXPECT_TRUE(scoped_temp_dir.CreateUniqueTempDir()); 578 base::FilePath pem_path = test_data_dir_. 579 AppendASCII("keybinding").AppendASCII("keybinding.pem"); 580 base::FilePath path_v1_unassigned = PackExtensionWithOptions( 581 test_data_dir_.AppendASCII("keybinding").AppendASCII("update") 582 .AppendASCII("v1_unassigned"), 583 scoped_temp_dir.path().AppendASCII("v1_unassigned.crx"), 584 pem_path, 585 base::FilePath()); 586 base::FilePath path_v2 = PackExtensionWithOptions( 587 test_data_dir_.AppendASCII("keybinding").AppendASCII("update") 588 .AppendASCII("v2"), 589 scoped_temp_dir.path().AppendASCII("v2.crx"), 590 pem_path, 591 base::FilePath()); 592 593 ExtensionRegistry* registry = ExtensionRegistry::Get(browser()->profile()); 594 CommandService* command_service = CommandService::Get(browser()->profile()); 595 596 // Install v1 of the extension without keybinding assigned. 597 ASSERT_TRUE(InstallExtension(path_v1_unassigned, 1)); 598 EXPECT_TRUE(registry->GetExtensionById(kId, ExtensionRegistry::ENABLED) != 599 NULL); 600 601 // Verify it is set to nothing. 602 ui::Accelerator accelerator = command_service->FindCommandByName( 603 kId, manifest_values::kBrowserActionCommandEvent).accelerator(); 604 EXPECT_EQ(ui::VKEY_UNKNOWN, accelerator.key_code()); 605 606 // Simulate the user setting the keybinding to Alt+Shift+G. 607 command_service->UpdateKeybindingPrefs( 608 kId, manifest_values::kBrowserActionCommandEvent, kAltShiftG); 609 610 // Update to version 2 with keybinding. 611 EXPECT_TRUE(UpdateExtension(kId, path_v2, 0)); 612 EXPECT_TRUE(registry->GetExtensionById(kId, ExtensionRegistry::ENABLED) != 613 NULL); 614 615 // Verify the previously-set keybinding is still set. 616 accelerator = command_service->FindCommandByName( 617 kId, manifest_values::kBrowserActionCommandEvent).accelerator(); 618 EXPECT_EQ(ui::VKEY_G, accelerator.key_code()); 619 EXPECT_FALSE(accelerator.IsCtrlDown()); 620 EXPECT_TRUE(accelerator.IsShiftDown()); 621 EXPECT_TRUE(accelerator.IsAltDown()); 622 } 623 624 IN_PROC_BROWSER_TEST_F(CommandsApiTest, 625 ShortcutChangedOnUpdateAfterBeingReassignedByUser) { 626 base::ScopedTempDir scoped_temp_dir; 627 EXPECT_TRUE(scoped_temp_dir.CreateUniqueTempDir()); 628 base::FilePath pem_path = test_data_dir_. 629 AppendASCII("keybinding").AppendASCII("keybinding.pem"); 630 base::FilePath path_v1 = PackExtensionWithOptions( 631 test_data_dir_.AppendASCII("keybinding").AppendASCII("update") 632 .AppendASCII("v1"), 633 scoped_temp_dir.path().AppendASCII("v1.crx"), 634 pem_path, 635 base::FilePath()); 636 base::FilePath path_v2_reassigned = PackExtensionWithOptions( 637 test_data_dir_.AppendASCII("keybinding").AppendASCII("update") 638 .AppendASCII("v2_reassigned"), 639 scoped_temp_dir.path().AppendASCII("v2_reassigned.crx"), 640 pem_path, 641 base::FilePath()); 642 643 ExtensionRegistry* registry = ExtensionRegistry::Get(browser()->profile()); 644 CommandService* command_service = CommandService::Get(browser()->profile()); 645 646 // Install v1 of the extension. 647 ASSERT_TRUE(InstallExtension(path_v1, 1)); 648 EXPECT_TRUE(registry->GetExtensionById(kId, ExtensionRegistry::ENABLED) != 649 NULL); 650 651 // Verify it has a command of Alt+Shift+F. 652 ui::Accelerator accelerator = command_service->FindCommandByName( 653 kId, manifest_values::kBrowserActionCommandEvent).accelerator(); 654 EXPECT_EQ(ui::VKEY_F, accelerator.key_code()); 655 EXPECT_FALSE(accelerator.IsCtrlDown()); 656 EXPECT_TRUE(accelerator.IsShiftDown()); 657 EXPECT_TRUE(accelerator.IsAltDown()); 658 659 // Simulate the user setting the keybinding to Alt+Shift+G. 660 command_service->UpdateKeybindingPrefs( 661 kId, manifest_values::kBrowserActionCommandEvent, kAltShiftG); 662 663 // Update to version 2 with different keybinding assigned. 664 EXPECT_TRUE(UpdateExtension(kId, path_v2_reassigned, 0)); 665 EXPECT_TRUE(registry->GetExtensionById(kId, ExtensionRegistry::ENABLED) != 666 NULL); 667 668 // Verify it has a command of Alt+Shift+G. 669 accelerator = command_service->FindCommandByName( 670 kId, manifest_values::kBrowserActionCommandEvent).accelerator(); 671 EXPECT_EQ(ui::VKEY_G, accelerator.key_code()); 672 EXPECT_FALSE(accelerator.IsCtrlDown()); 673 EXPECT_TRUE(accelerator.IsShiftDown()); 674 EXPECT_TRUE(accelerator.IsAltDown()); 675 } 676 677 IN_PROC_BROWSER_TEST_F(CommandsApiTest, 678 ShortcutRemovedOnUpdateAfterBeingReassignedByUser) { 679 base::ScopedTempDir scoped_temp_dir; 680 EXPECT_TRUE(scoped_temp_dir.CreateUniqueTempDir()); 681 base::FilePath pem_path = test_data_dir_. 682 AppendASCII("keybinding").AppendASCII("keybinding.pem"); 683 base::FilePath path_v1 = PackExtensionWithOptions( 684 test_data_dir_.AppendASCII("keybinding").AppendASCII("update") 685 .AppendASCII("v1"), 686 scoped_temp_dir.path().AppendASCII("v1.crx"), 687 pem_path, 688 base::FilePath()); 689 base::FilePath path_v2_unassigned = PackExtensionWithOptions( 690 test_data_dir_.AppendASCII("keybinding").AppendASCII("update") 691 .AppendASCII("v2_unassigned"), 692 scoped_temp_dir.path().AppendASCII("v2_unassigned.crx"), 693 pem_path, 694 base::FilePath()); 695 696 ExtensionRegistry* registry = ExtensionRegistry::Get(browser()->profile()); 697 CommandService* command_service = CommandService::Get(browser()->profile()); 698 699 // Install v1 of the extension. 700 ASSERT_TRUE(InstallExtension(path_v1, 1)); 701 EXPECT_TRUE(registry->GetExtensionById(kId, ExtensionRegistry::ENABLED) != 702 NULL); 703 704 // Verify it has a command of Alt+Shift+F. 705 ui::Accelerator accelerator = command_service->FindCommandByName( 706 kId, manifest_values::kBrowserActionCommandEvent).accelerator(); 707 EXPECT_EQ(ui::VKEY_F, accelerator.key_code()); 708 EXPECT_FALSE(accelerator.IsCtrlDown()); 709 EXPECT_TRUE(accelerator.IsShiftDown()); 710 EXPECT_TRUE(accelerator.IsAltDown()); 711 712 // Simulate the user reassigning the keybinding to Alt+Shift+G. 713 command_service->UpdateKeybindingPrefs( 714 kId, manifest_values::kBrowserActionCommandEvent, kAltShiftG); 715 716 // Update to version 2 without keybinding assigned. 717 EXPECT_TRUE(UpdateExtension(kId, path_v2_unassigned, 0)); 718 EXPECT_TRUE(registry->GetExtensionById(kId, ExtensionRegistry::ENABLED) != 719 NULL); 720 721 // Verify the keybinding is still set. 722 accelerator = command_service->FindCommandByName( 723 kId, manifest_values::kBrowserActionCommandEvent).accelerator(); 724 EXPECT_EQ(ui::VKEY_G, accelerator.key_code()); 725 EXPECT_FALSE(accelerator.IsCtrlDown()); 726 EXPECT_TRUE(accelerator.IsShiftDown()); 727 EXPECT_TRUE(accelerator.IsAltDown()); 728 } 729 730 // 731 #if defined(OS_CHROMEOS) && !defined(NDEBUG) 732 // TODO(dtseng): Test times out on Chrome OS debug. See http://crbug.com/412456. 733 #define MAYBE_ContinuePropagation DISABLED_ContinuePropagation 734 #else 735 #define MAYBE_ContinuePropagation ContinuePropagation 736 #endif 737 738 IN_PROC_BROWSER_TEST_F(CommandsApiTest, MAYBE_ContinuePropagation) { 739 // Setup the environment. 740 ASSERT_TRUE(test_server()->Start()); 741 ASSERT_TRUE(ui_test_utils::BringBrowserWindowToFront(browser())); 742 ASSERT_TRUE(RunExtensionTest("keybinding/continue_propagation")) << message_; 743 ui_test_utils::NavigateToURL( 744 browser(), test_server()->GetURL("files/extensions/test_file.txt")); 745 746 ResultCatcher catcher; 747 748 // Activate the shortcut (Ctrl+Shift+F). The page should capture the 749 // keystroke and not the extension since |onCommand| has no event listener 750 // initially. 751 ASSERT_TRUE(ui_test_utils::SendKeyPressSync( 752 browser(), ui::VKEY_F, true, true, false, false)); 753 ASSERT_TRUE(catcher.GetNextResult()); 754 755 // Now, the extension should have added an |onCommand| event listener. 756 // Send the same key, but the |onCommand| listener should now receive it. 757 ASSERT_TRUE(ui_test_utils::SendKeyPressSync( 758 browser(), ui::VKEY_F, true, true, false, false)); 759 ASSERT_TRUE(catcher.GetNextResult()); 760 761 // The extension should now have removed its |onCommand| event listener. 762 // Finally, the page should again receive the key. 763 ASSERT_TRUE(ui_test_utils::SendKeyPressSync( 764 browser(), ui::VKEY_F, true, true, false, false)); 765 ASSERT_TRUE(catcher.GetNextResult()); 766 } 767 768 // Test is only applicable on Chrome OS. 769 #if defined(OS_CHROMEOS) 770 // http://crbug.com/410534 771 #if defined(USE_OZONE) 772 #define MAYBE_ChromeOSConversions DISABLED_ChromeOSConversions 773 #else 774 #define MAYBE_ChromeOSConversions ChromeOSConversions 775 #endif 776 IN_PROC_BROWSER_TEST_F(CommandsApiTest, MAYBE_ChromeOSConversions) { 777 RunChromeOSConversionTest("keybinding/chromeos_conversions"); 778 } 779 #endif // OS_CHROMEOS 780 781 } // namespace extensions 782