Home | History | Annotate | Download | only in extensions
      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