Skip to content

Commit

Permalink
Send KEYUP and KEYDOWN rather than CHAR messages to the renderer window.
Browse files Browse the repository at this point in the history
When use_aura=1, WM_CHAR alone isn't sufficient. KEYDOWN and KEYUP
messages are needed for proper IME handling.

BUG=240843
TEST=chrome_frame_tests.exe --gtest_filter=*KeyboardInput*

Review URL: https://chromiumcodereview.appspot.com/14593006

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@200390 0039d316-1c4b-4281-b951-d872f2087c98
  • Loading branch information
grt@chromium.org committed May 15, 2013
1 parent b4be73d commit 6245b3e
Show file tree
Hide file tree
Showing 7 changed files with 54 additions and 25 deletions.
2 changes: 1 addition & 1 deletion chrome_frame/test/data/window_open.html
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@

function OnKeyPress() {
var char_code = String.fromCharCode(event.keyCode);
if (char_code == 'C') {
if (char_code == 'c') {
new_window.close();
}
}
Expand Down
2 changes: 1 addition & 1 deletion chrome_frame/test/delete_chrome_history_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -210,7 +210,7 @@ TEST_F(DeleteBrowsingHistoryTest, DISABLED_CFDeleteBrowsingHistory) {
EXPECT_CALL(load_helper, OnLoadComplete())
.WillOnce(testing::DoAll(
AccLeftClickInRenderer(&ie_mock_, AccObjectMatcher(L"username")),
PostCharMessagesToRenderer(&ie_mock_, WideToASCII(kFormFieldValue)),
PostKeyMessagesToRenderer(&ie_mock_, WideToASCII(kFormFieldValue)),
AccLeftClickInRenderer(&ie_mock_, AccObjectMatcher(L"Submit"))));

EXPECT_CALL(server_mock_, Post(_, testing::StrEq(L"/form"), _))
Expand Down
36 changes: 33 additions & 3 deletions chrome_frame/test/ie_event_sink.cc
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@
#include "base/string_number_conversions.h"
#include "base/string_util.h"
#include "base/stringprintf.h"
#include "base/strings/string_piece.h"
#include "base/time.h"
#include "base/utf_string_conversions.h"
#include "base/win/scoped_bstr.h"
#include "base/win/scoped_handle.h"
Expand Down Expand Up @@ -313,9 +315,37 @@ void IEEventSink::SetFocusToRenderer() {
simulate_input::SetKeyboardFocusToWindow(GetRendererWindow());
}

void IEEventSink::SendKeys(const wchar_t* input_string) {
SetFocusToRenderer();
simulate_input::SendStringW(input_string);
void IEEventSink::SendKeys(const char* input_string) {
HWND window = GetRendererWindow();
const base::TimeDelta kMessageSleep = base::TimeDelta::FromMilliseconds(50);
const base::StringPiece codes(input_string);
for (size_t i = 0; i < codes.length(); ++i) {
char character = codes[i];
UINT virtual_key = 0;

if (character >= 'a' && character <= 'z') {
// VK_A - VK_Z are ASCII 'A' - 'Z'.
virtual_key = 'A' + (character - 'a');
} else if (character >= '0' && character <= '9') {
// VK_0 - VK_9 are ASCII '0' - '9'.
virtual_key = character;
} else {
FAIL() << "Character value out of range at position " << i
<< " of string \"" << input_string << "\"";
}

UINT scan_code = MapVirtualKey(virtual_key, MAPVK_VK_TO_VSC);
EXPECT_NE(0U, scan_code) << "No translation for virtual key "
<< virtual_key << " for character at position "
<< i << " of string \"" << input_string << "\"";

::PostMessage(window, WM_KEYDOWN,
virtual_key, MAKELPARAM(1, scan_code));
base::PlatformThread::Sleep(kMessageSleep);
::PostMessage(window, WM_KEYUP,
virtual_key, MAKELPARAM(1, scan_code | KF_UP | KF_REPEAT));
base::PlatformThread::Sleep(kMessageSleep);
}
}

void IEEventSink::SendMouseClick(int x, int y,
Expand Down
6 changes: 3 additions & 3 deletions chrome_frame/test/ie_event_sink.h
Original file line number Diff line number Diff line change
Expand Up @@ -103,9 +103,9 @@ class IEEventSink
// Set input focus to chrome frame window.
void SetFocusToRenderer();

// Send keyboard input to the renderer window hosted in chrome using
// SendInput API.
void SendKeys(const wchar_t* input_string);
// Send keyboard input to the renderer window hosted in chrome using direct
// key down/up messages.
void SendKeys(const char* input_string);

// Send mouse click to the renderer window hosted in chrome using
// SendInput API.
Expand Down
27 changes: 13 additions & 14 deletions chrome_frame/test/mock_ie_event_sink_actions.h
Original file line number Diff line number Diff line change
Expand Up @@ -257,20 +257,19 @@ ACTION(OpenContextMenuAsync) {
::PostMessage(hwnd, WM_RBUTTONUP, 0, coordinates);
}

ACTION_P(PostCharMessage, character_code) {
::PostMessage(arg0, WM_CHAR, character_code, 0);
}

ACTION_P2(PostCharMessageToRenderer, mock, character_code) {
AccInWindow<void>(PostCharMessage(character_code),
mock->event_sink()->GetRendererWindow());
}

ACTION_P2(PostCharMessagesToRenderer, mock, character_codes) {
HWND window = mock->event_sink()->GetRendererWindow();
std::string codes = character_codes;
for (size_t i = 0; i < codes.length(); i++)
::PostMessage(window, WM_CHAR, codes[i], 0);
// Posts a WM_KEYDOWN and WM_KEYUP message to the renderer window. Modifiers are
// not supported, so |character_code| is limited to the regular expression
// [0-9a-z].
ACTION_P2(PostKeyMessageToRenderer, mock, character_code) {
char character_codes[] = { character_code, '\0' };
mock->event_sink()->SendKeys(character_codes);
}

// Posts WM_KEYDOWN and WM_KEYUP messages to the renderer window. Modifiers are
// not supported, so |character_codes| is limited to the regular expression
// [0-9a-z]*.
ACTION_P2(PostKeyMessagesToRenderer, mock, character_codes) {
mock->event_sink()->SendKeys(std::string(character_codes).c_str());
}

ACTION_P3(WatchWindow, mock, caption, window_class) {
Expand Down
2 changes: 1 addition & 1 deletion chrome_frame/test/navigation_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -401,7 +401,7 @@ TEST_P(FullTabNavigationTest, JavascriptWindowOpenCanClose) {
ie_mock_.ExpectNewWindow(&new_window_mock);
EXPECT_CALL(new_window_mock, OnLoad(_, StrEq(GetSimplePageUrl())))
.Times(testing::AtMost(2))
.WillOnce(PostCharMessageToRenderer(&ie_mock_, 'C')) // close the popup
.WillOnce(PostKeyMessageToRenderer(&ie_mock_, 'c')) // close the popup
.WillOnce(testing::Return());

EXPECT_CALL(new_window_mock, OnQuit())
Expand Down
4 changes: 2 additions & 2 deletions chrome_frame/test/ui_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -77,9 +77,9 @@ TEST_P(FullTabUITest, KeyboardInput) {
}
std::wstring key_event_url = GetTestUrl(L"keyevent.html");

const char* input = "Chrome";
static const char input[] = "chrome";
EXPECT_CALL(ie_mock_, OnLoad(GetParam().invokes_cf(), StrEq(key_event_url)))
.WillOnce(PostCharMessagesToRenderer(&ie_mock_, input));
.WillOnce(PostKeyMessagesToRenderer(&ie_mock_, input));

EXPECT_CALL(ie_mock_, OnMessage(StrCaseEq(UTF8ToWide(input)), _, _))
.WillOnce(CloseBrowserMock(&ie_mock_));
Expand Down

0 comments on commit 6245b3e

Please sign in to comment.