Index: content/renderer/render_view_browsertest.cc |
=================================================================== |
--- content/renderer/render_view_browsertest.cc (revision 140247) |
+++ content/renderer/render_view_browsertest.cc (working copy) |
@@ -11,8 +11,9 @@ |
#include "content/common/view_messages.h" |
#include "content/public/browser/native_web_keyboard_event.h" |
#include "content/public/common/bindings_policy.h" |
+#include "content/public/test/render_view_test.h" |
#include "content/renderer/render_view_impl.h" |
-#include "content/test/render_view_test.h" |
+#include "content/test/mock_keyboard.h" |
#include "net/base/net_errors.h" |
#include "testing/gtest/include/gtest/gtest.h" |
#include "third_party/WebKit/Source/WebKit/chromium/public/platform/WebString.h" |
@@ -25,18 +26,195 @@ |
#include "ui/gfx/codec/jpeg_codec.h" |
#include "webkit/glue/web_io_operators.h" |
+#if defined(OS_LINUX) && !defined(USE_AURA) |
+#include "ui/base/gtk/event_synthesis_gtk.h" |
+#endif |
+ |
+#if defined(USE_AURA) |
+#include "ui/aura/event.h" |
+#endif |
+ |
+#if defined(USE_AURA) && defined(USE_X11) |
+#include <X11/Xlib.h> |
+#include "ui/base/events.h" |
+#include "ui/base/keycodes/keyboard_code_conversion.h" |
+#include "ui/base/x/x11_util.h" |
+#endif |
+ |
using WebKit::WebFrame; |
using WebKit::WebInputEvent; |
using WebKit::WebMouseEvent; |
using WebKit::WebString; |
using WebKit::WebTextDirection; |
using WebKit::WebURLError; |
+using content::NativeWebKeyboardEvent; |
+namespace { |
+#if defined(USE_AURA) && defined(USE_X11) |
+// Converts MockKeyboard::Modifiers to ui::EventFlags. |
+int ConvertMockKeyboardModifier(MockKeyboard::Modifiers modifiers) { |
+ static struct ModifierMap { |
+ MockKeyboard::Modifiers src; |
+ int dst; |
+ } kModifierMap[] = { |
+ { MockKeyboard::LEFT_SHIFT, ui::EF_SHIFT_DOWN }, |
+ { MockKeyboard::RIGHT_SHIFT, ui::EF_SHIFT_DOWN }, |
+ { MockKeyboard::LEFT_CONTROL, ui::EF_CONTROL_DOWN }, |
+ { MockKeyboard::RIGHT_CONTROL, ui::EF_CONTROL_DOWN }, |
+ { MockKeyboard::LEFT_ALT, ui::EF_ALT_DOWN }, |
+ { MockKeyboard::RIGHT_ALT, ui::EF_ALT_DOWN }, |
+ }; |
+ int flags = 0; |
+ for (size_t i = 0; i < ARRAYSIZE_UNSAFE(kModifierMap); ++i) { |
+ if (kModifierMap[i].src & modifiers) { |
+ flags |= kModifierMap[i].dst; |
+ } |
+ } |
+ return flags; |
+} |
+#endif |
+} |
+ |
class RenderViewImplTest : public content::RenderViewTest { |
public: |
+ RenderViewImplTest() { |
+ // Attach a pseudo keyboard device to this object. |
+ mock_keyboard_.reset(new MockKeyboard()); |
+ } |
+ |
RenderViewImpl* view() { |
return static_cast<RenderViewImpl*>(view_); |
} |
+ |
+ // Sends IPC messages that emulates a key-press event. |
+ int SendKeyEvent(MockKeyboard::Layout layout, |
+ int key_code, |
+ MockKeyboard::Modifiers modifiers, |
+ string16* output) { |
+#if defined(OS_WIN) |
+ // Retrieve the Unicode character for the given tuple (keyboard-layout, |
+ // key-code, and modifiers). |
+ // Exit when a keyboard-layout driver cannot assign a Unicode character to |
+ // the tuple to prevent sending an invalid key code to the RenderView object. |
+ CHECK(mock_keyboard_.get()); |
+ CHECK(output); |
+ int length = mock_keyboard_->GetCharacters(layout, key_code, modifiers, |
+ output); |
+ if (length != 1) |
+ return -1; |
+ |
+ // Create IPC messages from Windows messages and send them to our |
+ // back-end. |
+ // A keyboard event of Windows consists of three Windows messages: |
+ // WM_KEYDOWN, WM_CHAR, and WM_KEYUP. |
+ // WM_KEYDOWN and WM_KEYUP sends virtual-key codes. On the other hand, |
+ // WM_CHAR sends a composed Unicode character. |
+ MSG msg1 = { NULL, WM_KEYDOWN, key_code, 0 }; |
+#if defined(USE_AURA) |
+ aura::KeyEvent evt1(msg1, false); |
+ NativeWebKeyboardEvent keydown_event(&evt1); |
+#else |
+ NativeWebKeyboardEvent keydown_event(msg1); |
+#endif |
+ SendNativeKeyEvent(keydown_event); |
+ |
+ MSG msg2 = { NULL, WM_CHAR, (*output)[0], 0 }; |
+#if defined(USE_AURA) |
+ aura::KeyEvent evt2(msg2, true); |
+ NativeWebKeyboardEvent char_event(&evt2); |
+#else |
+ NativeWebKeyboardEvent char_event(msg2); |
+#endif |
+ SendNativeKeyEvent(char_event); |
+ |
+ MSG msg3 = { NULL, WM_KEYUP, key_code, 0 }; |
+#if defined(USE_AURA) |
+ aura::KeyEvent evt3(msg3, false); |
+ NativeWebKeyboardEvent keyup_event(&evt3); |
+#else |
+ NativeWebKeyboardEvent keyup_event(msg3); |
+#endif |
+ SendNativeKeyEvent(keyup_event); |
+ |
+ return length; |
+#elif defined(USE_AURA) && defined(USE_X11) |
+ // We ignore |layout|, which means we are only testing the layout of the |
+ // current locale. TODO(mazda): fix this to respect |layout|. |
+ CHECK(output); |
+ const int flags = ConvertMockKeyboardModifier(modifiers); |
+ |
+ XEvent xevent1; |
+ InitXKeyEventForTesting(ui::ET_KEY_PRESSED, |
+ static_cast<ui::KeyboardCode>(key_code), |
+ flags, |
+ &xevent1); |
+ aura::KeyEvent event1(&xevent1, false); |
+ NativeWebKeyboardEvent keydown_event(&event1); |
+ SendNativeKeyEvent(keydown_event); |
+ |
+ XEvent xevent2; |
+ InitXKeyEventForTesting(ui::ET_KEY_PRESSED, |
+ static_cast<ui::KeyboardCode>(key_code), |
+ flags, |
+ &xevent2); |
+ aura::KeyEvent event2(&xevent2, true); |
+ NativeWebKeyboardEvent char_event(&event2); |
+ SendNativeKeyEvent(char_event); |
+ |
+ XEvent xevent3; |
+ InitXKeyEventForTesting(ui::ET_KEY_RELEASED, |
+ static_cast<ui::KeyboardCode>(key_code), |
+ flags, |
+ &xevent3); |
+ aura::KeyEvent event3(&xevent3, false); |
+ NativeWebKeyboardEvent keyup_event(&event3); |
+ SendNativeKeyEvent(keyup_event); |
+ |
+ long c = GetCharacterFromKeyCode(static_cast<ui::KeyboardCode>(key_code), |
+ flags); |
+ output->assign(1, static_cast<char16>(c)); |
+ return 1; |
+#elif defined(OS_LINUX) |
+ // We ignore |layout|, which means we are only testing the layout of the |
+ // current locale. TODO(estade): fix this to respect |layout|. |
+ std::vector<GdkEvent*> events; |
+ ui::SynthesizeKeyPressEvents( |
+ NULL, static_cast<ui::KeyboardCode>(key_code), |
+ modifiers & (MockKeyboard::LEFT_CONTROL | MockKeyboard::RIGHT_CONTROL), |
+ modifiers & (MockKeyboard::LEFT_SHIFT | MockKeyboard::RIGHT_SHIFT), |
+ modifiers & (MockKeyboard::LEFT_ALT | MockKeyboard::RIGHT_ALT), |
+ &events); |
+ |
+ guint32 unicode_key = 0; |
+ for (size_t i = 0; i < events.size(); ++i) { |
+ // Only send the up/down events for key press itself (skip the up/down |
+ // events for the modifier keys). |
+ if ((i + 1) == (events.size() / 2) || i == (events.size() / 2)) { |
+ unicode_key = gdk_keyval_to_unicode(events[i]->key.keyval); |
+ NativeWebKeyboardEvent webkit_event(events[i]); |
+ SendNativeKeyEvent(webkit_event); |
+ |
+ // Need to add a char event after the key down. |
+ if (webkit_event.type == WebKit::WebInputEvent::RawKeyDown) { |
+ NativeWebKeyboardEvent char_event = webkit_event; |
+ char_event.type = WebKit::WebInputEvent::Char; |
+ char_event.skip_in_browser = true; |
+ SendNativeKeyEvent(char_event); |
+ } |
+ } |
+ gdk_event_free(events[i]); |
+ } |
+ |
+ output->assign(1, static_cast<char16>(unicode_key)); |
+ return 1; |
+#else |
+ NOTIMPLEMENTED(); |
+ return L'\0'; |
+#endif |
+ } |
+ |
+ private: |
+ scoped_ptr<MockKeyboard> mock_keyboard_; |
}; |
// Test that we get form state change notifications when input fields change. |