| OLD | NEW |
| 1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "chrome/browser/extensions/extension_apitest.h" | 5 #include "chrome/browser/extensions/extension_apitest.h" |
| 6 #include "chrome/browser/extensions/window_controller.h" | 6 #include "chrome/browser/extensions/window_controller.h" |
| 7 #include "chrome/browser/ui/browser_window.h" | 7 #include "chrome/browser/ui/browser_window.h" |
| 8 #include "chrome/browser/ui/tabs/tab_strip_model.h" | 8 #include "chrome/browser/ui/tabs/tab_strip_model.h" |
| 9 #include "chrome/test/base/interactive_test_utils.h" | 9 #include "chrome/test/base/interactive_test_utils.h" |
| 10 #include "content/public/test/browser_test_utils.h" | 10 #include "content/public/test/browser_test_utils.h" |
| 11 #include "ui/base/base_window.h" | 11 #include "ui/base/base_window.h" |
| 12 #include "ui/base/test/ui_controls.h" | 12 #include "ui/base/test/ui_controls.h" |
| 13 | 13 |
| 14 #if defined(OS_LINUX) | 14 #if defined(OS_LINUX) |
| 15 #include <X11/Xlib.h> | 15 #include <X11/Xlib.h> |
| 16 #include <X11/extensions/XTest.h> | 16 #include <X11/extensions/XTest.h> |
| 17 #include <X11/keysym.h> | 17 #include <X11/keysym.h> |
| 18 | 18 |
| 19 #include "ui/events/keycodes/keyboard_code_conversion_x.h" | 19 #include "ui/events/keycodes/keyboard_code_conversion_x.h" |
| 20 #include "ui/gfx/x/x11_types.h" | 20 #include "ui/gfx/x/x11_types.h" |
| 21 #endif | 21 #endif |
| 22 | 22 |
| 23 #if defined(OS_MACOSX) |
| 24 #include <Carbon/Carbon.h> |
| 25 |
| 26 #include "base/mac/scoped_cftyperef.h" |
| 27 #endif |
| 28 |
| 23 namespace extensions { | 29 namespace extensions { |
| 24 | 30 |
| 25 typedef ExtensionApiTest GlobalCommandsApiTest; | 31 typedef ExtensionApiTest GlobalCommandsApiTest; |
| 26 | 32 |
| 27 #if defined(OS_LINUX) | 33 #if defined(OS_LINUX) |
| 28 // Send a simulated key press and release event, where |control|, |shift| or | 34 // Send a simulated key press and release event, where |control|, |shift| or |
| 29 // |alt| indicates whether the key is struck with corresponding modifier. | 35 // |alt| indicates whether the key is struck with corresponding modifier. |
| 30 void SendNativeKeyEventToXDisplay(ui::KeyboardCode key, | 36 void SendNativeKeyEventToXDisplay(ui::KeyboardCode key, |
| 31 bool control, | 37 bool control, |
| 32 bool shift, | 38 bool shift, |
| (...skipping 27 matching lines...) Expand all Loading... |
| 60 XTestFakeKeyEvent(display, *it, True, CurrentTime); | 66 XTestFakeKeyEvent(display, *it, True, CurrentTime); |
| 61 | 67 |
| 62 // Simulate the keys being released. | 68 // Simulate the keys being released. |
| 63 for (KeyCodes::iterator it = key_codes.begin(); it != key_codes.end(); it++) | 69 for (KeyCodes::iterator it = key_codes.begin(); it != key_codes.end(); it++) |
| 64 XTestFakeKeyEvent(display, *it, False, CurrentTime); | 70 XTestFakeKeyEvent(display, *it, False, CurrentTime); |
| 65 | 71 |
| 66 XFlush(display); | 72 XFlush(display); |
| 67 } | 73 } |
| 68 #endif // OS_LINUX | 74 #endif // OS_LINUX |
| 69 | 75 |
| 76 #if defined(OS_MACOSX) |
| 77 using base::ScopedCFTypeRef; |
| 78 |
| 79 void SendNativeCommandShift(int key_code) { |
| 80 CGEventSourceRef event_source = |
| 81 CGEventSourceCreate(kCGEventSourceStateHIDSystemState); |
| 82 CGEventTapLocation event_tap_location = kCGHIDEventTap; |
| 83 |
| 84 // Create the keyboard press events. |
| 85 ScopedCFTypeRef<CGEventRef> command_down(CGEventCreateKeyboardEvent( |
| 86 event_source, kVK_Command, true)); |
| 87 ScopedCFTypeRef<CGEventRef> shift_down(CGEventCreateKeyboardEvent( |
| 88 event_source, kVK_Shift, true)); |
| 89 ScopedCFTypeRef<CGEventRef> key_down(CGEventCreateKeyboardEvent( |
| 90 event_source, key_code, true)); |
| 91 CGEventSetFlags(key_down, kCGEventFlagMaskCommand | kCGEventFlagMaskShift); |
| 92 |
| 93 // Create the keyboard release events. |
| 94 ScopedCFTypeRef<CGEventRef> command_up(CGEventCreateKeyboardEvent( |
| 95 event_source, kVK_Command, false)); |
| 96 ScopedCFTypeRef<CGEventRef> shift_up(CGEventCreateKeyboardEvent( |
| 97 event_source, kVK_Shift, false)); |
| 98 ScopedCFTypeRef<CGEventRef> key_up(CGEventCreateKeyboardEvent( |
| 99 event_source, key_code, false)); |
| 100 CGEventSetFlags(key_up, kCGEventFlagMaskCommand | kCGEventFlagMaskShift); |
| 101 |
| 102 // Post all of the events. |
| 103 CGEventPost(event_tap_location, command_down); |
| 104 CGEventPost(event_tap_location, shift_down); |
| 105 CGEventPost(event_tap_location, key_down); |
| 106 CGEventPost(event_tap_location, key_up); |
| 107 CGEventPost(event_tap_location, shift_up); |
| 108 CGEventPost(event_tap_location, command_up); |
| 109 |
| 110 CFRelease(event_source); |
| 111 } |
| 112 #endif |
| 113 |
| 70 #if defined(OS_WIN) || (defined(OS_LINUX) && !defined(OS_CHROMEOS)) | 114 #if defined(OS_WIN) || (defined(OS_LINUX) && !defined(OS_CHROMEOS)) |
| 71 // The feature is only fully implemented on Windows and Linux, other platforms | 115 // The feature is only fully implemented on Windows and Linux, other platforms |
| 72 // coming. | 116 // coming. |
| 73 #define MAYBE_GlobalCommand GlobalCommand | 117 #define MAYBE_GlobalCommand GlobalCommand |
| 74 #else | 118 #else |
| 75 #define MAYBE_GlobalCommand DISABLED_GlobalCommand | 119 #define MAYBE_GlobalCommand DISABLED_GlobalCommand |
| 76 #endif | 120 #endif |
| 77 | 121 |
| 78 // Test the basics of global commands and make sure they work when Chrome | 122 // Test the basics of global commands and make sure they work when Chrome |
| 79 // doesn't have focus. Also test that non-global commands are not treated as | 123 // doesn't have focus. Also test that non-global commands are not treated as |
| 80 // global and that keys beyond Ctrl+Shift+[0..9] cannot be auto-assigned by an | 124 // global and that keys beyond Ctrl+Shift+[0..9] cannot be auto-assigned by an |
| 81 // extension. | 125 // extension. |
| 82 IN_PROC_BROWSER_TEST_F(GlobalCommandsApiTest, MAYBE_GlobalCommand) { | 126 IN_PROC_BROWSER_TEST_F(GlobalCommandsApiTest, MAYBE_GlobalCommand) { |
| 83 FeatureSwitch::ScopedOverride enable_global_commands( | 127 FeatureSwitch::ScopedOverride enable_global_commands( |
| 84 FeatureSwitch::global_commands(), true); | 128 FeatureSwitch::global_commands(), true); |
| 85 | 129 |
| 86 // Load the extension in the non-incognito browser. | 130 // Load the extension in the non-incognito browser. |
| 87 ResultCatcher catcher; | 131 ResultCatcher catcher; |
| 88 ASSERT_TRUE(RunExtensionTest("keybinding/global")) << message_; | 132 ASSERT_TRUE(RunExtensionTest("keybinding/global")) << message_; |
| 89 ASSERT_TRUE(catcher.GetNextResult()); | 133 ASSERT_TRUE(catcher.GetNextResult()); |
| 90 | 134 |
| 91 #if !defined(OS_LINUX) | 135 #if defined(OS_WIN) |
| 92 // Our infrastructure for sending keys expects a browser to send them to, but | 136 // Our infrastructure for sending keys expects a browser to send them to, but |
| 93 // to properly test global shortcuts you need to send them to another target. | 137 // to properly test global shortcuts you need to send them to another target. |
| 94 // So, create an incognito browser to use as a target to send the shortcuts | 138 // So, create an incognito browser to use as a target to send the shortcuts |
| 95 // to. It will ignore all of them and allow us test whether the global | 139 // to. It will ignore all of them and allow us test whether the global |
| 96 // shortcut really is global in nature and also that the non-global shortcut | 140 // shortcut really is global in nature and also that the non-global shortcut |
| 97 // is non-global. | 141 // is non-global. |
| 98 Browser* incognito_browser = CreateIncognitoBrowser(); | 142 Browser* incognito_browser = CreateIncognitoBrowser(); |
| 99 | 143 |
| 100 // Try to activate the non-global shortcut (Ctrl+Shift+1) and the | 144 // Try to activate the non-global shortcut (Ctrl+Shift+1) and the |
| 101 // non-assignable shortcut (Ctrl+Shift+A) by sending the keystrokes to the | 145 // non-assignable shortcut (Ctrl+Shift+A) by sending the keystrokes to the |
| 102 // incognito browser. Both shortcuts should have no effect (extension is not | 146 // incognito browser. Both shortcuts should have no effect (extension is not |
| 103 // loaded there). | 147 // loaded there). |
| 104 ASSERT_TRUE(ui_test_utils::SendKeyPressSync( | 148 ASSERT_TRUE(ui_test_utils::SendKeyPressSync( |
| 105 incognito_browser, ui::VKEY_1, true, true, false, false)); | 149 incognito_browser, ui::VKEY_1, true, true, false, false)); |
| 106 ASSERT_TRUE(ui_test_utils::SendKeyPressSync( | 150 ASSERT_TRUE(ui_test_utils::SendKeyPressSync( |
| 107 incognito_browser, ui::VKEY_A, true, true, false, false)); | 151 incognito_browser, ui::VKEY_A, true, true, false, false)); |
| 108 | 152 |
| 109 // Activate the shortcut (Ctrl+Shift+9). This should have an effect. | 153 // Activate the shortcut (Ctrl+Shift+9). This should have an effect. |
| 110 ASSERT_TRUE(ui_test_utils::SendKeyPressSync( | 154 ASSERT_TRUE(ui_test_utils::SendKeyPressSync( |
| 111 incognito_browser, ui::VKEY_9, true, true, false, false)); | 155 incognito_browser, ui::VKEY_9, true, true, false, false)); |
| 112 #else | 156 #elif defined(OS_LINUX) |
| 113 // Create an incognito browser to capture the focus. | 157 // Create an incognito browser to capture the focus. |
| 114 CreateIncognitoBrowser(); | 158 CreateIncognitoBrowser(); |
| 115 | 159 |
| 116 // On Linux, our infrastructure for sending keys just synthesize keyboard | 160 // On Linux, our infrastructure for sending keys just synthesize keyboard |
| 117 // event and send them directly to the specified window, without notifying the | 161 // event and send them directly to the specified window, without notifying the |
| 118 // X root window. It didn't work while testing global shortcut because the | 162 // X root window. It didn't work while testing global shortcut because the |
| 119 // stuff of global shortcut on Linux need to be notified when KeyPress event | 163 // stuff of global shortcut on Linux need to be notified when KeyPress event |
| 120 // is happening on X root window. So we simulate the keyboard input here. | 164 // is happening on X root window. So we simulate the keyboard input here. |
| 121 SendNativeKeyEventToXDisplay(ui::VKEY_1, true, true, false); | 165 SendNativeKeyEventToXDisplay(ui::VKEY_1, true, true, false); |
| 122 SendNativeKeyEventToXDisplay(ui::VKEY_A, true, true, false); | 166 SendNativeKeyEventToXDisplay(ui::VKEY_A, true, true, false); |
| 123 SendNativeKeyEventToXDisplay(ui::VKEY_9, true, true, false); | 167 SendNativeKeyEventToXDisplay(ui::VKEY_9, true, true, false); |
| 168 #elif defined(OS_MACOSX) |
| 169 // Create an incognito browser to capture the focus. |
| 170 CreateIncognitoBrowser(); |
| 171 |
| 172 // Send some native mac key events. |
| 173 SendNativeCommandShift(kVK_ANSI_1); |
| 174 SendNativeCommandShift(kVK_ANSI_A); |
| 175 SendNativeCommandShift(kVK_ANSI_9); |
| 124 #endif | 176 #endif |
| 125 | 177 |
| 126 // If this fails, it might be because the global shortcut failed to work, | 178 // If this fails, it might be because the global shortcut failed to work, |
| 127 // but it might also be because the non-global shortcuts unexpectedly | 179 // but it might also be because the non-global shortcuts unexpectedly |
| 128 // worked. | 180 // worked. |
| 129 ASSERT_TRUE(catcher.GetNextResult()) << catcher.message(); | 181 ASSERT_TRUE(catcher.GetNextResult()) << catcher.message(); |
| 130 } | 182 } |
| 131 | 183 |
| 132 #if defined(OS_WIN) | 184 #if defined(OS_WIN) |
| 133 // The feature is only fully implemented on Windows, other platforms coming. | 185 // The feature is only fully implemented on Windows, other platforms coming. |
| 186 // TODO(smus): On mac, SendKeyPress must first support media keys. |
| 134 #define MAYBE_GlobalDuplicatedMediaKey GlobalDuplicatedMediaKey | 187 #define MAYBE_GlobalDuplicatedMediaKey GlobalDuplicatedMediaKey |
| 135 #else | 188 #else |
| 136 #define MAYBE_GlobalDuplicatedMediaKey DISABLED_GlobalDuplicatedMediaKey | 189 #define MAYBE_GlobalDuplicatedMediaKey DISABLED_GlobalDuplicatedMediaKey |
| 137 #endif | 190 #endif |
| 138 | 191 |
| 139 IN_PROC_BROWSER_TEST_F(GlobalCommandsApiTest, MAYBE_GlobalDuplicatedMediaKey) { | 192 IN_PROC_BROWSER_TEST_F(GlobalCommandsApiTest, MAYBE_GlobalDuplicatedMediaKey) { |
| 140 FeatureSwitch::ScopedOverride enable_global_commands( | 193 FeatureSwitch::ScopedOverride enable_global_commands( |
| 141 FeatureSwitch::global_commands(), true); | 194 FeatureSwitch::global_commands(), true); |
| 142 | 195 |
| 143 ResultCatcher catcher; | 196 ResultCatcher catcher; |
| (...skipping 12 matching lines...) Expand all Loading... |
| 156 false, | 209 false, |
| 157 false, | 210 false, |
| 158 false); | 211 false); |
| 159 | 212 |
| 160 // We should get two success result. | 213 // We should get two success result. |
| 161 ASSERT_TRUE(catcher.GetNextResult()); | 214 ASSERT_TRUE(catcher.GetNextResult()); |
| 162 ASSERT_TRUE(catcher.GetNextResult()); | 215 ASSERT_TRUE(catcher.GetNextResult()); |
| 163 } | 216 } |
| 164 | 217 |
| 165 } // namespace extensions | 218 } // namespace extensions |
| OLD | NEW |