Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(98)

Side by Side Diff: chrome/test/webdriver/webdriver_key_converter.cc

Issue 23526047: Delete old chromedriver code, and remove mongoose webserver. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: . Created 7 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
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 "chrome/test/webdriver/webdriver_key_converter.h"
6
7 #include "base/format_macros.h"
8 #include "base/logging.h"
9 #include "base/strings/stringprintf.h"
10 #include "base/strings/utf_string_conversions.h"
11 #include "chrome/common/automation_constants.h"
12 #include "chrome/test/automation/automation_json_requests.h"
13 #include "chrome/test/webdriver/keycode_text_conversion.h"
14 #include "chrome/test/webdriver/webdriver_logging.h"
15
16 namespace {
17
18 struct ModifierMaskAndKeyCode {
19 int mask;
20 ui::KeyboardCode key_code;
21 };
22
23 const ModifierMaskAndKeyCode kModifiers[] = {
24 { automation::kShiftKeyMask, ui::VKEY_SHIFT },
25 { automation::kControlKeyMask, ui::VKEY_CONTROL },
26 { automation::kAltKeyMask, ui::VKEY_MENU }
27 };
28
29 // TODO(kkania): Use this in KeyMap.
30 // Ordered list of all the key codes corresponding to special WebDriver keys.
31 // These WebDriver keys are defined in the Unicode Private Use Area.
32 // http://code.google.com/p/selenium/wiki/JsonWireProtocol#/session/:sessionId/e lement/:id/value
33 const ui::KeyboardCode kSpecialWebDriverKeys[] = {
34 ui::VKEY_UNKNOWN,
35 ui::VKEY_UNKNOWN,
36 ui::VKEY_HELP,
37 ui::VKEY_BACK,
38 ui::VKEY_TAB,
39 ui::VKEY_CLEAR,
40 ui::VKEY_RETURN,
41 ui::VKEY_RETURN,
42 ui::VKEY_SHIFT,
43 ui::VKEY_CONTROL,
44 ui::VKEY_MENU,
45 ui::VKEY_PAUSE,
46 ui::VKEY_ESCAPE,
47 ui::VKEY_SPACE,
48 ui::VKEY_PRIOR, // page up
49 ui::VKEY_NEXT, // page down
50 ui::VKEY_END,
51 ui::VKEY_HOME,
52 ui::VKEY_LEFT,
53 ui::VKEY_UP,
54 ui::VKEY_RIGHT,
55 ui::VKEY_DOWN,
56 ui::VKEY_INSERT,
57 ui::VKEY_DELETE,
58 ui::VKEY_OEM_1, // semicolon
59 ui::VKEY_OEM_PLUS, // equals
60 ui::VKEY_NUMPAD0,
61 ui::VKEY_NUMPAD1,
62 ui::VKEY_NUMPAD2,
63 ui::VKEY_NUMPAD3,
64 ui::VKEY_NUMPAD4,
65 ui::VKEY_NUMPAD5,
66 ui::VKEY_NUMPAD6,
67 ui::VKEY_NUMPAD7,
68 ui::VKEY_NUMPAD8,
69 ui::VKEY_NUMPAD9,
70 ui::VKEY_MULTIPLY,
71 ui::VKEY_ADD,
72 ui::VKEY_OEM_COMMA,
73 ui::VKEY_SUBTRACT,
74 ui::VKEY_DECIMAL,
75 ui::VKEY_DIVIDE,
76 ui::VKEY_UNKNOWN,
77 ui::VKEY_UNKNOWN,
78 ui::VKEY_UNKNOWN,
79 ui::VKEY_UNKNOWN,
80 ui::VKEY_UNKNOWN,
81 ui::VKEY_UNKNOWN,
82 ui::VKEY_UNKNOWN,
83 ui::VKEY_F1,
84 ui::VKEY_F2,
85 ui::VKEY_F3,
86 ui::VKEY_F4,
87 ui::VKEY_F5,
88 ui::VKEY_F6,
89 ui::VKEY_F7,
90 ui::VKEY_F8,
91 ui::VKEY_F9,
92 ui::VKEY_F10,
93 ui::VKEY_F11,
94 ui::VKEY_F12};
95
96 const char16 kWebDriverNullKey = 0xE000U;
97 const char16 kWebDriverShiftKey = 0xE008U;
98 const char16 kWebDriverControlKey = 0xE009U;
99 const char16 kWebDriverAltKey = 0xE00AU;
100 const char16 kWebDriverCommandKey = 0xE03DU;
101
102 // Returns whether the given key is a WebDriver key modifier.
103 bool IsModifierKey(char16 key) {
104 switch (key) {
105 case kWebDriverShiftKey:
106 case kWebDriverControlKey:
107 case kWebDriverAltKey:
108 case kWebDriverCommandKey:
109 return true;
110 default:
111 return false;
112 }
113 }
114
115 // Gets the key code associated with |key|, if it is a special WebDriver key.
116 // Returns whether |key| is a special WebDriver key. If true, |key_code| will
117 // be set.
118 bool KeyCodeFromSpecialWebDriverKey(char16 key, ui::KeyboardCode* key_code) {
119 int index = static_cast<int>(key) - 0xE000U;
120 bool is_special_key = index >= 0 &&
121 index < static_cast<int>(arraysize(kSpecialWebDriverKeys));
122 if (is_special_key)
123 *key_code = kSpecialWebDriverKeys[index];
124 return is_special_key;
125 }
126
127 // Gets the key code associated with |key|, if it is a special shorthand key.
128 // Shorthand keys are common text equivalents for keys, such as the newline
129 // character, which is shorthand for the return key. Returns whether |key| is
130 // a shorthand key. If true, |key_code| will be set and |client_should_skip|
131 // will be set to whether the key should be skipped.
132 bool KeyCodeFromShorthandKey(char16 key_utf16,
133 ui::KeyboardCode* key_code,
134 bool* client_should_skip) {
135 string16 key_str_utf16;
136 key_str_utf16.push_back(key_utf16);
137 std::string key_str_utf8 = UTF16ToUTF8(key_str_utf16);
138 if (key_str_utf8.length() != 1)
139 return false;
140 bool should_skip = false;
141 char key = key_str_utf8[0];
142 if (key == '\n') {
143 *key_code = ui::VKEY_RETURN;
144 } else if (key == '\t') {
145 *key_code = ui::VKEY_TAB;
146 } else if (key == '\b') {
147 *key_code = ui::VKEY_BACK;
148 } else if (key == ' ') {
149 *key_code = ui::VKEY_SPACE;
150 } else if (key == '\r') {
151 *key_code = ui::VKEY_UNKNOWN;
152 should_skip = true;
153 } else {
154 return false;
155 }
156 *client_should_skip = should_skip;
157 return true;
158 }
159
160 } // namespace
161
162 namespace webdriver {
163
164 WebKeyEvent CreateKeyDownEvent(ui::KeyboardCode key_code, int modifiers) {
165 return WebKeyEvent(automation::kRawKeyDownType,
166 key_code,
167 std::string(),
168 std::string(),
169 modifiers);
170 }
171
172 WebKeyEvent CreateKeyUpEvent(ui::KeyboardCode key_code, int modifiers) {
173 return WebKeyEvent(automation::kKeyUpType,
174 key_code,
175 std::string(),
176 std::string(),
177 modifiers);
178 }
179
180 WebKeyEvent CreateCharEvent(const std::string& unmodified_text,
181 const std::string& modified_text,
182 int modifiers) {
183 return WebKeyEvent(automation::kCharType,
184 ui::VKEY_UNKNOWN,
185 unmodified_text,
186 modified_text,
187 modifiers);
188 }
189
190 bool ConvertKeysToWebKeyEvents(const string16& client_keys,
191 const Logger& logger,
192 bool release_modifiers,
193 int* modifiers,
194 std::vector<WebKeyEvent>* client_key_events,
195 std::string* error_msg) {
196 std::vector<WebKeyEvent> key_events;
197
198 string16 keys = client_keys;
199 // Add an implicit NULL character to the end of the input to depress all
200 // modifiers.
201 if (release_modifiers)
202 keys.push_back(kWebDriverNullKey);
203
204 int sticky_modifiers = *modifiers;
205 for (size_t i = 0; i < keys.size(); ++i) {
206 char16 key = keys[i];
207
208 if (key == kWebDriverNullKey) {
209 // Release all modifier keys and clear |stick_modifiers|.
210 if (sticky_modifiers & automation::kShiftKeyMask)
211 key_events.push_back(CreateKeyUpEvent(ui::VKEY_SHIFT, 0));
212 if (sticky_modifiers & automation::kControlKeyMask)
213 key_events.push_back(CreateKeyUpEvent(ui::VKEY_CONTROL, 0));
214 if (sticky_modifiers & automation::kAltKeyMask)
215 key_events.push_back(CreateKeyUpEvent(ui::VKEY_MENU, 0));
216 if (sticky_modifiers & automation::kMetaKeyMask)
217 key_events.push_back(CreateKeyUpEvent(ui::VKEY_COMMAND, 0));
218 sticky_modifiers = 0;
219 continue;
220 }
221 if (IsModifierKey(key)) {
222 // Press or release the modifier, and adjust |sticky_modifiers|.
223 bool modifier_down = false;
224 ui::KeyboardCode key_code = ui::VKEY_UNKNOWN;
225 if (key == kWebDriverShiftKey) {
226 sticky_modifiers ^= automation::kShiftKeyMask;
227 modifier_down = sticky_modifiers & automation::kShiftKeyMask;
228 key_code = ui::VKEY_SHIFT;
229 } else if (key == kWebDriverControlKey) {
230 sticky_modifiers ^= automation::kControlKeyMask;
231 modifier_down = sticky_modifiers & automation::kControlKeyMask;
232 key_code = ui::VKEY_CONTROL;
233 } else if (key == kWebDriverAltKey) {
234 sticky_modifiers ^= automation::kAltKeyMask;
235 modifier_down = sticky_modifiers & automation::kAltKeyMask;
236 key_code = ui::VKEY_MENU;
237 } else if (key == kWebDriverCommandKey) {
238 sticky_modifiers ^= automation::kMetaKeyMask;
239 modifier_down = sticky_modifiers & automation::kMetaKeyMask;
240 key_code = ui::VKEY_COMMAND;
241 } else {
242 NOTREACHED();
243 }
244 if (modifier_down)
245 key_events.push_back(CreateKeyDownEvent(key_code, sticky_modifiers));
246 else
247 key_events.push_back(CreateKeyUpEvent(key_code, sticky_modifiers));
248 continue;
249 }
250
251 ui::KeyboardCode key_code = ui::VKEY_UNKNOWN;
252 std::string unmodified_text, modified_text;
253 int all_modifiers = sticky_modifiers;
254
255 // Get the key code, text, and modifiers for the given key.
256 bool should_skip = false;
257 if (KeyCodeFromSpecialWebDriverKey(key, &key_code) ||
258 KeyCodeFromShorthandKey(key, &key_code, &should_skip)) {
259 if (should_skip)
260 continue;
261 if (key_code == ui::VKEY_UNKNOWN) {
262 *error_msg = base::StringPrintf(
263 "Unknown WebDriver key(%d) at string index (%" PRIuS ")",
264 static_cast<int>(key),
265 i);
266 return false;
267 }
268 if (key_code == ui::VKEY_RETURN) {
269 // For some reason Chrome expects a carriage return for the return key.
270 modified_text = unmodified_text = "\r";
271 } else {
272 // WebDriver assumes a numpad key should translate to the number,
273 // which requires NumLock to be on with some platforms. This isn't
274 // formally in the spec, but is expected by their tests.
275 int webdriver_modifiers = 0;
276 if (key_code >= ui::VKEY_NUMPAD0 && key_code <= ui::VKEY_NUMPAD9)
277 webdriver_modifiers = automation::kNumLockKeyMask;
278 unmodified_text = ConvertKeyCodeToText(key_code, webdriver_modifiers);
279 modified_text = ConvertKeyCodeToText(
280 key_code,
281 all_modifiers | webdriver_modifiers);
282 }
283 } else {
284 int necessary_modifiers = 0;
285 ConvertCharToKeyCode(key, &key_code, &necessary_modifiers);
286 all_modifiers |= necessary_modifiers;
287 if (key_code != ui::VKEY_UNKNOWN) {
288 unmodified_text = ConvertKeyCodeToText(key_code, 0);
289 modified_text = ConvertKeyCodeToText(key_code, all_modifiers);
290 }
291 if (unmodified_text.empty() || modified_text.empty()) {
292 // Do a best effort and use the raw key we were given.
293 logger.Log(
294 kWarningLogLevel,
295 base::StringPrintf("No translation for key code. Code point: %d",
296 static_cast<int>(key)));
297 if (unmodified_text.empty())
298 unmodified_text = UTF16ToUTF8(keys.substr(i, 1));
299 if (modified_text.empty())
300 modified_text = UTF16ToUTF8(keys.substr(i, 1));
301 }
302 }
303
304 // Create the key events.
305 bool necessary_modifiers[3];
306 for (int i = 0; i < 3; ++i) {
307 necessary_modifiers[i] =
308 all_modifiers & kModifiers[i].mask &&
309 !(sticky_modifiers & kModifiers[i].mask);
310 if (necessary_modifiers[i]) {
311 key_events.push_back(
312 CreateKeyDownEvent(kModifiers[i].key_code, sticky_modifiers));
313 }
314 }
315
316 key_events.push_back(CreateKeyDownEvent(key_code, all_modifiers));
317 if (unmodified_text.length() || modified_text.length()) {
318 key_events.push_back(
319 CreateCharEvent(unmodified_text, modified_text, all_modifiers));
320 }
321 key_events.push_back(CreateKeyUpEvent(key_code, all_modifiers));
322
323 for (int i = 2; i > -1; --i) {
324 if (necessary_modifiers[i]) {
325 key_events.push_back(
326 CreateKeyUpEvent(kModifiers[i].key_code, sticky_modifiers));
327 }
328 }
329 }
330 client_key_events->swap(key_events);
331 *modifiers = sticky_modifiers;
332 return true;
333 }
334
335 } // namespace webdriver
OLDNEW
« no previous file with comments | « chrome/test/webdriver/webdriver_key_converter.h ('k') | chrome/test/webdriver/webdriver_key_converter_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698