| 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.
|
|
|