• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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:
CommandsApiTest()44   CommandsApiTest() {}
~CommandsApiTest()45   virtual ~CommandsApiTest() {}
46 
47  protected:
GetBrowserActionsBar()48   BrowserActionTestUtil GetBrowserActionsBar() {
49     return BrowserActionTestUtil(browser());
50   }
51 
IsGrantedForTab(const Extension * extension,const content::WebContents * web_contents)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)
RunChromeOSConversionTest(const std::string & extension_path)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.
IN_PROC_BROWSER_TEST_F(CommandsApiTest,Basic)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
IN_PROC_BROWSER_TEST_F(CommandsApiTest,MAYBE_PageAction)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.
IN_PROC_BROWSER_TEST_F(CommandsApiTest,SynthesizedCommand)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.
IN_PROC_BROWSER_TEST_F(CommandsApiTest,DontOverwriteSystemShortcuts)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.
IN_PROC_BROWSER_TEST_F(CommandsApiTest,OverwriteBookmarkShortcut)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.
IN_PROC_BROWSER_TEST_F(CommandsApiTest,OverwriteBookmarkShortcutDoesNotOverrideWebKeybinding)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.
IN_PROC_BROWSER_TEST_F(CommandsApiTest,OverwriteBookmarkShortcutByUserOverridesWebKeybinding)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.
IN_PROC_BROWSER_TEST_F(CommandsApiTest,MAYBE_AllowDuplicatedMediaKeys)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 
IN_PROC_BROWSER_TEST_F(CommandsApiTest,ShortcutAddedOnUpdate)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 
IN_PROC_BROWSER_TEST_F(CommandsApiTest,ShortcutChangedOnUpdate)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 
IN_PROC_BROWSER_TEST_F(CommandsApiTest,ShortcutRemovedOnUpdate)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 
IN_PROC_BROWSER_TEST_F(CommandsApiTest,ShortcutAddedOnUpdateAfterBeingAssignedByUser)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 
IN_PROC_BROWSER_TEST_F(CommandsApiTest,ShortcutChangedOnUpdateAfterBeingReassignedByUser)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 
IN_PROC_BROWSER_TEST_F(CommandsApiTest,ShortcutRemovedOnUpdateAfterBeingReassignedByUser)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 
IN_PROC_BROWSER_TEST_F(CommandsApiTest,MAYBE_ContinuePropagation)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
IN_PROC_BROWSER_TEST_F(CommandsApiTest,MAYBE_ChromeOSConversions)776 IN_PROC_BROWSER_TEST_F(CommandsApiTest, MAYBE_ChromeOSConversions) {
777   RunChromeOSConversionTest("keybinding/chromeos_conversions");
778 }
779 #endif  // OS_CHROMEOS
780 
781 }  // namespace extensions
782