diff options
author | kkania@chromium.org <kkania@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-07-26 15:32:18 +0000 |
---|---|---|
committer | kkania@chromium.org <kkania@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-07-26 15:32:18 +0000 |
commit | 376d1e164bdfde1ca048d1dac77028b7b8af531e (patch) | |
tree | 24fbbd8558084c83a95e1f004df62383aaff29c6 /chrome | |
parent | 61eeb33fdbc9925e18b7132947e99a895861b666 (diff) | |
download | chromium_src-376d1e164bdfde1ca048d1dac77028b7b8af531e.zip chromium_src-376d1e164bdfde1ca048d1dac77028b7b8af531e.tar.gz chromium_src-376d1e164bdfde1ca048d1dac77028b7b8af531e.tar.bz2 |
Fix chromedriver to generate control and/or alt key strokes when given a character that requires it.
Also, print out the version info and accept integers or floats when getting the first client rect.
BUG=85239,88565
TEST=none
Review URL: http://codereview.chromium.org/7412003
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@94097 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome')
-rw-r--r-- | chrome/chrome_tests.gypi | 2 | ||||
-rw-r--r-- | chrome/test/webdriver/keycode_text_conversion_mac.mm | 13 | ||||
-rw-r--r-- | chrome/test/webdriver/keycode_text_conversion_unittest.cc | 43 | ||||
-rw-r--r-- | chrome/test/webdriver/keycode_text_conversion_win.cc | 6 | ||||
-rw-r--r-- | chrome/test/webdriver/server.cc | 8 | ||||
-rw-r--r-- | chrome/test/webdriver/session.cc | 14 | ||||
-rw-r--r-- | chrome/test/webdriver/webdriver_key_converter.cc | 34 | ||||
-rw-r--r-- | chrome/test/webdriver/webdriver_key_converter_unittest.cc | 22 | ||||
-rw-r--r-- | chrome/test/webdriver/webdriver_test_util.cc | 62 | ||||
-rw-r--r-- | chrome/test/webdriver/webdriver_test_util.h | 56 |
10 files changed, 226 insertions, 34 deletions
diff --git a/chrome/chrome_tests.gypi b/chrome/chrome_tests.gypi index fd795af..414e187 100644 --- a/chrome/chrome_tests.gypi +++ b/chrome/chrome_tests.gypi @@ -1002,6 +1002,8 @@ 'test/webdriver/keycode_text_conversion_unittest.cc', 'test/webdriver/utility_functions_unittest.cc', 'test/webdriver/webdriver_key_converter_unittest.cc', + 'test/webdriver/webdriver_test_util.cc', + 'test/webdriver/webdriver_test_util.h', ], 'conditions': [ ['OS=="win"', { diff --git a/chrome/test/webdriver/keycode_text_conversion_mac.mm b/chrome/test/webdriver/keycode_text_conversion_mac.mm index fc142be..5dbe6bf 100644 --- a/chrome/test/webdriver/keycode_text_conversion_mac.mm +++ b/chrome/test/webdriver/keycode_text_conversion_mac.mm @@ -30,7 +30,16 @@ std::string ConvertKeyCodeToText(ui::KeyboardCode key_code, int modifiers) { int mac_modifiers = 0; if (modifiers & automation::kShiftKeyMask) - mac_modifiers = shiftKey >> 8; + mac_modifiers |= shiftKey; + if (modifiers & automation::kControlKeyMask) + mac_modifiers |= controlKey; + if (modifiers & automation::kAltKeyMask) + mac_modifiers |= optionKey; + if (modifiers & automation::kMetaKeyMask) + mac_modifiers |= cmdKey; + // Convert EventRecord modifiers to format UCKeyTranslate accepts. See docs + // on UCKeyTranslate for more info. + UInt32 modifier_key_state = (mac_modifiers >> 8) & 0xFF; base::mac::ScopedCFTypeRef<TISInputSourceRef> input_source_copy( TISCopyCurrentKeyboardLayoutInputSource()); @@ -44,7 +53,7 @@ std::string ConvertKeyCodeToText(ui::KeyboardCode key_code, int modifiers) { reinterpret_cast<const UCKeyboardLayout*>(CFDataGetBytePtr(layout_data)), static_cast<UInt16>(mac_key_code), kUCKeyActionDown, - mac_modifiers, + modifier_key_state, LMGetKbdLast(), kUCKeyTranslateNoDeadKeysBit, &dead_key_state, diff --git a/chrome/test/webdriver/keycode_text_conversion_unittest.cc b/chrome/test/webdriver/keycode_text_conversion_unittest.cc index 02f2db3..35dd538 100644 --- a/chrome/test/webdriver/keycode_text_conversion_unittest.cc +++ b/chrome/test/webdriver/keycode_text_conversion_unittest.cc @@ -8,6 +8,7 @@ #include "base/utf_string_conversions.h" #include "chrome/common/automation_constants.h" #include "chrome/test/webdriver/keycode_text_conversion.h" +#include "chrome/test/webdriver/webdriver_test_util.h" #include "testing/gtest/include/gtest/gtest.h" #include "ui/base/keycodes/keyboard_codes.h" @@ -15,7 +16,7 @@ using automation::kShiftKeyMask; using webdriver::ConvertKeyCodeToText; using webdriver::ConvertCharToKeyCode; -namespace { +namespace webdriver { void CheckCharToKeyCode(char character, ui::KeyboardCode key_code, int modifiers) { @@ -77,4 +78,42 @@ TEST(KeycodeTextConversionTest, CharToKeyCode) { CheckCantConvertChar(L'\u2159'); } -} // namespace +#if defined(OS_LINUX) +#define MAYBE_NonShiftModifiers DISABLED_NonShiftModifiers +#else +#define MAYBE_NonShiftModifiers NonShiftModifiers +#endif + +TEST(KeycodeTextConversionTest, MAYBE_NonShiftModifiers) { + RestoreKeyboardLayoutOnDestruct restore; +#if defined(OS_WIN) + ASSERT_TRUE(SwitchKeyboardLayout("00000407")); // german + int ctrl_and_alt = automation::kControlKeyMask | automation::kAltKeyMask; + CheckCharToKeyCode('@', ui::VKEY_Q, ctrl_and_alt); + EXPECT_EQ("@", ConvertKeyCodeToText(ui::VKEY_Q, ctrl_and_alt)); +#elif defined(OS_MACOSX) + ASSERT_TRUE(SwitchKeyboardLayout("com.apple.keylayout.German")); + EXPECT_EQ("@", ConvertKeyCodeToText(ui::VKEY_L, automation::kAltKeyMask)); +#endif +} + +#if defined(OS_LINUX) +#define MAYBE_NonEnglish DISABLED_NonEnglish +#else +#define MAYBE_NonEnglish NonEnglish +#endif + +TEST(KeycodeTextConversionTest, MAYBE_NonEnglish) { + RestoreKeyboardLayoutOnDestruct restore; +#if defined(OS_WIN) + ASSERT_TRUE(SwitchKeyboardLayout("00000408")); // greek + CheckCharToKeyCode(';', ui::VKEY_Q, 0); + EXPECT_EQ(";", ConvertKeyCodeToText(ui::VKEY_Q, 0)); +#elif defined(OS_MACOSX) + ASSERT_TRUE(SwitchKeyboardLayout("com.apple.keylayout.German")); + CheckCharToKeyCode('z', ui::VKEY_Y, 0); + EXPECT_EQ("z", ConvertKeyCodeToText(ui::VKEY_Y, 0)); +#endif +} + +} // namespace webdriver diff --git a/chrome/test/webdriver/keycode_text_conversion_win.cc b/chrome/test/webdriver/keycode_text_conversion_win.cc index 2863fc1..180c923 100644 --- a/chrome/test/webdriver/keycode_text_conversion_win.cc +++ b/chrome/test/webdriver/keycode_text_conversion_win.cc @@ -16,9 +16,13 @@ namespace webdriver { std::string ConvertKeyCodeToText(ui::KeyboardCode key_code, int modifiers) { UINT scan_code = ::MapVirtualKeyW(key_code, MAPVK_VK_TO_VSC); BYTE keyboard_state[256]; - ::GetKeyboardState(keyboard_state); + memset(keyboard_state, 0, 256); if (modifiers & automation::kShiftKeyMask) keyboard_state[VK_SHIFT] |= 0x80; + if (modifiers & automation::kControlKeyMask) + keyboard_state[VK_CONTROL] |= 0x80; + if (modifiers & automation::kAltKeyMask) + keyboard_state[VK_MENU] |= 0x80; wchar_t chars[5]; int code = ::ToUnicode(key_code, scan_code, keyboard_state, chars, 4, 0); // |ToUnicode| converts some non-text key codes like F1 to various ASCII diff --git a/chrome/test/webdriver/server.cc b/chrome/test/webdriver/server.cc index e118466..4f612d1 100644 --- a/chrome/test/webdriver/server.cc +++ b/chrome/test/webdriver/server.cc @@ -25,6 +25,7 @@ #include "base/test/test_timeouts.h" #include "base/threading/platform_thread.h" #include "base/utf_string_conversions.h" +#include "chrome/common/chrome_constants.h" #include "chrome/common/chrome_paths.h" #include "chrome/common/chrome_switches.h" #include "chrome/test/webdriver/commands/alert_commands.h" @@ -229,11 +230,8 @@ int main(int argc, char *argv[]) { // The tests depend on parsing the first line ChromeDriver outputs, // so all other logging should happen after this. std::cout << "Started ChromeDriver" << std::endl - << "port=" << port << std::endl; - - if (root.length()) { - VLOG(1) << "Serving files from the current working directory"; - } + << "port=" << port << std::endl + << "version=" << chrome::kChromeVersion << std::endl; // Run until we receive command to shutdown. shutdown_event.Wait(); diff --git a/chrome/test/webdriver/session.cc b/chrome/test/webdriver/session.cc index 54e60ef..7249bfa 100644 --- a/chrome/test/webdriver/session.cc +++ b/chrome/test/webdriver/session.cc @@ -812,17 +812,19 @@ Error* Session::GetElementFirstClientRect(const FrameId& frame_id, JsonStringify(result.get())); } DictionaryValue* dict = static_cast<DictionaryValue*>(result.get()); - int left, top, width, height; - if (!dict->GetInteger("left", &left) || - !dict->GetInteger("top", &top) || - !dict->GetInteger("width", &width) || - !dict->GetInteger("height", &height)) { + // TODO(kkania): Convert the atom to return integers. + double left, top, width, height; + if (!dict->GetDouble("left", &left) || + !dict->GetDouble("top", &top) || + !dict->GetDouble("width", &width) || + !dict->GetDouble("height", &height)) { return new Error( kUnknownError, "GetFirstClientRect atom returned invalid dict: " + JsonStringify(dict)); } - *rect = gfx::Rect(left, top, width, height); + *rect = gfx::Rect(static_cast<int>(left), static_cast<int>(top), + static_cast<int>(width), static_cast<int>(height)); return NULL; } diff --git a/chrome/test/webdriver/webdriver_key_converter.cc b/chrome/test/webdriver/webdriver_key_converter.cc index 8d72191..33f9f390 100644 --- a/chrome/test/webdriver/webdriver_key_converter.cc +++ b/chrome/test/webdriver/webdriver_key_converter.cc @@ -13,6 +13,17 @@ namespace { +struct ModifierMaskAndKeyCode { + int mask; + ui::KeyboardCode key_code; +}; + +const ModifierMaskAndKeyCode kModifiers[] = { + { automation::kShiftKeyMask, ui::VKEY_SHIFT }, + { automation::kControlKeyMask, ui::VKEY_CONTROL }, + { automation::kAltKeyMask, ui::VKEY_MENU } +}; + // TODO(kkania): Use this in KeyMap. // Ordered list of all the key codes corresponding to special WebDriver keys. // These WebDriver keys are defined in the Unicode Private Use Area. @@ -267,12 +278,15 @@ bool ConvertKeysToWebKeyEvents(const string16& client_keys, } // Create the key events. - bool need_shift_key = - all_modifiers & automation::kShiftKeyMask && - !(sticky_modifiers & automation::kShiftKeyMask); - if (need_shift_key) { - key_events.push_back( - CreateKeyDownEvent(ui::VKEY_SHIFT, sticky_modifiers)); + bool necessary_modifiers[3]; + for (int i = 0; i < 3; ++i) { + necessary_modifiers[i] = + all_modifiers & kModifiers[i].mask && + !(sticky_modifiers & kModifiers[i].mask); + if (necessary_modifiers[i]) { + key_events.push_back( + CreateKeyDownEvent(kModifiers[i].key_code, sticky_modifiers)); + } } key_events.push_back(CreateKeyDownEvent(key_code, all_modifiers)); @@ -282,9 +296,11 @@ bool ConvertKeysToWebKeyEvents(const string16& client_keys, } key_events.push_back(CreateKeyUpEvent(key_code, all_modifiers)); - if (need_shift_key) { - key_events.push_back( - CreateKeyUpEvent(ui::VKEY_SHIFT, sticky_modifiers)); + for (int i = 2; i > -1; --i) { + if (necessary_modifiers[i]) { + key_events.push_back( + CreateKeyUpEvent(kModifiers[i].key_code, sticky_modifiers)); + } } } client_key_events->swap(key_events); diff --git a/chrome/test/webdriver/webdriver_key_converter_unittest.cc b/chrome/test/webdriver/webdriver_key_converter_unittest.cc index e7974f2..1fe3e5e 100644 --- a/chrome/test/webdriver/webdriver_key_converter_unittest.cc +++ b/chrome/test/webdriver/webdriver_key_converter_unittest.cc @@ -9,6 +9,7 @@ #include "base/utf_string_conversions.h" #include "chrome/test/automation/automation_json_requests.h" #include "chrome/test/webdriver/webdriver_key_converter.h" +#include "chrome/test/webdriver/webdriver_test_util.h" #include "testing/gtest/include/gtest/gtest.h" namespace webdriver { @@ -127,16 +128,19 @@ TEST(WebDriverKeyConverter, FrenchKeyOnEnglishLayout) { } #if defined(OS_WIN) -TEST(WebDriverKeyConverter, FrenchKeyOnFrenchLayout) { +TEST(WebDriverKeyConverter, NeedsCtrlAndAlt) { + RestoreKeyboardLayoutOnDestruct restore; + int ctrl_and_alt = automation::kControlKeyMask | automation::kAltKeyMask; WebKeyEvent event_array[] = { - CreateKeyDownEvent(ui::VKEY_2, 0), - CreateCharEvent(WideToUTF8(L"\u00E9"), WideToUTF8(L"\u00E9"), 0), - CreateKeyUpEvent(ui::VKEY_2, 0)}; - HKL french_layout = ::LoadKeyboardLayout(L"0000040C", 0); - ASSERT_TRUE(french_layout); - HKL prev_layout = ::ActivateKeyboardLayout(french_layout, 0); - CheckEvents(WideToUTF16(L"\u00E9"), event_array, arraysize(event_array)); - ::ActivateKeyboardLayout(prev_layout, 0); + CreateKeyDownEvent(ui::VKEY_CONTROL, 0), + CreateKeyDownEvent(ui::VKEY_MENU, 0), + CreateKeyDownEvent(ui::VKEY_Q, ctrl_and_alt), + CreateCharEvent("q", "@", ctrl_and_alt), + CreateKeyUpEvent(ui::VKEY_Q, ctrl_and_alt), + CreateKeyUpEvent(ui::VKEY_MENU, 0), + CreateKeyUpEvent(ui::VKEY_CONTROL, 0)}; + ASSERT_TRUE(SwitchKeyboardLayout("00000407")); + CheckEvents("@", event_array, arraysize(event_array)); } #endif diff --git a/chrome/test/webdriver/webdriver_test_util.cc b/chrome/test/webdriver/webdriver_test_util.cc new file mode 100644 index 0000000..ce464b1 --- /dev/null +++ b/chrome/test/webdriver/webdriver_test_util.cc @@ -0,0 +1,62 @@ +// Copyright (c) 2011 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/test/webdriver/webdriver_test_util.h" + +#include "base/logging.h" +#include "base/utf_string_conversions.h" + +namespace webdriver { + +RestoreKeyboardLayoutOnDestruct::RestoreKeyboardLayoutOnDestruct() { +#if defined(OS_WIN) + layout_ = GetKeyboardLayout(NULL); +#elif defined(OS_MACOSX) + layout_.reset(TISCopyCurrentKeyboardInputSource()); +#elif defined(OS_LINUX) + NOTIMPLEMENTED(); +#endif +} + +RestoreKeyboardLayoutOnDestruct::~RestoreKeyboardLayoutOnDestruct() { +#if defined(OS_WIN) + ActivateKeyboardLayout(layout_, 0); +#elif defined(OS_MACOSX) + TISSelectInputSource(layout_); +#elif defined(OS_LINUX) + NOTIMPLEMENTED(); +#endif +} + +#if defined(OS_WIN) +bool SwitchKeyboardLayout(const std::string& input_locale_identifier) { + HKL layout = LoadKeyboardLayout( + UTF8ToWide(input_locale_identifier).c_str(), 0); + if (!layout) + return false; + return !!ActivateKeyboardLayout(layout, 0); +} +#endif // defined(OS_WIN) + +#if defined(OS_MACOSX) +bool SwitchKeyboardLayout(const std::string& input_source_id) { + base::mac::ScopedCFTypeRef<CFMutableDictionaryRef> filter_dict( + CFDictionaryCreateMutable(kCFAllocatorDefault, + 1, + &kCFTypeDictionaryKeyCallBacks, + &kCFTypeDictionaryValueCallBacks)); + base::mac::ScopedCFTypeRef<CFStringRef> id_ref(CFStringCreateWithCString( + kCFAllocatorDefault, input_source_id.c_str(), kCFStringEncodingUTF8)); + CFDictionaryAddValue(filter_dict, kTISPropertyInputSourceID, id_ref); + base::mac::ScopedCFTypeRef<CFArrayRef> sources( + TISCreateInputSourceList(filter_dict, true)); + if (CFArrayGetCount(sources) != 1) + return false; + TISInputSourceRef source = (TISInputSourceRef)CFArrayGetValueAtIndex( + sources, 0); + return TISSelectInputSource(source) == noErr; +} +#endif // defined(OS_WIN) + +} // namespace webdriver diff --git a/chrome/test/webdriver/webdriver_test_util.h b/chrome/test/webdriver/webdriver_test_util.h new file mode 100644 index 0000000..0832d2d --- /dev/null +++ b/chrome/test/webdriver/webdriver_test_util.h @@ -0,0 +1,56 @@ +// Copyright (c) 2011 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_TEST_WEBDRIVER_WEBDRIVER_TEST_UTIL_H_ +#define CHROME_TEST_WEBDRIVER_WEBDRIVER_TEST_UTIL_H_ +#pragma once + +#include <string> + +#include "base/basictypes.h" + +#if defined(OS_WIN) +#include <windows.h> +#elif defined(OS_MACOSX) +#include <Carbon/Carbon.h> +#include "base/mac/scoped_cftyperef.h" +#endif + +namespace webdriver { + +// Restores the keyboard layout that was active at this object's creation +// when this object goes out of scope. +class RestoreKeyboardLayoutOnDestruct { + public: + RestoreKeyboardLayoutOnDestruct(); + ~RestoreKeyboardLayoutOnDestruct(); + + private: +#if defined(OS_WIN) + HKL layout_; +#elif defined(OS_MACOSX) + base::mac::ScopedCFTypeRef<TISInputSourceRef> layout_; +#endif + + DISALLOW_COPY_AND_ASSIGN(RestoreKeyboardLayoutOnDestruct); +}; + +#if defined(OS_WIN) +// Loads and activates the given keyboard layout. |input_locale_identifier| +// is composed of a device and language ID. Returns true on success. +// See http://msdn.microsoft.com/en-us/library/dd318693(v=vs.85).aspx +// Example: "00000409" is the default en-us keyboard layout. +bool SwitchKeyboardLayout(const std::string& input_locale_identifier); +#endif // defined(OS_WIN) + +#if defined(OS_MACOSX) +// Selects the input source for the given input source ID. Returns true on +// success. +// Example: "com.apple.keyboardlayout.US" is the default en-us keyboard layout. +bool SwitchKeyboardLayout(const std::string& input_source_id); +#endif // defined(OS_MACOSX) + +} // namespace webdriver + +#endif // CHROME_TEST_WEBDRIVER_WEBDRIVER_TEST_UTIL_H_ |