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.
5 #include "base/command_line.h"
6 #include "chrome/app/chrome_command_ids.h"
7 #include "chrome/browser/extensions/active_tab_permission_granter.h"
8 #include "chrome/browser/extensions/api/commands/command_service.h"
9 #include "chrome/browser/extensions/browser_action_test_util.h"
10 #include "chrome/browser/extensions/component_loader.h"
11 #include "chrome/browser/extensions/extension_action.h"
12 #include "chrome/browser/extensions/extension_action_manager.h"
13 #include "chrome/browser/extensions/extension_apitest.h"
14 #include "chrome/browser/extensions/extension_service.h"
15 #include "chrome/browser/sessions/session_tab_helper.h"
16 #include "chrome/browser/ui/browser.h"
17 #include "chrome/browser/ui/browser_command_controller.h"
18 #include "chrome/browser/ui/browser_commands.h"
19 #include "chrome/browser/ui/tabs/tab_strip_model.h"
20 #include "chrome/test/base/interactive_test_utils.h"
21 #include "chrome/test/base/ui_test_utils.h"
22 #include "content/public/browser/notification_service.h"
23 #include "content/public/browser/web_contents.h"
24 #include "content/public/test/javascript_test_observer.h"
25 #include "extensions/browser/extension_registry.h"
26 #include "extensions/common/extension.h"
27 #include "extensions/common/feature_switch.h"
28 #include "extensions/common/manifest_constants.h"
29 #include "extensions/common/permissions/permissions_data.h"
30 #include "extensions/test/extension_test_message_listener.h"
31 #include "extensions/test/result_catcher.h"
33 using content::WebContents
;
35 namespace extensions
{
39 // This extension ID is used for tests require a stable ID over multiple
40 // extension installs.
41 const char kId
[] = "pgoakhfeplldmjheffidklpoklkppipp";
43 // Default keybinding to use for emulating user-defined shortcut overrides. The
44 // test extensions use Alt+Shift+F and Alt+Shift+H.
45 const char kAltShiftG
[] = "Alt+Shift+G";
47 // Name of the command for the "basics" test extension.
48 const char kBasicsShortcutCommandName
[] = "toggle-feature";
49 // Name of the command for the overwrite_bookmark_shortcut test extension.
50 const char kOverwriteBookmarkShortcutCommandName
[] = "send message";
52 #if defined(OS_MACOSX)
53 const char kBookmarkKeybinding
[] = "Command+D";
55 const char kBookmarkKeybinding
[] = "Ctrl+D";
56 #endif // defined(OS_MACOSX)
58 bool SendBookmarkKeyPressSync(Browser
* browser
) {
59 return ui_test_utils::SendKeyPressSync(
61 #if defined(OS_MACOSX)
62 false, false, false, true
64 true, false, false, false
69 // Named command for media key overwrite test.
70 const char kMediaKeyTestCommand
[] = "test_mediakeys_update";
72 // A scoped observer that listens for dom automation messages.
73 class DomMessageListener
: public content::TestMessageHandler
{
75 explicit DomMessageListener(content::WebContents
* web_contents
);
76 ~DomMessageListener() override
;
78 // Wait until a message is received.
81 // Clears and resets the observer.
84 const std::string
& message() const { return message_
; }
87 // content::TestMessageHandler:
88 MessageResponse
HandleMessage(const std::string
& json
) override
;
89 void Reset() override
;
91 // The message received. Note that this will be JSON, so if it is a string,
92 // it will be wrapped in quotes.
95 content::JavascriptTestObserver observer_
;
97 DISALLOW_COPY_AND_ASSIGN(DomMessageListener
);
100 DomMessageListener::DomMessageListener(content::WebContents
* web_contents
)
101 : observer_(web_contents
, this) {
104 DomMessageListener::~DomMessageListener() {
107 void DomMessageListener::Wait() {
111 void DomMessageListener::Clear() {
112 // We don't just call this in DomMessageListener::Reset() because the
113 // JavascriptTestObserver's Reset() method also resets its handler (this).
117 content::TestMessageHandler::MessageResponse
DomMessageListener::HandleMessage(
118 const std::string
& json
) {
123 void DomMessageListener::Reset() {
124 TestMessageHandler::Reset();
130 class CommandsApiTest
: public ExtensionApiTest
{
133 ~CommandsApiTest() override
{}
136 bool IsGrantedForTab(const Extension
* extension
,
137 const content::WebContents
* web_contents
) {
138 return extension
->permissions_data()->HasAPIPermissionForTab(
139 SessionTabHelper::IdForTab(web_contents
), APIPermission::kTab
);
142 #if defined(OS_CHROMEOS)
143 void RunChromeOSConversionTest(const std::string
& extension_path
) {
144 // Setup the environment.
145 ASSERT_TRUE(test_server()->Start());
146 ASSERT_TRUE(ui_test_utils::BringBrowserWindowToFront(browser()));
147 ASSERT_TRUE(RunExtensionTest(extension_path
)) << message_
;
148 ui_test_utils::NavigateToURL(
149 browser(), test_server()->GetURL("files/extensions/test_file.txt"));
151 ResultCatcher catcher
;
153 // Send all expected keys (Search+Shift+{Left, Up, Right, Down}).
154 ASSERT_TRUE(ui_test_utils::SendKeyPressSync(
155 browser(), ui::VKEY_LEFT
, false, true, false, true));
156 ASSERT_TRUE(ui_test_utils::SendKeyPressSync(
157 browser(), ui::VKEY_UP
, false, true, false, true));
158 ASSERT_TRUE(ui_test_utils::SendKeyPressSync(
159 browser(), ui::VKEY_RIGHT
, false, true, false, true));
160 ASSERT_TRUE(ui_test_utils::SendKeyPressSync(
161 browser(), ui::VKEY_DOWN
, false, true, false, true));
163 ASSERT_TRUE(catcher
.GetNextResult());
165 #endif // OS_CHROMEOS
168 // Test the basic functionality of the Keybinding API:
169 // - That pressing the shortcut keys should perform actions (activate the
170 // browser action or send an event).
171 // - Note: Page action keybindings are tested in PageAction test below.
172 // - The shortcut keys taken by one extension are not overwritten by the last
173 // installed extension.
174 IN_PROC_BROWSER_TEST_F(CommandsApiTest
, Basic
) {
175 ASSERT_TRUE(test_server()->Start());
176 ASSERT_TRUE(RunExtensionTest("keybinding/basics")) << message_
;
177 const Extension
* extension
= GetSingleLoadedExtension();
178 ASSERT_TRUE(extension
) << message_
;
180 // Load this extension, which uses the same keybindings but sets the page
181 // to different colors. This is so we can see that it doesn't interfere. We
182 // don't test this extension in any other way (it should otherwise be
183 // immaterial to this test).
184 ASSERT_TRUE(RunExtensionTest("keybinding/conflicting")) << message_
;
186 BrowserActionTestUtil
browser_actions_bar(browser());
187 // Test that there are two browser actions in the toolbar.
188 ASSERT_EQ(2, browser_actions_bar
.NumberOfBrowserActions());
190 ui_test_utils::NavigateToURL(
191 browser(), test_server()->GetURL("files/extensions/test_file.txt"));
193 // activeTab shouldn't have been granted yet.
194 WebContents
* tab
= browser()->tab_strip_model()->GetActiveWebContents();
197 EXPECT_FALSE(IsGrantedForTab(extension
, tab
));
199 ExtensionTestMessageListener
test_listener(false); // Won't reply.
200 // Activate the browser action shortcut (Ctrl+Shift+F).
201 ASSERT_TRUE(ui_test_utils::SendKeyPressSync(
202 browser(), ui::VKEY_F
, true, true, false, false));
203 EXPECT_TRUE(test_listener
.WaitUntilSatisfied());
204 // activeTab should now be granted.
205 EXPECT_TRUE(IsGrantedForTab(extension
, tab
));
206 // Verify the command worked.
207 EXPECT_EQ(std::string("basics browser action"), test_listener
.message());
209 test_listener
.Reset();
210 // Activate the command shortcut (Ctrl+Shift+Y).
211 ASSERT_TRUE(ui_test_utils::SendKeyPressSync(
212 browser(), ui::VKEY_Y
, true, true, false, false));
213 EXPECT_TRUE(test_listener
.WaitUntilSatisfied());
214 EXPECT_EQ(std::string(kBasicsShortcutCommandName
), test_listener
.message());
217 IN_PROC_BROWSER_TEST_F(CommandsApiTest
, PageAction
) {
218 ASSERT_TRUE(test_server()->Start());
219 ASSERT_TRUE(RunExtensionTest("keybinding/page_action")) << message_
;
220 const Extension
* extension
= GetSingleLoadedExtension();
221 ASSERT_TRUE(extension
) << message_
;
224 // Load a page, the extension will detect the navigation and request to show
225 // the page action icon.
226 ResultCatcher catcher
;
227 ui_test_utils::NavigateToURL(
228 browser(), test_server()->GetURL("files/extensions/test_file.txt"));
229 ASSERT_TRUE(catcher
.GetNextResult());
232 // Make sure it appears and is the right one.
233 ASSERT_TRUE(WaitForPageActionVisibilityChangeTo(1));
234 int tab_id
= SessionTabHelper::FromWebContents(
235 browser()->tab_strip_model()->GetActiveWebContents())->session_id().id();
236 ExtensionAction
* action
=
237 ExtensionActionManager::Get(browser()->profile())->
238 GetPageAction(*extension
);
240 EXPECT_EQ("Send message", action
->GetTitle(tab_id
));
242 ExtensionTestMessageListener
test_listener(false); // Won't reply.
243 test_listener
.set_extension_id(extension
->id());
245 // Activate the shortcut (Alt+Shift+F).
246 ASSERT_TRUE(ui_test_utils::SendKeyPressSync(
247 browser(), ui::VKEY_F
, false, true, true, false));
249 test_listener
.WaitUntilSatisfied();
250 EXPECT_EQ("clicked", test_listener
.message());
253 IN_PROC_BROWSER_TEST_F(CommandsApiTest
, PageActionKeyUpdated
) {
254 ASSERT_TRUE(test_server()->Start());
255 ASSERT_TRUE(RunExtensionTest("keybinding/page_action")) << message_
;
256 const Extension
* extension
= GetSingleLoadedExtension();
257 ASSERT_TRUE(extension
) << message_
;
259 CommandService
* command_service
= CommandService::Get(browser()->profile());
260 // Simulate the user setting the keybinding to Alt+Shift+G.
261 command_service
->UpdateKeybindingPrefs(
262 extension
->id(), manifest_values::kPageActionCommandEvent
, kAltShiftG
);
265 // Load a page. The extension will detect the navigation and request to show
266 // the page action icon.
267 ResultCatcher catcher
;
268 ui_test_utils::NavigateToURL(
269 browser(), test_server()->GetURL("files/extensions/test_file.txt"));
270 ASSERT_TRUE(catcher
.GetNextResult());
273 ExtensionTestMessageListener
test_listener(false); // Won't reply.
274 test_listener
.set_extension_id(extension
->id());
276 // Activate the shortcut.
277 ASSERT_TRUE(ui_test_utils::SendKeyPressSync(
278 browser(), ui::VKEY_G
, false, true, true, false));
280 test_listener
.WaitUntilSatisfied();
281 EXPECT_EQ("clicked", test_listener
.message());
284 // This test validates that the getAll query API function returns registered
285 // commands as well as synthesized ones and that inactive commands (like the
286 // synthesized ones are in nature) have no shortcuts.
287 IN_PROC_BROWSER_TEST_F(CommandsApiTest
, SynthesizedCommand
) {
288 ASSERT_TRUE(test_server()->Start());
289 ASSERT_TRUE(RunExtensionTest("keybinding/synthesized")) << message_
;
292 // This test validates that an extension cannot request a shortcut that is
293 // already in use by Chrome.
294 IN_PROC_BROWSER_TEST_F(CommandsApiTest
, DontOverwriteSystemShortcuts
) {
295 ASSERT_TRUE(test_server()->Start());
297 ASSERT_TRUE(ui_test_utils::BringBrowserWindowToFront(browser()));
299 ASSERT_TRUE(RunExtensionTest("keybinding/dont_overwrite_system")) << message_
;
301 ui_test_utils::NavigateToURL(
302 browser(), test_server()->GetURL("files/extensions/test_file.txt"));
304 // Activate the regular shortcut (Alt+Shift+F).
305 ExtensionTestMessageListener
alt_shift_f_listener("alt_shift_f", false);
306 ASSERT_TRUE(ui_test_utils::SendKeyPressSync(
307 browser(), ui::VKEY_F
, false, true, true, false));
308 EXPECT_TRUE(alt_shift_f_listener
.WaitUntilSatisfied());
310 // Try to activate the bookmark shortcut (Ctrl+D). This should not work
311 // without requesting via chrome_settings_overrides.
313 // Since keypresses are sent synchronously, we can check this by first sending
314 // Ctrl+D (which shouldn't work), followed by Alt+Shift+F (which should work),
315 // and listening for both. If, by the time we receive the Alt+Shift+F
316 // response, we haven't received a response for Ctrl+D, it is safe to say we
317 // won't receive one.
319 ExtensionTestMessageListener
ctrl_d_listener("ctrl_d", false);
320 alt_shift_f_listener
.Reset();
322 ASSERT_TRUE(SendBookmarkKeyPressSync(browser()));
324 ASSERT_TRUE(ui_test_utils::SendKeyPressSync(
325 browser(), ui::VKEY_F
, false, true, true, false));
326 EXPECT_TRUE(alt_shift_f_listener
.WaitUntilSatisfied());
327 EXPECT_FALSE(ctrl_d_listener
.was_satisfied());
330 // Try to activate the Ctrl+F shortcut (shouldn't work).
332 ExtensionTestMessageListener
ctrl_f_listener("ctrl_f", false);
333 alt_shift_f_listener
.Reset();
335 ASSERT_TRUE(ui_test_utils::SendKeyPressSync(
336 browser(), ui::VKEY_F
, true, false, false, false));
338 ASSERT_TRUE(ui_test_utils::SendKeyPressSync(
339 browser(), ui::VKEY_F
, false, true, true, false));
340 EXPECT_TRUE(alt_shift_f_listener
.WaitUntilSatisfied());
341 EXPECT_FALSE(ctrl_f_listener
.was_satisfied());
345 // This test validates that an extension can remove the Chrome bookmark shortcut
346 // if it has requested to do so.
347 IN_PROC_BROWSER_TEST_F(CommandsApiTest
, RemoveBookmarkShortcut
) {
348 ASSERT_TRUE(test_server()->Start());
350 ASSERT_TRUE(ui_test_utils::BringBrowserWindowToFront(browser()));
352 // This functionality requires a feature flag.
353 base::CommandLine::ForCurrentProcess()->AppendSwitchASCII(
354 "--enable-override-bookmarks-ui", "1");
356 ASSERT_TRUE(RunExtensionTest("keybinding/remove_bookmark_shortcut"))
359 EXPECT_FALSE(chrome::IsCommandEnabled(browser(), IDC_BOOKMARK_PAGE
));
362 // This test validates that an extension cannot remove the Chrome bookmark
363 // shortcut without being given permission with a feature flag.
364 IN_PROC_BROWSER_TEST_F(CommandsApiTest
,
365 RemoveBookmarkShortcutWithoutPermission
) {
366 ASSERT_TRUE(test_server()->Start());
368 ASSERT_TRUE(ui_test_utils::BringBrowserWindowToFront(browser()));
370 EXPECT_TRUE(RunExtensionTestIgnoreManifestWarnings(
371 "keybinding/remove_bookmark_shortcut"));
373 EXPECT_TRUE(chrome::IsCommandEnabled(browser(), IDC_BOOKMARK_PAGE
));
376 // This test validates that an extension that removes the Chrome bookmark
377 // shortcut continues to remove the bookmark shortcut with a user-assigned
378 // Ctrl+D shortcut (i.e. it does not trigger the overwrite functionality).
379 IN_PROC_BROWSER_TEST_F(CommandsApiTest
,
380 RemoveBookmarkShortcutWithUserKeyBinding
) {
381 ASSERT_TRUE(test_server()->Start());
383 ASSERT_TRUE(ui_test_utils::BringBrowserWindowToFront(browser()));
385 // This functionality requires a feature flag.
386 base::CommandLine::ForCurrentProcess()->AppendSwitchASCII(
387 "--enable-override-bookmarks-ui", "1");
389 ASSERT_TRUE(RunExtensionTest("keybinding/remove_bookmark_shortcut"))
392 // Check that the shortcut is removed.
393 CommandService
* command_service
= CommandService::Get(browser()->profile());
394 const Extension
* extension
= GetSingleLoadedExtension();
395 // Simulate the user setting a keybinding to Ctrl+D.
396 command_service
->UpdateKeybindingPrefs(
397 extension
->id(), manifest_values::kBrowserActionCommandEvent
,
398 kBookmarkKeybinding
);
400 // Force the command enable state to be recalculated.
401 browser()->command_controller()->ExtensionStateChanged();
403 EXPECT_FALSE(chrome::IsCommandEnabled(browser(), IDC_BOOKMARK_PAGE
));
406 // This test validates that an extension can override the Chrome bookmark
407 // shortcut if it has requested to do so.
408 IN_PROC_BROWSER_TEST_F(CommandsApiTest
, OverwriteBookmarkShortcut
) {
409 ASSERT_TRUE(test_server()->Start());
411 ASSERT_TRUE(ui_test_utils::BringBrowserWindowToFront(browser()));
413 // This functionality requires a feature flag.
414 base::CommandLine::ForCurrentProcess()->AppendSwitchASCII(
415 "--enable-override-bookmarks-ui", "1");
417 ASSERT_TRUE(RunExtensionTest("keybinding/overwrite_bookmark_shortcut"))
420 ui_test_utils::NavigateToURL(
421 browser(), test_server()->GetURL("files/extensions/test_file.txt"));
423 // Activate the shortcut (Ctrl+D) to send a test message.
424 ExtensionTestMessageListener
test_listener(false); // Won't reply.
425 ASSERT_TRUE(SendBookmarkKeyPressSync(browser()));
426 EXPECT_TRUE(test_listener
.WaitUntilSatisfied());
427 EXPECT_EQ(std::string(kOverwriteBookmarkShortcutCommandName
),
428 test_listener
.message());
431 // This test validates that an extension that requests to override the Chrome
432 // bookmark shortcut, but does not get the keybinding, does not remove the
434 IN_PROC_BROWSER_TEST_F(CommandsApiTest
,
435 OverwriteBookmarkShortcutWithoutKeybinding
) {
436 // This functionality requires a feature flag.
437 base::CommandLine::ForCurrentProcess()->AppendSwitchASCII(
438 "--enable-override-bookmarks-ui", "1");
440 ASSERT_TRUE(test_server()->Start());
442 EXPECT_TRUE(chrome::IsCommandEnabled(browser(), IDC_BOOKMARK_PAGE
));
444 ASSERT_TRUE(RunExtensionTest("keybinding/overwrite_bookmark_shortcut"))
447 const Extension
* extension
= GetSingleLoadedExtension();
448 CommandService
* command_service
= CommandService::Get(browser()->profile());
450 // Verify the expected command is present.
451 EXPECT_TRUE(command_service
->GetNamedCommands(
452 extension
->id(), CommandService::SUGGESTED
, CommandService::ANY_SCOPE
,
454 EXPECT_EQ(1u, commands
.count(kOverwriteBookmarkShortcutCommandName
));
456 // Simulate the user removing the Ctrl+D keybinding from the command.
457 command_service
->RemoveKeybindingPrefs(
458 extension
->id(), kOverwriteBookmarkShortcutCommandName
);
460 // Force the command enable state to be recalculated.
461 browser()->command_controller()->ExtensionStateChanged();
463 EXPECT_TRUE(chrome::IsCommandEnabled(browser(), IDC_BOOKMARK_PAGE
));
466 // This test validates that an extension override of the Chrome bookmark
467 // shortcut does not supersede the same keybinding by web pages.
468 IN_PROC_BROWSER_TEST_F(CommandsApiTest
,
469 OverwriteBookmarkShortcutDoesNotOverrideWebKeybinding
) {
470 ASSERT_TRUE(test_server()->Start());
472 ASSERT_TRUE(ui_test_utils::BringBrowserWindowToFront(browser()));
474 // This functionality requires a feature flag.
475 base::CommandLine::ForCurrentProcess()->AppendSwitchASCII(
476 "--enable-override-bookmarks-ui", "1");
478 ASSERT_TRUE(RunExtensionTest("keybinding/overwrite_bookmark_shortcut"))
481 ui_test_utils::NavigateToURL(
483 test_server()->GetURL(
484 "files/extensions/test_file_with_ctrl-d_keybinding.html"));
486 WebContents
* tab
= browser()->tab_strip_model()->GetActiveWebContents();
489 // Activate the shortcut (Ctrl+D) which should be handled by the page and send
491 DomMessageListener
listener(tab
);
492 ASSERT_TRUE(SendBookmarkKeyPressSync(browser()));
494 EXPECT_EQ(std::string("\"web page received\""), listener
.message());
497 // This test validates that user-set override of the Chrome bookmark shortcut in
498 // an extension that does not request it does supersede the same keybinding by
500 IN_PROC_BROWSER_TEST_F(CommandsApiTest
,
501 OverwriteBookmarkShortcutByUserOverridesWebKeybinding
) {
502 ASSERT_TRUE(test_server()->Start());
504 ASSERT_TRUE(ui_test_utils::BringBrowserWindowToFront(browser()));
506 // This functionality requires a feature flag.
507 base::CommandLine::ForCurrentProcess()->AppendSwitchASCII(
508 "--enable-override-bookmarks-ui", "1");
510 ASSERT_TRUE(RunExtensionTest("keybinding/basics"))
513 CommandService
* command_service
= CommandService::Get(browser()->profile());
515 const Extension
* extension
= GetSingleLoadedExtension();
516 // Simulate the user setting the keybinding to Ctrl+D.
517 command_service
->UpdateKeybindingPrefs(
518 extension
->id(), manifest_values::kBrowserActionCommandEvent
,
519 kBookmarkKeybinding
);
521 ui_test_utils::NavigateToURL(
523 test_server()->GetURL(
524 "files/extensions/test_file_with_ctrl-d_keybinding.html"));
526 ExtensionTestMessageListener
test_listener(false); // Won't reply.
527 // Activate the shortcut (Ctrl+D) which should be handled by the extension.
528 ASSERT_TRUE(SendBookmarkKeyPressSync(browser()));
529 EXPECT_TRUE(test_listener
.WaitUntilSatisfied());
530 EXPECT_EQ(std::string("basics browser action"), test_listener
.message());
534 // Currently this feature is implemented on Windows only.
535 #define MAYBE_AllowDuplicatedMediaKeys AllowDuplicatedMediaKeys
537 #define MAYBE_AllowDuplicatedMediaKeys DISABLED_AllowDuplicatedMediaKeys
540 // Test that media keys go to all extensions that register for them.
541 IN_PROC_BROWSER_TEST_F(CommandsApiTest
, MAYBE_AllowDuplicatedMediaKeys
) {
542 ResultCatcher catcher
;
543 ASSERT_TRUE(RunExtensionTest("keybinding/non_global_media_keys_0"))
545 ASSERT_TRUE(catcher
.GetNextResult());
546 ASSERT_TRUE(RunExtensionTest("keybinding/non_global_media_keys_1"))
548 ASSERT_TRUE(catcher
.GetNextResult());
550 // Activate the Media Stop key.
551 ASSERT_TRUE(ui_test_utils::SendKeyPressSync(
552 browser(), ui::VKEY_MEDIA_STOP
, false, false, false, false));
554 // We should get two success result.
555 ASSERT_TRUE(catcher
.GetNextResult());
556 ASSERT_TRUE(catcher
.GetNextResult());
559 IN_PROC_BROWSER_TEST_F(CommandsApiTest
, ShortcutAddedOnUpdate
) {
560 base::ScopedTempDir scoped_temp_dir
;
561 EXPECT_TRUE(scoped_temp_dir
.CreateUniqueTempDir());
562 base::FilePath pem_path
= test_data_dir_
.
563 AppendASCII("keybinding").AppendASCII("keybinding.pem");
564 base::FilePath path_v1_unassigned
= PackExtensionWithOptions(
565 test_data_dir_
.AppendASCII("keybinding").AppendASCII("update")
566 .AppendASCII("v1_unassigned"),
567 scoped_temp_dir
.path().AppendASCII("v1_unassigned.crx"),
570 base::FilePath path_v2
= PackExtensionWithOptions(
571 test_data_dir_
.AppendASCII("keybinding").AppendASCII("update")
573 scoped_temp_dir
.path().AppendASCII("v2.crx"),
577 ExtensionRegistry
* registry
= ExtensionRegistry::Get(browser()->profile());
578 CommandService
* command_service
= CommandService::Get(browser()->profile());
580 // Install v1 of the extension without keybinding assigned.
581 ASSERT_TRUE(InstallExtension(path_v1_unassigned
, 1));
582 EXPECT_TRUE(registry
->GetExtensionById(kId
, ExtensionRegistry::ENABLED
) !=
585 // Verify it is set to nothing.
586 ui::Accelerator accelerator
= command_service
->FindCommandByName(
587 kId
, manifest_values::kBrowserActionCommandEvent
).accelerator();
588 EXPECT_EQ(ui::VKEY_UNKNOWN
, accelerator
.key_code());
590 // Update to version 2 with keybinding.
591 EXPECT_TRUE(UpdateExtension(kId
, path_v2
, 0));
592 EXPECT_TRUE(registry
->GetExtensionById(kId
, ExtensionRegistry::ENABLED
) !=
595 // Verify it has a command of Alt+Shift+F.
596 accelerator
= command_service
->FindCommandByName(
597 kId
, manifest_values::kBrowserActionCommandEvent
).accelerator();
598 EXPECT_EQ(ui::VKEY_F
, accelerator
.key_code());
599 EXPECT_FALSE(accelerator
.IsCtrlDown());
600 EXPECT_TRUE(accelerator
.IsShiftDown());
601 EXPECT_TRUE(accelerator
.IsAltDown());
604 IN_PROC_BROWSER_TEST_F(CommandsApiTest
, ShortcutChangedOnUpdate
) {
605 base::ScopedTempDir scoped_temp_dir
;
606 EXPECT_TRUE(scoped_temp_dir
.CreateUniqueTempDir());
607 base::FilePath pem_path
= test_data_dir_
.
608 AppendASCII("keybinding").AppendASCII("keybinding.pem");
609 base::FilePath path_v1
= PackExtensionWithOptions(
610 test_data_dir_
.AppendASCII("keybinding").AppendASCII("update")
612 scoped_temp_dir
.path().AppendASCII("v1.crx"),
615 base::FilePath path_v2_reassigned
= PackExtensionWithOptions(
616 test_data_dir_
.AppendASCII("keybinding").AppendASCII("update")
617 .AppendASCII("v2_reassigned"),
618 scoped_temp_dir
.path().AppendASCII("v2_reassigned.crx"),
622 ExtensionRegistry
* registry
= ExtensionRegistry::Get(browser()->profile());
623 CommandService
* command_service
= CommandService::Get(browser()->profile());
625 // Install v1 of the extension.
626 ASSERT_TRUE(InstallExtension(path_v1
, 1));
627 EXPECT_TRUE(registry
->GetExtensionById(kId
, ExtensionRegistry::ENABLED
) !=
630 // Verify it has a command of Alt+Shift+F.
631 ui::Accelerator accelerator
= command_service
->FindCommandByName(
632 kId
, manifest_values::kBrowserActionCommandEvent
).accelerator();
633 EXPECT_EQ(ui::VKEY_F
, accelerator
.key_code());
634 EXPECT_FALSE(accelerator
.IsCtrlDown());
635 EXPECT_TRUE(accelerator
.IsShiftDown());
636 EXPECT_TRUE(accelerator
.IsAltDown());
638 // Update to version 2 with different keybinding assigned.
639 EXPECT_TRUE(UpdateExtension(kId
, path_v2_reassigned
, 0));
640 EXPECT_TRUE(registry
->GetExtensionById(kId
, ExtensionRegistry::ENABLED
) !=
643 // Verify it has a command of Alt+Shift+H.
644 accelerator
= command_service
->FindCommandByName(
645 kId
, manifest_values::kBrowserActionCommandEvent
).accelerator();
646 EXPECT_EQ(ui::VKEY_H
, accelerator
.key_code());
647 EXPECT_FALSE(accelerator
.IsCtrlDown());
648 EXPECT_TRUE(accelerator
.IsShiftDown());
649 EXPECT_TRUE(accelerator
.IsAltDown());
652 IN_PROC_BROWSER_TEST_F(CommandsApiTest
, ShortcutRemovedOnUpdate
) {
653 base::ScopedTempDir scoped_temp_dir
;
654 EXPECT_TRUE(scoped_temp_dir
.CreateUniqueTempDir());
655 base::FilePath pem_path
= test_data_dir_
.
656 AppendASCII("keybinding").AppendASCII("keybinding.pem");
657 base::FilePath path_v1
= PackExtensionWithOptions(
658 test_data_dir_
.AppendASCII("keybinding").AppendASCII("update")
660 scoped_temp_dir
.path().AppendASCII("v1.crx"),
663 base::FilePath path_v2_unassigned
= PackExtensionWithOptions(
664 test_data_dir_
.AppendASCII("keybinding").AppendASCII("update")
665 .AppendASCII("v2_unassigned"),
666 scoped_temp_dir
.path().AppendASCII("v2_unassigned.crx"),
670 ExtensionRegistry
* registry
= ExtensionRegistry::Get(browser()->profile());
671 CommandService
* command_service
= CommandService::Get(browser()->profile());
673 // Install v1 of the extension.
674 ASSERT_TRUE(InstallExtension(path_v1
, 1));
675 EXPECT_TRUE(registry
->GetExtensionById(kId
, ExtensionRegistry::ENABLED
) !=
678 // Verify it has a command of Alt+Shift+F.
679 ui::Accelerator accelerator
= command_service
->FindCommandByName(
680 kId
, manifest_values::kBrowserActionCommandEvent
).accelerator();
681 EXPECT_EQ(ui::VKEY_F
, accelerator
.key_code());
682 EXPECT_FALSE(accelerator
.IsCtrlDown());
683 EXPECT_TRUE(accelerator
.IsShiftDown());
684 EXPECT_TRUE(accelerator
.IsAltDown());
686 // Update to version 2 without keybinding assigned.
687 EXPECT_TRUE(UpdateExtension(kId
, path_v2_unassigned
, 0));
688 EXPECT_TRUE(registry
->GetExtensionById(kId
, ExtensionRegistry::ENABLED
) !=
691 // Verify the keybinding gets set to nothing.
692 accelerator
= command_service
->FindCommandByName(
693 kId
, manifest_values::kBrowserActionCommandEvent
).accelerator();
694 EXPECT_EQ(ui::VKEY_UNKNOWN
, accelerator
.key_code());
697 IN_PROC_BROWSER_TEST_F(CommandsApiTest
,
698 ShortcutAddedOnUpdateAfterBeingAssignedByUser
) {
699 base::ScopedTempDir scoped_temp_dir
;
700 EXPECT_TRUE(scoped_temp_dir
.CreateUniqueTempDir());
701 base::FilePath pem_path
= test_data_dir_
.
702 AppendASCII("keybinding").AppendASCII("keybinding.pem");
703 base::FilePath path_v1_unassigned
= PackExtensionWithOptions(
704 test_data_dir_
.AppendASCII("keybinding").AppendASCII("update")
705 .AppendASCII("v1_unassigned"),
706 scoped_temp_dir
.path().AppendASCII("v1_unassigned.crx"),
709 base::FilePath path_v2
= PackExtensionWithOptions(
710 test_data_dir_
.AppendASCII("keybinding").AppendASCII("update")
712 scoped_temp_dir
.path().AppendASCII("v2.crx"),
716 ExtensionRegistry
* registry
= ExtensionRegistry::Get(browser()->profile());
717 CommandService
* command_service
= CommandService::Get(browser()->profile());
719 // Install v1 of the extension without keybinding assigned.
720 ASSERT_TRUE(InstallExtension(path_v1_unassigned
, 1));
721 EXPECT_TRUE(registry
->GetExtensionById(kId
, ExtensionRegistry::ENABLED
) !=
724 // Verify it is set to nothing.
725 ui::Accelerator accelerator
= command_service
->FindCommandByName(
726 kId
, manifest_values::kBrowserActionCommandEvent
).accelerator();
727 EXPECT_EQ(ui::VKEY_UNKNOWN
, accelerator
.key_code());
729 // Simulate the user setting the keybinding to Alt+Shift+G.
730 command_service
->UpdateKeybindingPrefs(
731 kId
, manifest_values::kBrowserActionCommandEvent
, kAltShiftG
);
733 // Update to version 2 with keybinding.
734 EXPECT_TRUE(UpdateExtension(kId
, path_v2
, 0));
735 EXPECT_TRUE(registry
->GetExtensionById(kId
, ExtensionRegistry::ENABLED
) !=
738 // Verify the previously-set keybinding is still set.
739 accelerator
= command_service
->FindCommandByName(
740 kId
, manifest_values::kBrowserActionCommandEvent
).accelerator();
741 EXPECT_EQ(ui::VKEY_G
, accelerator
.key_code());
742 EXPECT_FALSE(accelerator
.IsCtrlDown());
743 EXPECT_TRUE(accelerator
.IsShiftDown());
744 EXPECT_TRUE(accelerator
.IsAltDown());
747 IN_PROC_BROWSER_TEST_F(CommandsApiTest
,
748 ShortcutChangedOnUpdateAfterBeingReassignedByUser
) {
749 base::ScopedTempDir scoped_temp_dir
;
750 EXPECT_TRUE(scoped_temp_dir
.CreateUniqueTempDir());
751 base::FilePath pem_path
= test_data_dir_
.
752 AppendASCII("keybinding").AppendASCII("keybinding.pem");
753 base::FilePath path_v1
= PackExtensionWithOptions(
754 test_data_dir_
.AppendASCII("keybinding").AppendASCII("update")
756 scoped_temp_dir
.path().AppendASCII("v1.crx"),
759 base::FilePath path_v2_reassigned
= PackExtensionWithOptions(
760 test_data_dir_
.AppendASCII("keybinding").AppendASCII("update")
761 .AppendASCII("v2_reassigned"),
762 scoped_temp_dir
.path().AppendASCII("v2_reassigned.crx"),
766 ExtensionRegistry
* registry
= ExtensionRegistry::Get(browser()->profile());
767 CommandService
* command_service
= CommandService::Get(browser()->profile());
769 // Install v1 of the extension.
770 ASSERT_TRUE(InstallExtension(path_v1
, 1));
771 EXPECT_TRUE(registry
->GetExtensionById(kId
, ExtensionRegistry::ENABLED
) !=
774 // Verify it has a command of Alt+Shift+F.
775 ui::Accelerator accelerator
= command_service
->FindCommandByName(
776 kId
, manifest_values::kBrowserActionCommandEvent
).accelerator();
777 EXPECT_EQ(ui::VKEY_F
, accelerator
.key_code());
778 EXPECT_FALSE(accelerator
.IsCtrlDown());
779 EXPECT_TRUE(accelerator
.IsShiftDown());
780 EXPECT_TRUE(accelerator
.IsAltDown());
782 // Simulate the user setting the keybinding to Alt+Shift+G.
783 command_service
->UpdateKeybindingPrefs(
784 kId
, manifest_values::kBrowserActionCommandEvent
, kAltShiftG
);
786 // Update to version 2 with different keybinding assigned.
787 EXPECT_TRUE(UpdateExtension(kId
, path_v2_reassigned
, 0));
788 EXPECT_TRUE(registry
->GetExtensionById(kId
, ExtensionRegistry::ENABLED
) !=
791 // Verify it has a command of Alt+Shift+G.
792 accelerator
= command_service
->FindCommandByName(
793 kId
, manifest_values::kBrowserActionCommandEvent
).accelerator();
794 EXPECT_EQ(ui::VKEY_G
, accelerator
.key_code());
795 EXPECT_FALSE(accelerator
.IsCtrlDown());
796 EXPECT_TRUE(accelerator
.IsShiftDown());
797 EXPECT_TRUE(accelerator
.IsAltDown());
800 // Test that Media keys do not overwrite previous settings.
801 IN_PROC_BROWSER_TEST_F(CommandsApiTest
,
802 MediaKeyShortcutChangedOnUpdateAfterBeingReassignedByUser
) {
803 base::ScopedTempDir scoped_temp_dir
;
804 EXPECT_TRUE(scoped_temp_dir
.CreateUniqueTempDir());
805 base::FilePath pem_path
= test_data_dir_
.
806 AppendASCII("keybinding").AppendASCII("keybinding.pem");
807 base::FilePath path_v1
= PackExtensionWithOptions(
808 test_data_dir_
.AppendASCII("keybinding").AppendASCII("update")
809 .AppendASCII("mk_v1"),
810 scoped_temp_dir
.path().AppendASCII("mk_v1.crx"),
813 base::FilePath path_v2_reassigned
= PackExtensionWithOptions(
814 test_data_dir_
.AppendASCII("keybinding").AppendASCII("update")
815 .AppendASCII("mk_v2"),
816 scoped_temp_dir
.path().AppendASCII("mk_v2.crx"),
820 ExtensionRegistry
* registry
= ExtensionRegistry::Get(browser()->profile());
821 CommandService
* command_service
= CommandService::Get(browser()->profile());
823 // Install v1 of the extension.
824 ASSERT_TRUE(InstallExtension(path_v1
, 1));
825 EXPECT_TRUE(registry
->GetExtensionById(kId
, ExtensionRegistry::ENABLED
) !=
828 // Verify it has a command of MediaPlayPause.
829 ui::Accelerator accelerator
= command_service
->FindCommandByName(
830 kId
, kMediaKeyTestCommand
).accelerator();
831 EXPECT_EQ(ui::VKEY_MEDIA_PLAY_PAUSE
, accelerator
.key_code());
832 EXPECT_FALSE(accelerator
.IsCtrlDown());
833 EXPECT_FALSE(accelerator
.IsShiftDown());
834 EXPECT_FALSE(accelerator
.IsAltDown());
836 // Simulate the user setting the keybinding to Alt+Shift+G.
837 command_service
->UpdateKeybindingPrefs(
838 kId
, kMediaKeyTestCommand
, kAltShiftG
);
840 // Update to version 2 with different keybinding assigned.
841 EXPECT_TRUE(UpdateExtension(kId
, path_v2_reassigned
, 0));
842 EXPECT_TRUE(registry
->GetExtensionById(kId
, ExtensionRegistry::ENABLED
) !=
845 // Verify it has a command of Alt+Shift+G.
846 accelerator
= command_service
->FindCommandByName(
847 kId
, kMediaKeyTestCommand
).accelerator();
848 EXPECT_EQ(ui::VKEY_G
, accelerator
.key_code());
849 EXPECT_FALSE(accelerator
.IsCtrlDown());
850 EXPECT_TRUE(accelerator
.IsShiftDown());
851 EXPECT_TRUE(accelerator
.IsAltDown());
854 IN_PROC_BROWSER_TEST_F(CommandsApiTest
,
855 ShortcutRemovedOnUpdateAfterBeingReassignedByUser
) {
856 base::ScopedTempDir scoped_temp_dir
;
857 EXPECT_TRUE(scoped_temp_dir
.CreateUniqueTempDir());
858 base::FilePath pem_path
= test_data_dir_
.
859 AppendASCII("keybinding").AppendASCII("keybinding.pem");
860 base::FilePath path_v1
= PackExtensionWithOptions(
861 test_data_dir_
.AppendASCII("keybinding").AppendASCII("update")
863 scoped_temp_dir
.path().AppendASCII("v1.crx"),
866 base::FilePath path_v2_unassigned
= PackExtensionWithOptions(
867 test_data_dir_
.AppendASCII("keybinding").AppendASCII("update")
868 .AppendASCII("v2_unassigned"),
869 scoped_temp_dir
.path().AppendASCII("v2_unassigned.crx"),
873 ExtensionRegistry
* registry
= ExtensionRegistry::Get(browser()->profile());
874 CommandService
* command_service
= CommandService::Get(browser()->profile());
876 // Install v1 of the extension.
877 ASSERT_TRUE(InstallExtension(path_v1
, 1));
878 EXPECT_TRUE(registry
->GetExtensionById(kId
, ExtensionRegistry::ENABLED
) !=
881 // Verify it has a command of Alt+Shift+F.
882 ui::Accelerator accelerator
= command_service
->FindCommandByName(
883 kId
, manifest_values::kBrowserActionCommandEvent
).accelerator();
884 EXPECT_EQ(ui::VKEY_F
, accelerator
.key_code());
885 EXPECT_FALSE(accelerator
.IsCtrlDown());
886 EXPECT_TRUE(accelerator
.IsShiftDown());
887 EXPECT_TRUE(accelerator
.IsAltDown());
889 // Simulate the user reassigning the keybinding to Alt+Shift+G.
890 command_service
->UpdateKeybindingPrefs(
891 kId
, manifest_values::kBrowserActionCommandEvent
, kAltShiftG
);
893 // Update to version 2 without keybinding assigned.
894 EXPECT_TRUE(UpdateExtension(kId
, path_v2_unassigned
, 0));
895 EXPECT_TRUE(registry
->GetExtensionById(kId
, ExtensionRegistry::ENABLED
) !=
898 // Verify the keybinding is still set.
899 accelerator
= command_service
->FindCommandByName(
900 kId
, manifest_values::kBrowserActionCommandEvent
).accelerator();
901 EXPECT_EQ(ui::VKEY_G
, accelerator
.key_code());
902 EXPECT_FALSE(accelerator
.IsCtrlDown());
903 EXPECT_TRUE(accelerator
.IsShiftDown());
904 EXPECT_TRUE(accelerator
.IsAltDown());
908 #if defined(OS_CHROMEOS) && !defined(NDEBUG)
909 // TODO(dtseng): Test times out on Chrome OS debug. See http://crbug.com/412456.
910 #define MAYBE_ContinuePropagation DISABLED_ContinuePropagation
912 #define MAYBE_ContinuePropagation ContinuePropagation
915 IN_PROC_BROWSER_TEST_F(CommandsApiTest
, MAYBE_ContinuePropagation
) {
916 // Setup the environment.
917 ASSERT_TRUE(test_server()->Start());
918 ASSERT_TRUE(ui_test_utils::BringBrowserWindowToFront(browser()));
919 ASSERT_TRUE(RunExtensionTest("keybinding/continue_propagation")) << message_
;
920 ui_test_utils::NavigateToURL(
921 browser(), test_server()->GetURL("files/extensions/test_file.txt"));
923 ResultCatcher catcher
;
925 // Activate the shortcut (Ctrl+Shift+F). The page should capture the
926 // keystroke and not the extension since |onCommand| has no event listener
928 ASSERT_TRUE(ui_test_utils::SendKeyPressSync(
929 browser(), ui::VKEY_F
, true, true, false, false));
930 ASSERT_TRUE(catcher
.GetNextResult());
932 // Now, the extension should have added an |onCommand| event listener.
933 // Send the same key, but the |onCommand| listener should now receive it.
934 ASSERT_TRUE(ui_test_utils::SendKeyPressSync(
935 browser(), ui::VKEY_F
, true, true, false, false));
936 ASSERT_TRUE(catcher
.GetNextResult());
938 // The extension should now have removed its |onCommand| event listener.
939 // Finally, the page should again receive the key.
940 ASSERT_TRUE(ui_test_utils::SendKeyPressSync(
941 browser(), ui::VKEY_F
, true, true, false, false));
942 ASSERT_TRUE(catcher
.GetNextResult());
945 // Test is only applicable on Chrome OS.
946 #if defined(OS_CHROMEOS)
947 // http://crbug.com/410534
948 #if defined(USE_OZONE)
949 #define MAYBE_ChromeOSConversions DISABLED_ChromeOSConversions
951 #define MAYBE_ChromeOSConversions ChromeOSConversions
953 IN_PROC_BROWSER_TEST_F(CommandsApiTest
, MAYBE_ChromeOSConversions
) {
954 RunChromeOSConversionTest("keybinding/chromeos_conversions");
956 #endif // OS_CHROMEOS
958 // Make sure component extensions retain keybindings after removal then
960 IN_PROC_BROWSER_TEST_F(CommandsApiTest
, AddRemoveAddComponentExtension
) {
961 ASSERT_TRUE(test_server()->Start());
962 ASSERT_TRUE(RunComponentExtensionTest("keybinding/component")) << message_
;
964 extensions::ExtensionSystem::Get(browser()->profile())
965 ->extension_service()
967 ->Remove("pkplfbidichfdicaijlchgnapepdginl");
969 ASSERT_TRUE(RunComponentExtensionTest("keybinding/component")) << message_
;
972 } // namespace extensions