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
27using content::WebContents;
28
29namespace extensions {
30
31namespace {
32// This extension ID is used for tests require a stable ID over multiple
33// extension installs.
34const char kId[] = "pgoakhfeplldmjheffidklpoklkppipp";
35
36// Default keybinding to use for emulating user-defined shortcut overrides. The
37// test extensions use Alt+Shift+F and Alt+Shift+H.
38const char kAltShiftG[] = "Alt+Shift+G";
39}
40
41class CommandsApiTest : public ExtensionApiTest {
42 public:
43  CommandsApiTest() {}
44  virtual ~CommandsApiTest() {}
45
46 protected:
47  BrowserActionTestUtil GetBrowserActionsBar() {
48    return BrowserActionTestUtil(browser());
49  }
50
51  bool IsGrantedForTab(const Extension* extension,
52                       const content::WebContents* web_contents) {
53    return extension->permissions_data()->HasAPIPermissionForTab(
54        SessionID::IdForTab(web_contents), APIPermission::kTab);
55  }
56};
57
58// Test the basic functionality of the Keybinding API:
59// - That pressing the shortcut keys should perform actions (activate the
60//   browser action or send an event).
61// - Note: Page action keybindings are tested in PageAction test below.
62// - The shortcut keys taken by one extension are not overwritten by the last
63//   installed extension.
64IN_PROC_BROWSER_TEST_F(CommandsApiTest, Basic) {
65  ASSERT_TRUE(test_server()->Start());
66  ASSERT_TRUE(RunExtensionTest("keybinding/basics")) << message_;
67  const Extension* extension = GetSingleLoadedExtension();
68  ASSERT_TRUE(extension) << message_;
69
70  // Load this extension, which uses the same keybindings but sets the page
71  // to different colors. This is so we can see that it doesn't interfere. We
72  // don't test this extension in any other way (it should otherwise be
73  // immaterial to this test).
74  ASSERT_TRUE(RunExtensionTest("keybinding/conflicting")) << message_;
75
76  // Test that there are two browser actions in the toolbar.
77  ASSERT_EQ(2, GetBrowserActionsBar().NumberOfBrowserActions());
78
79  ui_test_utils::NavigateToURL(browser(),
80      test_server()->GetURL("files/extensions/test_file.txt"));
81
82  // activeTab shouldn't have been granted yet.
83  WebContents* tab = browser()->tab_strip_model()->GetActiveWebContents();
84  ASSERT_TRUE(tab);
85
86  EXPECT_FALSE(IsGrantedForTab(extension, tab));
87
88  // Activate the shortcut (Ctrl+Shift+F).
89  ASSERT_TRUE(ui_test_utils::SendKeyPressSync(
90      browser(), ui::VKEY_F, true, true, false, false));
91
92  // activeTab should now be granted.
93  EXPECT_TRUE(IsGrantedForTab(extension, tab));
94
95  // Verify the command worked.
96  bool result = false;
97  ASSERT_TRUE(content::ExecuteScriptAndExtractBool(
98      tab,
99      "setInterval(function(){"
100      "  if(document.body.bgColor == 'red'){"
101      "    window.domAutomationController.send(true)}}, 100)",
102      &result));
103  ASSERT_TRUE(result);
104
105  // Activate the shortcut (Ctrl+Shift+Y).
106  ASSERT_TRUE(ui_test_utils::SendKeyPressSync(
107      browser(), ui::VKEY_Y, true, true, false, false));
108
109  result = false;
110  ASSERT_TRUE(content::ExecuteScriptAndExtractBool(
111      tab,
112      "setInterval(function(){"
113      "  if(document.body.bgColor == 'blue'){"
114      "    window.domAutomationController.send(true)}}, 100)",
115      &result));
116  ASSERT_TRUE(result);
117}
118
119// Flaky on linux and chromeos, http://crbug.com/165825
120#if defined(OS_MACOSX) || defined(OS_WIN)
121#define MAYBE_PageAction PageAction
122#else
123#define MAYBE_PageAction DISABLED_PageAction
124#endif
125IN_PROC_BROWSER_TEST_F(CommandsApiTest, MAYBE_PageAction) {
126  ASSERT_TRUE(test_server()->Start());
127  ASSERT_TRUE(RunExtensionTest("keybinding/page_action")) << message_;
128  const Extension* extension = GetSingleLoadedExtension();
129  ASSERT_TRUE(extension) << message_;
130
131  {
132    // Load a page, the extension will detect the navigation and request to show
133    // the page action icon.
134    ResultCatcher catcher;
135    ui_test_utils::NavigateToURL(browser(),
136        test_server()->GetURL("files/extensions/test_file.txt"));
137    ASSERT_TRUE(catcher.GetNextResult());
138  }
139
140  // Make sure it appears and is the right one.
141  ASSERT_TRUE(WaitForPageActionVisibilityChangeTo(1));
142  int tab_id = SessionTabHelper::FromWebContents(
143      browser()->tab_strip_model()->GetActiveWebContents())->session_id().id();
144  ExtensionAction* action =
145      ExtensionActionManager::Get(browser()->profile())->
146      GetPageAction(*extension);
147  ASSERT_TRUE(action);
148  EXPECT_EQ("Make this page red", action->GetTitle(tab_id));
149
150  // Activate the shortcut (Alt+Shift+F).
151  ASSERT_TRUE(ui_test_utils::SendKeyPressSync(
152      browser(), ui::VKEY_F, false, true, true, false));
153
154  // Verify the command worked (the page action turns the page red).
155  WebContents* tab = browser()->tab_strip_model()->GetActiveWebContents();
156  bool result = false;
157  ASSERT_TRUE(content::ExecuteScriptAndExtractBool(
158      tab,
159      "setInterval(function(){"
160      "  if(document.body.bgColor == 'red'){"
161      "    window.domAutomationController.send(true)}}, 100)",
162      &result));
163  ASSERT_TRUE(result);
164}
165
166// This test validates that the getAll query API function returns registered
167// commands as well as synthesized ones and that inactive commands (like the
168// synthesized ones are in nature) have no shortcuts.
169IN_PROC_BROWSER_TEST_F(CommandsApiTest, SynthesizedCommand) {
170  ASSERT_TRUE(test_server()->Start());
171  ASSERT_TRUE(RunExtensionTest("keybinding/synthesized")) << message_;
172}
173
174// This test validates that an extension cannot request a shortcut that is
175// already in use by Chrome.
176IN_PROC_BROWSER_TEST_F(CommandsApiTest, DontOverwriteSystemShortcuts) {
177  ASSERT_TRUE(test_server()->Start());
178
179  ASSERT_TRUE(ui_test_utils::BringBrowserWindowToFront(browser()));
180
181  ASSERT_TRUE(RunExtensionTest("keybinding/dont_overwrite_system")) << message_;
182
183  ui_test_utils::NavigateToURL(browser(),
184      test_server()->GetURL("files/extensions/test_file.txt"));
185
186  WebContents* tab = browser()->tab_strip_model()->GetActiveWebContents();
187  ASSERT_TRUE(tab);
188
189  // Activate the shortcut (Alt+Shift+F) to make the page blue.
190  {
191    ResultCatcher catcher;
192    ASSERT_TRUE(ui_test_utils::SendKeyPressSync(
193        browser(), ui::VKEY_F, false, true, true, false));
194    ASSERT_TRUE(catcher.GetNextResult());
195  }
196
197  bool result = false;
198  ASSERT_TRUE(content::ExecuteScriptAndExtractBool(
199      tab,
200      "setInterval(function() {"
201      "  if (document.body.bgColor == 'blue') {"
202      "    window.domAutomationController.send(true)}}, 100)",
203      &result));
204  ASSERT_TRUE(result);
205
206  // Activate the bookmark shortcut (Ctrl+D) to make the page green (should not
207  // work without requesting via chrome_settings_overrides).
208#if defined(OS_MACOSX)
209    ASSERT_TRUE(ui_test_utils::SendKeyPressSync(
210        browser(), ui::VKEY_D, false, false, false, true));
211#else
212    ASSERT_TRUE(ui_test_utils::SendKeyPressSync(
213        browser(), ui::VKEY_D, true, false, false, false));
214#endif
215
216  // The page should still be blue.
217  result = false;
218  ASSERT_TRUE(content::ExecuteScriptAndExtractBool(
219      tab,
220      "setInterval(function() {"
221      "  if (document.body.bgColor == 'blue') {"
222      "    window.domAutomationController.send(true)}}, 100)",
223      &result));
224  ASSERT_TRUE(result);
225
226  // Activate the shortcut (Ctrl+F) to make the page red (should not work).
227  ASSERT_TRUE(ui_test_utils::SendKeyPressSync(
228      browser(), ui::VKEY_F, true, false, false, false));
229
230  // The page should still be blue.
231  result = false;
232  ASSERT_TRUE(content::ExecuteScriptAndExtractBool(
233      tab,
234      "setInterval(function() {"
235      "  if (document.body.bgColor == 'blue') {"
236      "    window.domAutomationController.send(true)}}, 100)",
237      &result));
238  ASSERT_TRUE(result);
239}
240
241// This test validates that an extension can override the Chrome bookmark
242// shortcut if it has requested to do so.
243IN_PROC_BROWSER_TEST_F(CommandsApiTest, OverwriteBookmarkShortcut) {
244  ASSERT_TRUE(test_server()->Start());
245
246  ASSERT_TRUE(ui_test_utils::BringBrowserWindowToFront(browser()));
247
248  // This functionality requires a feature flag.
249  CommandLine::ForCurrentProcess()->AppendSwitchASCII(
250      "--enable-override-bookmarks-ui",
251      "1");
252
253  ASSERT_TRUE(RunExtensionTest("keybinding/overwrite_bookmark_shortcut"))
254      << message_;
255
256  ui_test_utils::NavigateToURL(browser(),
257      test_server()->GetURL("files/extensions/test_file.txt"));
258
259  WebContents* tab = browser()->tab_strip_model()->GetActiveWebContents();
260  ASSERT_TRUE(tab);
261
262  // Activate the shortcut (Ctrl+D) to make the page green.
263  {
264    ResultCatcher catcher;
265#if defined(OS_MACOSX)
266    ASSERT_TRUE(ui_test_utils::SendKeyPressSync(
267        browser(), ui::VKEY_D, false, false, false, true));
268#else
269    ASSERT_TRUE(ui_test_utils::SendKeyPressSync(
270        browser(), ui::VKEY_D, true, false, false, false));
271#endif
272    ASSERT_TRUE(catcher.GetNextResult());
273  }
274
275  bool result = false;
276  ASSERT_TRUE(content::ExecuteScriptAndExtractBool(
277      tab,
278      "setInterval(function() {"
279      "  if (document.body.bgColor == 'green') {"
280      "    window.domAutomationController.send(true)}}, 100)",
281      &result));
282  ASSERT_TRUE(result);
283}
284
285#if defined(OS_WIN)
286// Currently this feature is implemented on Windows only.
287#define MAYBE_AllowDuplicatedMediaKeys AllowDuplicatedMediaKeys
288#else
289#define MAYBE_AllowDuplicatedMediaKeys DISABLED_AllowDuplicatedMediaKeys
290#endif
291
292// Test that media keys go to all extensions that register for them.
293IN_PROC_BROWSER_TEST_F(CommandsApiTest, MAYBE_AllowDuplicatedMediaKeys) {
294  ResultCatcher catcher;
295  ASSERT_TRUE(RunExtensionTest("keybinding/non_global_media_keys_0"))
296      << message_;
297  ASSERT_TRUE(catcher.GetNextResult());
298  ASSERT_TRUE(RunExtensionTest("keybinding/non_global_media_keys_1"))
299      << message_;
300  ASSERT_TRUE(catcher.GetNextResult());
301
302  // Activate the Media Stop key.
303  ASSERT_TRUE(ui_test_utils::SendKeyPressSync(
304      browser(), ui::VKEY_MEDIA_STOP, false, false, false, false));
305
306  // We should get two success result.
307  ASSERT_TRUE(catcher.GetNextResult());
308  ASSERT_TRUE(catcher.GetNextResult());
309}
310
311IN_PROC_BROWSER_TEST_F(CommandsApiTest, ShortcutAddedOnUpdate) {
312  base::ScopedTempDir scoped_temp_dir;
313  EXPECT_TRUE(scoped_temp_dir.CreateUniqueTempDir());
314  base::FilePath pem_path = test_data_dir_.
315      AppendASCII("keybinding").AppendASCII("keybinding.pem");
316  base::FilePath path_v1_unassigned = PackExtensionWithOptions(
317      test_data_dir_.AppendASCII("keybinding").AppendASCII("update")
318                    .AppendASCII("v1_unassigned"),
319      scoped_temp_dir.path().AppendASCII("v1_unassigned.crx"),
320      pem_path,
321      base::FilePath());
322  base::FilePath path_v2 = PackExtensionWithOptions(
323      test_data_dir_.AppendASCII("keybinding").AppendASCII("update")
324                    .AppendASCII("v2"),
325      scoped_temp_dir.path().AppendASCII("v2.crx"),
326      pem_path,
327      base::FilePath());
328
329  ExtensionRegistry* registry = ExtensionRegistry::Get(browser()->profile());
330  CommandService* command_service = CommandService::Get(browser()->profile());
331
332  // Install v1 of the extension without keybinding assigned.
333  ASSERT_TRUE(InstallExtension(path_v1_unassigned, 1));
334  EXPECT_TRUE(registry->GetExtensionById(kId, ExtensionRegistry::ENABLED) !=
335              NULL);
336
337  // Verify it is set to nothing.
338  ui::Accelerator accelerator = command_service->FindCommandByName(
339      kId, manifest_values::kBrowserActionCommandEvent).accelerator();
340  EXPECT_EQ(ui::VKEY_UNKNOWN, accelerator.key_code());
341
342  // Update to version 2 with keybinding.
343  EXPECT_TRUE(UpdateExtension(kId, path_v2, 0));
344  EXPECT_TRUE(registry->GetExtensionById(kId, ExtensionRegistry::ENABLED) !=
345              NULL);
346
347  // Verify it has a command of Alt+Shift+F.
348  accelerator = command_service->FindCommandByName(
349      kId, manifest_values::kBrowserActionCommandEvent).accelerator();
350  EXPECT_EQ(ui::VKEY_F, accelerator.key_code());
351  EXPECT_FALSE(accelerator.IsCtrlDown());
352  EXPECT_TRUE(accelerator.IsShiftDown());
353  EXPECT_TRUE(accelerator.IsAltDown());
354}
355
356IN_PROC_BROWSER_TEST_F(CommandsApiTest, ShortcutChangedOnUpdate) {
357  base::ScopedTempDir scoped_temp_dir;
358  EXPECT_TRUE(scoped_temp_dir.CreateUniqueTempDir());
359  base::FilePath pem_path = test_data_dir_.
360      AppendASCII("keybinding").AppendASCII("keybinding.pem");
361  base::FilePath path_v1 = PackExtensionWithOptions(
362      test_data_dir_.AppendASCII("keybinding").AppendASCII("update")
363                    .AppendASCII("v1"),
364      scoped_temp_dir.path().AppendASCII("v1.crx"),
365      pem_path,
366      base::FilePath());
367  base::FilePath path_v2_reassigned = PackExtensionWithOptions(
368      test_data_dir_.AppendASCII("keybinding").AppendASCII("update")
369                    .AppendASCII("v2_reassigned"),
370      scoped_temp_dir.path().AppendASCII("v2_reassigned.crx"),
371      pem_path,
372      base::FilePath());
373
374  ExtensionRegistry* registry = ExtensionRegistry::Get(browser()->profile());
375  CommandService* command_service = CommandService::Get(browser()->profile());
376
377  // Install v1 of the extension.
378  ASSERT_TRUE(InstallExtension(path_v1, 1));
379  EXPECT_TRUE(registry->GetExtensionById(kId, ExtensionRegistry::ENABLED) !=
380              NULL);
381
382  // Verify it has a command of Alt+Shift+F.
383  ui::Accelerator accelerator = command_service->FindCommandByName(
384      kId, manifest_values::kBrowserActionCommandEvent).accelerator();
385  EXPECT_EQ(ui::VKEY_F, accelerator.key_code());
386  EXPECT_FALSE(accelerator.IsCtrlDown());
387  EXPECT_TRUE(accelerator.IsShiftDown());
388  EXPECT_TRUE(accelerator.IsAltDown());
389
390  // Update to version 2 with different keybinding assigned.
391  EXPECT_TRUE(UpdateExtension(kId, path_v2_reassigned, 0));
392  EXPECT_TRUE(registry->GetExtensionById(kId, ExtensionRegistry::ENABLED) !=
393              NULL);
394
395  // Verify it has a command of Alt+Shift+H.
396  accelerator = command_service->FindCommandByName(
397      kId, manifest_values::kBrowserActionCommandEvent).accelerator();
398  EXPECT_EQ(ui::VKEY_H, accelerator.key_code());
399  EXPECT_FALSE(accelerator.IsCtrlDown());
400  EXPECT_TRUE(accelerator.IsShiftDown());
401  EXPECT_TRUE(accelerator.IsAltDown());
402}
403
404IN_PROC_BROWSER_TEST_F(CommandsApiTest, ShortcutRemovedOnUpdate) {
405  base::ScopedTempDir scoped_temp_dir;
406  EXPECT_TRUE(scoped_temp_dir.CreateUniqueTempDir());
407  base::FilePath pem_path = test_data_dir_.
408      AppendASCII("keybinding").AppendASCII("keybinding.pem");
409  base::FilePath path_v1 = PackExtensionWithOptions(
410      test_data_dir_.AppendASCII("keybinding").AppendASCII("update")
411                    .AppendASCII("v1"),
412      scoped_temp_dir.path().AppendASCII("v1.crx"),
413      pem_path,
414      base::FilePath());
415  base::FilePath path_v2_unassigned = PackExtensionWithOptions(
416      test_data_dir_.AppendASCII("keybinding").AppendASCII("update")
417                    .AppendASCII("v2_unassigned"),
418      scoped_temp_dir.path().AppendASCII("v2_unassigned.crx"),
419      pem_path,
420      base::FilePath());
421
422  ExtensionRegistry* registry = ExtensionRegistry::Get(browser()->profile());
423  CommandService* command_service = CommandService::Get(browser()->profile());
424
425  // Install v1 of the extension.
426  ASSERT_TRUE(InstallExtension(path_v1, 1));
427  EXPECT_TRUE(registry->GetExtensionById(kId, ExtensionRegistry::ENABLED) !=
428              NULL);
429
430  // Verify it has a command of Alt+Shift+F.
431  ui::Accelerator accelerator = command_service->FindCommandByName(
432      kId, manifest_values::kBrowserActionCommandEvent).accelerator();
433  EXPECT_EQ(ui::VKEY_F, accelerator.key_code());
434  EXPECT_FALSE(accelerator.IsCtrlDown());
435  EXPECT_TRUE(accelerator.IsShiftDown());
436  EXPECT_TRUE(accelerator.IsAltDown());
437
438  // Update to version 2 without keybinding assigned.
439  EXPECT_TRUE(UpdateExtension(kId, path_v2_unassigned, 0));
440  EXPECT_TRUE(registry->GetExtensionById(kId, ExtensionRegistry::ENABLED) !=
441              NULL);
442
443  // Verify the keybinding gets set to nothing.
444  accelerator = command_service->FindCommandByName(
445      kId, manifest_values::kBrowserActionCommandEvent).accelerator();
446  EXPECT_EQ(ui::VKEY_UNKNOWN, accelerator.key_code());
447}
448
449IN_PROC_BROWSER_TEST_F(CommandsApiTest,
450                       ShortcutAddedOnUpdateAfterBeingAssignedByUser) {
451  base::ScopedTempDir scoped_temp_dir;
452  EXPECT_TRUE(scoped_temp_dir.CreateUniqueTempDir());
453  base::FilePath pem_path = test_data_dir_.
454      AppendASCII("keybinding").AppendASCII("keybinding.pem");
455  base::FilePath path_v1_unassigned = PackExtensionWithOptions(
456      test_data_dir_.AppendASCII("keybinding").AppendASCII("update")
457                    .AppendASCII("v1_unassigned"),
458      scoped_temp_dir.path().AppendASCII("v1_unassigned.crx"),
459      pem_path,
460      base::FilePath());
461  base::FilePath path_v2 = PackExtensionWithOptions(
462      test_data_dir_.AppendASCII("keybinding").AppendASCII("update")
463                    .AppendASCII("v2"),
464      scoped_temp_dir.path().AppendASCII("v2.crx"),
465      pem_path,
466      base::FilePath());
467
468  ExtensionRegistry* registry = ExtensionRegistry::Get(browser()->profile());
469  CommandService* command_service = CommandService::Get(browser()->profile());
470
471  // Install v1 of the extension without keybinding assigned.
472  ASSERT_TRUE(InstallExtension(path_v1_unassigned, 1));
473  EXPECT_TRUE(registry->GetExtensionById(kId, ExtensionRegistry::ENABLED) !=
474              NULL);
475
476  // Verify it is set to nothing.
477  ui::Accelerator accelerator = command_service->FindCommandByName(
478      kId, manifest_values::kBrowserActionCommandEvent).accelerator();
479  EXPECT_EQ(ui::VKEY_UNKNOWN, accelerator.key_code());
480
481  // Simulate the user setting the keybinding to Alt+Shift+G.
482  command_service->UpdateKeybindingPrefs(
483      kId, manifest_values::kBrowserActionCommandEvent, kAltShiftG);
484
485  // Update to version 2 with keybinding.
486  EXPECT_TRUE(UpdateExtension(kId, path_v2, 0));
487  EXPECT_TRUE(registry->GetExtensionById(kId, ExtensionRegistry::ENABLED) !=
488              NULL);
489
490  // Verify the previously-set keybinding is still set.
491  accelerator = command_service->FindCommandByName(
492      kId, manifest_values::kBrowserActionCommandEvent).accelerator();
493  EXPECT_EQ(ui::VKEY_G, accelerator.key_code());
494  EXPECT_FALSE(accelerator.IsCtrlDown());
495  EXPECT_TRUE(accelerator.IsShiftDown());
496  EXPECT_TRUE(accelerator.IsAltDown());
497}
498
499IN_PROC_BROWSER_TEST_F(CommandsApiTest,
500                       ShortcutChangedOnUpdateAfterBeingReassignedByUser) {
501  base::ScopedTempDir scoped_temp_dir;
502  EXPECT_TRUE(scoped_temp_dir.CreateUniqueTempDir());
503  base::FilePath pem_path = test_data_dir_.
504      AppendASCII("keybinding").AppendASCII("keybinding.pem");
505  base::FilePath path_v1 = PackExtensionWithOptions(
506      test_data_dir_.AppendASCII("keybinding").AppendASCII("update")
507                    .AppendASCII("v1"),
508      scoped_temp_dir.path().AppendASCII("v1.crx"),
509      pem_path,
510      base::FilePath());
511  base::FilePath path_v2_reassigned = PackExtensionWithOptions(
512      test_data_dir_.AppendASCII("keybinding").AppendASCII("update")
513                    .AppendASCII("v2_reassigned"),
514      scoped_temp_dir.path().AppendASCII("v2_reassigned.crx"),
515      pem_path,
516      base::FilePath());
517
518  ExtensionRegistry* registry = ExtensionRegistry::Get(browser()->profile());
519  CommandService* command_service = CommandService::Get(browser()->profile());
520
521  // Install v1 of the extension.
522  ASSERT_TRUE(InstallExtension(path_v1, 1));
523  EXPECT_TRUE(registry->GetExtensionById(kId, ExtensionRegistry::ENABLED) !=
524              NULL);
525
526  // Verify it has a command of Alt+Shift+F.
527  ui::Accelerator accelerator = command_service->FindCommandByName(
528      kId, manifest_values::kBrowserActionCommandEvent).accelerator();
529  EXPECT_EQ(ui::VKEY_F, accelerator.key_code());
530  EXPECT_FALSE(accelerator.IsCtrlDown());
531  EXPECT_TRUE(accelerator.IsShiftDown());
532  EXPECT_TRUE(accelerator.IsAltDown());
533
534  // Simulate the user setting the keybinding to Alt+Shift+G.
535  command_service->UpdateKeybindingPrefs(
536      kId, manifest_values::kBrowserActionCommandEvent, kAltShiftG);
537
538  // Update to version 2 with different keybinding assigned.
539  EXPECT_TRUE(UpdateExtension(kId, path_v2_reassigned, 0));
540  EXPECT_TRUE(registry->GetExtensionById(kId, ExtensionRegistry::ENABLED) !=
541              NULL);
542
543  // Verify it has a command of Alt+Shift+G.
544  accelerator = command_service->FindCommandByName(
545      kId, manifest_values::kBrowserActionCommandEvent).accelerator();
546  EXPECT_EQ(ui::VKEY_G, accelerator.key_code());
547  EXPECT_FALSE(accelerator.IsCtrlDown());
548  EXPECT_TRUE(accelerator.IsShiftDown());
549  EXPECT_TRUE(accelerator.IsAltDown());
550}
551
552IN_PROC_BROWSER_TEST_F(CommandsApiTest,
553                       ShortcutRemovedOnUpdateAfterBeingReassignedByUser) {
554  base::ScopedTempDir scoped_temp_dir;
555  EXPECT_TRUE(scoped_temp_dir.CreateUniqueTempDir());
556  base::FilePath pem_path = test_data_dir_.
557      AppendASCII("keybinding").AppendASCII("keybinding.pem");
558  base::FilePath path_v1 = PackExtensionWithOptions(
559      test_data_dir_.AppendASCII("keybinding").AppendASCII("update")
560                    .AppendASCII("v1"),
561      scoped_temp_dir.path().AppendASCII("v1.crx"),
562      pem_path,
563      base::FilePath());
564  base::FilePath path_v2_unassigned = PackExtensionWithOptions(
565      test_data_dir_.AppendASCII("keybinding").AppendASCII("update")
566                    .AppendASCII("v2_unassigned"),
567      scoped_temp_dir.path().AppendASCII("v2_unassigned.crx"),
568      pem_path,
569      base::FilePath());
570
571  ExtensionRegistry* registry = ExtensionRegistry::Get(browser()->profile());
572  CommandService* command_service = CommandService::Get(browser()->profile());
573
574  // Install v1 of the extension.
575  ASSERT_TRUE(InstallExtension(path_v1, 1));
576  EXPECT_TRUE(registry->GetExtensionById(kId, ExtensionRegistry::ENABLED) !=
577              NULL);
578
579  // Verify it has a command of Alt+Shift+F.
580  ui::Accelerator accelerator = command_service->FindCommandByName(
581      kId, manifest_values::kBrowserActionCommandEvent).accelerator();
582  EXPECT_EQ(ui::VKEY_F, accelerator.key_code());
583  EXPECT_FALSE(accelerator.IsCtrlDown());
584  EXPECT_TRUE(accelerator.IsShiftDown());
585  EXPECT_TRUE(accelerator.IsAltDown());
586
587  // Simulate the user reassigning the keybinding to Alt+Shift+G.
588  command_service->UpdateKeybindingPrefs(
589      kId, manifest_values::kBrowserActionCommandEvent, kAltShiftG);
590
591  // Update to version 2 without keybinding assigned.
592  EXPECT_TRUE(UpdateExtension(kId, path_v2_unassigned, 0));
593  EXPECT_TRUE(registry->GetExtensionById(kId, ExtensionRegistry::ENABLED) !=
594              NULL);
595
596  // Verify the keybinding is still set.
597  accelerator = command_service->FindCommandByName(
598      kId, manifest_values::kBrowserActionCommandEvent).accelerator();
599  EXPECT_EQ(ui::VKEY_G, accelerator.key_code());
600  EXPECT_FALSE(accelerator.IsCtrlDown());
601  EXPECT_TRUE(accelerator.IsShiftDown());
602  EXPECT_TRUE(accelerator.IsAltDown());
603}
604
605}  // namespace extensions
606