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