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 #endif | |
26 | |
23 namespace extensions { | 27 namespace extensions { |
24 | 28 |
25 typedef ExtensionApiTest GlobalCommandsApiTest; | 29 typedef ExtensionApiTest GlobalCommandsApiTest; |
26 | 30 |
27 #if defined(OS_LINUX) | 31 #if defined(OS_LINUX) |
28 // Send a simulated key press and release event, where |control|, |shift| or | 32 // Send a simulated key press and release event, where |control|, |shift| or |
29 // |alt| indicates whether the key is struck with corresponding modifier. | 33 // |alt| indicates whether the key is struck with corresponding modifier. |
30 void SendNativeKeyEventToXDisplay(ui::KeyboardCode key, | 34 void SendNativeKeyEventToXDisplay(ui::KeyboardCode key, |
31 bool control, | 35 bool control, |
32 bool shift, | 36 bool shift, |
(...skipping 27 matching lines...) Expand all Loading... | |
60 XTestFakeKeyEvent(display, *it, True, CurrentTime); | 64 XTestFakeKeyEvent(display, *it, True, CurrentTime); |
61 | 65 |
62 // Simulate the keys being released. | 66 // Simulate the keys being released. |
63 for (KeyCodes::iterator it = key_codes.begin(); it != key_codes.end(); it++) | 67 for (KeyCodes::iterator it = key_codes.begin(); it != key_codes.end(); it++) |
64 XTestFakeKeyEvent(display, *it, False, CurrentTime); | 68 XTestFakeKeyEvent(display, *it, False, CurrentTime); |
65 | 69 |
66 XFlush(display); | 70 XFlush(display); |
67 } | 71 } |
68 #endif // OS_LINUX | 72 #endif // OS_LINUX |
69 | 73 |
70 #if defined(OS_WIN) || (defined(OS_LINUX) && !defined(OS_CHROMEOS)) | 74 #if defined(OS_MACOSX) |
75 void SendNativeCommandShift(int key_code) { | |
76 CGEventSourceRef src = | |
77 CGEventSourceCreate(kCGEventSourceStateHIDSystemState); | |
78 | |
79 CGEventRef cmd_d = CGEventCreateKeyboardEvent(src, kVK_Command, true); | |
Robert Sesek
2013/12/09 19:17:42
You should place these in a ScopedCFTypeRef so tha
Mark Mentovai
2013/12/09 19:31:54
This sounds like the key event is for command-D, c
smus
2013/12/09 23:37:06
Done.
| |
80 CGEventRef cmd_u = CGEventCreateKeyboardEvent(src, kVK_Command, false); | |
Mark Mentovai
2013/12/09 19:31:54
Why don’t you create these in the order that they
smus
2013/12/09 23:37:06
Done.
| |
81 CGEventRef shift_d = CGEventCreateKeyboardEvent(src, kVK_Shift, true); | |
82 CGEventRef shift_u = CGEventCreateKeyboardEvent(src, kVK_Shift, false); | |
83 CGEventRef key_d = CGEventCreateKeyboardEvent(src, key_code, true); | |
84 CGEventRef key_u = CGEventCreateKeyboardEvent(src, key_code, false); | |
85 | |
86 CGEventSetFlags(key_d, kCGEventFlagMaskCommand | kCGEventFlagMaskShift); | |
Mark Mentovai
2013/12/09 19:31:54
This should immediately follow the creation of key
smus
2013/12/09 23:37:06
Done.
| |
87 CGEventSetFlags(key_u, kCGEventFlagMaskCommand | kCGEventFlagMaskShift); | |
Mark Mentovai
2013/12/09 19:31:54
Ditto, key_u.
smus
2013/12/09 23:37:06
Done.
| |
88 | |
89 CGEventTapLocation loc = kCGHIDEventTap; // kCGSessionEventTap also works | |
Mark Mentovai
2013/12/09 19:31:54
http://google-styleguide.googlecode.com/svn/trunk/
smus
2013/12/09 23:37:06
Done.
| |
90 CGEventPost(loc, cmd_d); | |
91 CGEventPost(loc, shift_d); | |
92 CGEventPost(loc, key_d); | |
93 CGEventPost(loc, key_u); | |
94 CGEventPost(loc, shift_u); | |
95 CGEventPost(loc, cmd_u); | |
96 | |
97 CFRelease(cmd_d); | |
Mark Mentovai
2013/12/09 19:31:54
Use a base::ScopedCFTypeRef (base/mac/scoped_cftyp
smus
2013/12/09 23:37:06
Done.
| |
98 CFRelease(cmd_u); | |
99 CFRelease(shift_d); | |
100 CFRelease(shift_u); | |
101 CFRelease(key_d); | |
102 CFRelease(key_u); | |
103 CFRelease(src); | |
104 } | |
105 #endif | |
106 | |
107 #if defined(OS_WIN) || (defined(OS_LINUX) && !defined(OS_CHROMEOS)) || defined(O S_MACOSX) | |
71 // The feature is only fully implemented on Windows and Linux, other platforms | 108 // The feature is only fully implemented on Windows and Linux, other platforms |
72 // coming. | 109 // coming. |
73 #define MAYBE_GlobalCommand GlobalCommand | 110 #define MAYBE_GlobalCommand GlobalCommand |
74 #else | 111 #else |
75 #define MAYBE_GlobalCommand DISABLED_GlobalCommand | 112 #define MAYBE_GlobalCommand DISABLED_GlobalCommand |
76 #endif | 113 #endif |
77 | 114 |
78 // Test the basics of global commands and make sure they work when Chrome | 115 // 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 | 116 // 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 | 117 // global and that keys beyond Ctrl+Shift+[0..9] cannot be auto-assigned by an |
81 // extension. | 118 // extension. |
82 IN_PROC_BROWSER_TEST_F(GlobalCommandsApiTest, MAYBE_GlobalCommand) { | 119 IN_PROC_BROWSER_TEST_F(GlobalCommandsApiTest, MAYBE_GlobalCommand) { |
83 FeatureSwitch::ScopedOverride enable_global_commands( | 120 FeatureSwitch::ScopedOverride enable_global_commands( |
84 FeatureSwitch::global_commands(), true); | 121 FeatureSwitch::global_commands(), true); |
85 | 122 |
86 // Load the extension in the non-incognito browser. | 123 // Load the extension in the non-incognito browser. |
87 ResultCatcher catcher; | 124 ResultCatcher catcher; |
88 ASSERT_TRUE(RunExtensionTest("keybinding/global")) << message_; | 125 ASSERT_TRUE(RunExtensionTest("keybinding/global")) << message_; |
89 ASSERT_TRUE(catcher.GetNextResult()); | 126 ASSERT_TRUE(catcher.GetNextResult()); |
90 | 127 |
91 #if !defined(OS_LINUX) | 128 #if defined(OS_WIN) |
92 // Our infrastructure for sending keys expects a browser to send them to, but | 129 // 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. | 130 // 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 | 131 // 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 | 132 // 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 | 133 // shortcut really is global in nature and also that the non-global shortcut |
97 // is non-global. | 134 // is non-global. |
98 Browser* incognito_browser = CreateIncognitoBrowser(); | 135 Browser* incognito_browser = CreateIncognitoBrowser(); |
99 | 136 |
100 // Try to activate the non-global shortcut (Ctrl+Shift+1) and the | 137 // 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 | 138 // non-assignable shortcut (Ctrl+Shift+A) by sending the keystrokes to the |
102 // incognito browser. Both shortcuts should have no effect (extension is not | 139 // incognito browser. Both shortcuts should have no effect (extension is not |
103 // loaded there). | 140 // loaded there). |
104 ASSERT_TRUE(ui_test_utils::SendKeyPressSync( | 141 ASSERT_TRUE(ui_test_utils::SendKeyPressSync( |
105 incognito_browser, ui::VKEY_1, true, true, false, false)); | 142 incognito_browser, ui::VKEY_1, true, true, false, false)); |
106 ASSERT_TRUE(ui_test_utils::SendKeyPressSync( | 143 ASSERT_TRUE(ui_test_utils::SendKeyPressSync( |
107 incognito_browser, ui::VKEY_A, true, true, false, false)); | 144 incognito_browser, ui::VKEY_A, true, true, false, false)); |
108 | 145 |
109 // Activate the shortcut (Ctrl+Shift+9). This should have an effect. | 146 // Activate the shortcut (Ctrl+Shift+9). This should have an effect. |
110 ASSERT_TRUE(ui_test_utils::SendKeyPressSync( | 147 ASSERT_TRUE(ui_test_utils::SendKeyPressSync( |
111 incognito_browser, ui::VKEY_9, true, true, false, false)); | 148 incognito_browser, ui::VKEY_9, true, true, false, false)); |
112 #else | 149 #elif defined(OS_LINUX) |
113 // Create an incognito browser to capture the focus. | 150 // Create an incognito browser to capture the focus. |
114 CreateIncognitoBrowser(); | 151 CreateIncognitoBrowser(); |
115 | 152 |
116 // On Linux, our infrastructure for sending keys just synthesize keyboard | 153 // On Linux, our infrastructure for sending keys just synthesize keyboard |
117 // event and send them directly to the specified window, without notifying the | 154 // 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 | 155 // 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 | 156 // 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. | 157 // is happening on X root window. So we simulate the keyboard input here. |
121 SendNativeKeyEventToXDisplay(ui::VKEY_1, true, true, false); | 158 SendNativeKeyEventToXDisplay(ui::VKEY_1, true, true, false); |
122 SendNativeKeyEventToXDisplay(ui::VKEY_A, true, true, false); | 159 SendNativeKeyEventToXDisplay(ui::VKEY_A, true, true, false); |
123 SendNativeKeyEventToXDisplay(ui::VKEY_9, true, true, false); | 160 SendNativeKeyEventToXDisplay(ui::VKEY_9, true, true, false); |
161 #elif defined(OS_MACOSX) | |
162 // Create an incognito browser to capture the focus. | |
163 CreateIncognitoBrowser(); | |
164 | |
165 // Send some native mac key events. | |
166 SendNativeCommandShift(kVK_ANSI_1); | |
167 SendNativeCommandShift(kVK_ANSI_A); | |
168 SendNativeCommandShift(kVK_ANSI_9); | |
124 #endif | 169 #endif |
125 | 170 |
126 // If this fails, it might be because the global shortcut failed to work, | 171 // 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 | 172 // but it might also be because the non-global shortcuts unexpectedly |
128 // worked. | 173 // worked. |
129 ASSERT_TRUE(catcher.GetNextResult()) << catcher.message(); | 174 ASSERT_TRUE(catcher.GetNextResult()) << catcher.message(); |
130 } | 175 } |
131 | 176 |
132 #if defined(OS_WIN) | 177 #if defined(OS_WIN) |
133 // The feature is only fully implemented on Windows, other platforms coming. | 178 // The feature is only fully implemented on Windows, other platforms coming. |
179 // TODO(smus): On mac, SendKeyPress must first support media keys. | |
134 #define MAYBE_GlobalDuplicatedMediaKey GlobalDuplicatedMediaKey | 180 #define MAYBE_GlobalDuplicatedMediaKey GlobalDuplicatedMediaKey |
135 #else | 181 #else |
136 #define MAYBE_GlobalDuplicatedMediaKey DISABLED_GlobalDuplicatedMediaKey | 182 #define MAYBE_GlobalDuplicatedMediaKey DISABLED_GlobalDuplicatedMediaKey |
137 #endif | 183 #endif |
138 | 184 |
139 IN_PROC_BROWSER_TEST_F(GlobalCommandsApiTest, MAYBE_GlobalDuplicatedMediaKey) { | 185 IN_PROC_BROWSER_TEST_F(GlobalCommandsApiTest, MAYBE_GlobalDuplicatedMediaKey) { |
140 FeatureSwitch::ScopedOverride enable_global_commands( | 186 FeatureSwitch::ScopedOverride enable_global_commands( |
141 FeatureSwitch::global_commands(), true); | 187 FeatureSwitch::global_commands(), true); |
142 | 188 |
143 ResultCatcher catcher; | 189 ResultCatcher catcher; |
(...skipping 12 matching lines...) Expand all Loading... | |
156 false, | 202 false, |
157 false, | 203 false, |
158 false); | 204 false); |
159 | 205 |
160 // We should get two success result. | 206 // We should get two success result. |
161 ASSERT_TRUE(catcher.GetNextResult()); | 207 ASSERT_TRUE(catcher.GetNextResult()); |
162 ASSERT_TRUE(catcher.GetNextResult()); | 208 ASSERT_TRUE(catcher.GetNextResult()); |
163 } | 209 } |
164 | 210 |
165 } // namespace extensions | 211 } // namespace extensions |
OLD | NEW |