Index: content/public/test/render_view_test.cc |
diff --git a/content/public/test/render_view_test.cc b/content/public/test/render_view_test.cc |
index ca67587df8b334707b223f0019aed624b7ebd983..6ec66a1111a262780ecf70a15599c425caecb8a4 100644 |
--- a/content/public/test/render_view_test.cc |
+++ b/content/public/test/render_view_test.cc |
@@ -4,6 +4,8 @@ |
#include "content/public/test/render_view_test.h" |
+#include <cctype> |
+ |
#include "base/run_loop.h" |
#include "content/common/dom_storage/dom_storage_types.h" |
#include "content/common/frame_messages.h" |
@@ -23,10 +25,12 @@ |
#include "content/renderer/renderer_main_platform_delegate.h" |
#include "content/renderer/scheduler/renderer_scheduler.h" |
#include "content/test/fake_compositor_dependencies.h" |
+#include "content/test/mock_keyboard.h" |
#include "content/test/mock_render_process.h" |
#include "content/test/test_content_client.h" |
#include "third_party/WebKit/public/platform/WebScreenInfo.h" |
#include "third_party/WebKit/public/platform/WebURLRequest.h" |
+#include "third_party/WebKit/public/web/WebDocument.h" |
#include "third_party/WebKit/public/web/WebHistoryItem.h" |
#include "third_party/WebKit/public/web/WebInputEvent.h" |
#include "third_party/WebKit/public/web/WebKit.h" |
@@ -34,12 +38,26 @@ |
#include "third_party/WebKit/public/web/WebScriptSource.h" |
#include "third_party/WebKit/public/web/WebView.h" |
#include "ui/base/resource/resource_bundle.h" |
+#include "ui/events/event.h" |
+#include "ui/events/keycodes/keyboard_codes.h" |
#include "v8/include/v8.h" |
#if defined(OS_MACOSX) |
#include "base/mac/scoped_nsautorelease_pool.h" |
#endif |
+#if defined(USE_AURA) && defined(USE_X11) |
+#include <X11/Xlib.h> |
+#include "ui/events/event_constants.h" |
+#include "ui/events/keycodes/keyboard_code_conversion.h" |
+#include "ui/events/test/events_test_utils.h" |
+#include "ui/events/test/events_test_utils_x11.h" |
+#endif |
+ |
+#if defined(USE_OZONE) |
+#include "ui/events/keycodes/keyboard_code_conversion.h" |
+#endif |
+ |
using blink::WebGestureEvent; |
using blink::WebInputEvent; |
using blink::WebLocalFrame; |
@@ -49,6 +67,7 @@ using blink::WebString; |
using blink::WebURLRequest; |
namespace { |
+ |
const int32 kOpenerId = -2; |
const int32 kRouteId = 5; |
const int32 kMainFrameRouteId = 6; |
@@ -56,6 +75,30 @@ const int32 kNewWindowRouteId = 7; |
const int32 kNewFrameRouteId = 10; |
const int32 kSurfaceId = 42; |
+#if (defined(USE_AURA) && defined(USE_X11)) || defined(USE_OZONE) |
+// Converts MockKeyboard::Modifiers to ui::EventFlags. |
+int ConvertMockKeyboardModifier(content::MockKeyboard::Modifiers modifiers) { |
+ static struct ModifierMap { |
+ content::MockKeyboard::Modifiers src; |
+ int dst; |
+ } kModifierMap[] = { |
+ { content::MockKeyboard::LEFT_SHIFT, ui::EF_SHIFT_DOWN }, |
+ { content::MockKeyboard::RIGHT_SHIFT, ui::EF_SHIFT_DOWN }, |
+ { content::MockKeyboard::LEFT_CONTROL, ui::EF_CONTROL_DOWN }, |
+ { content::MockKeyboard::RIGHT_CONTROL, ui::EF_CONTROL_DOWN }, |
+ { content::MockKeyboard::LEFT_ALT, ui::EF_ALT_DOWN }, |
+ { content::MockKeyboard::RIGHT_ALT, ui::EF_ALT_DOWN }, |
+ }; |
+ int flags = 0; |
+ for (size_t i = 0; i < arraysize(kModifierMap); ++i) { |
+ if (kModifierMap[i].src & modifiers) { |
+ flags |= kModifierMap[i].dst; |
+ } |
+ } |
+ return flags; |
+} |
+#endif |
+ |
} // namespace |
namespace content { |
@@ -394,6 +437,159 @@ void RenderViewTest::Resize(gfx::Size new_size, |
OnMessageReceived(*resize_message); |
} |
+int RenderViewTest::SendKeyEvent(const MockKeyboard& keyboard, |
+ int key_code, |
+ base::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(output); |
+ int length = keyboard.GetCharacters(key_code, 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}; |
+ ui::KeyEvent evt1(msg1); |
+ NativeWebKeyboardEvent keydown_event(evt1); |
+ SendNativeKeyEvent(keydown_event); |
+ |
+ MSG msg2 = {NULL, WM_CHAR, (*output)[0], 0}; |
+ ui::KeyEvent evt2(msg2); |
+ NativeWebKeyboardEvent char_event(evt2); |
+ SendNativeKeyEvent(char_event); |
+ |
+ MSG msg3 = {NULL, WM_KEYUP, key_code, 0}; |
+ ui::KeyEvent evt3(msg3); |
+ NativeWebKeyboardEvent keyup_event(evt3); |
+ 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(keyboard.modifiers()); |
+ |
+ ui::ScopedXI2Event xevent; |
+ xevent.InitKeyEvent(ui::ET_KEY_PRESSED, |
+ static_cast<ui::KeyboardCode>(key_code), flags); |
+ ui::KeyEvent event1(xevent); |
+ NativeWebKeyboardEvent keydown_event(event1); |
+ SendNativeKeyEvent(keydown_event); |
+ |
+ // X11 doesn't actually have native character events, but give the test |
+ // what it wants. |
+ xevent.InitKeyEvent(ui::ET_KEY_PRESSED, |
+ static_cast<ui::KeyboardCode>(key_code), flags); |
+ ui::KeyEvent event2(xevent); |
+ event2.set_character( |
+ GetCharacterFromKeyCode(event2.key_code(), event2.flags())); |
+ ui::KeyEventTestApi test_event2(&event2); |
+ test_event2.set_is_char(true); |
+ NativeWebKeyboardEvent char_event(event2); |
+ SendNativeKeyEvent(char_event); |
+ |
+ xevent.InitKeyEvent(ui::ET_KEY_RELEASED, |
+ static_cast<ui::KeyboardCode>(key_code), flags); |
+ ui::KeyEvent event3(xevent); |
+ NativeWebKeyboardEvent keyup_event(event3); |
+ SendNativeKeyEvent(keyup_event); |
+ |
+ long c = |
+ GetCharacterFromKeyCode(static_cast<ui::KeyboardCode>(key_code), flags); |
+ output->assign(1, static_cast<base::char16>(c)); |
+ return 1; |
+#elif defined(USE_OZONE) |
+ const int flags = ConvertMockKeyboardModifier(keyboard.modifiers()); |
+ |
+ ui::KeyEvent keydown_event(ui::ET_KEY_PRESSED, |
+ static_cast<ui::KeyboardCode>(key_code), flags); |
+ NativeWebKeyboardEvent keydown_web_event(keydown_event); |
+ SendNativeKeyEvent(keydown_web_event); |
+ |
+ ui::KeyEvent char_event(keydown_event.GetCharacter(), |
+ static_cast<ui::KeyboardCode>(key_code), flags); |
+ NativeWebKeyboardEvent char_web_event(char_event); |
+ SendNativeKeyEvent(char_web_event); |
+ |
+ ui::KeyEvent keyup_event(ui::ET_KEY_RELEASED, |
+ static_cast<ui::KeyboardCode>(key_code), flags); |
+ NativeWebKeyboardEvent keyup_web_event(keyup_event); |
+ SendNativeKeyEvent(keyup_web_event); |
+ |
+ long c = |
+ GetCharacterFromKeyCode(static_cast<ui::KeyboardCode>(key_code), flags); |
+ output->assign(1, static_cast<base::char16>(c)); |
+ return 1; |
+#else |
+ NOTIMPLEMENTED(); |
+ return L'\0'; |
+#endif |
+} |
+ |
+void RenderViewTest::SimulateUserTypingASCIICharacter(char ascii_character) { |
+ int key_code = ascii_character; |
+ bool is_shift_pressed = false; |
+ |
+ if (isalnum(ascii_character)) { |
+ key_code = base::ToUpperASCII(ascii_character); |
+ is_shift_pressed = isupper(ascii_character); |
+ } else if (ascii_character == '@') { |
+ key_code = '2'; |
+ is_shift_pressed = true; |
+ } else if (ascii_character == '.') { |
+ key_code = ui::VKEY_OEM_PERIOD; |
+ } else if (ascii_character == '_') { |
+ key_code = ui::VKEY_OEM_MINUS; |
+ is_shift_pressed = true; |
+ } else { |
+ NOTREACHED(); |
+ } |
+ |
+ SimulateUserTypingKeyCodeWithShift(key_code, is_shift_pressed); |
+} |
+ |
+void RenderViewTest::SimulateUserTypingKeyCodeWithShift(int key_code, |
+ bool is_shift_pressed) { |
+ base::string16 unused_char_code; |
+ content::MockKeyboard keyboard; |
+ EXPECT_TRUE(keyboard.Update( |
+ content::MockKeyboard::LAYOUT_UNITED_STATES, |
+ is_shift_pressed ? content::MockKeyboard::LEFT_SHIFT |
+ : content::MockKeyboard::NONE)); |
+ SendKeyEvent(keyboard, key_code, &unused_char_code); |
+} |
+ |
+void RenderViewTest::SimulateUserInputChangeForElement( |
+ blink::WebInputElement* input, |
+ blink::WebFrame* input_frame, |
+ const std::string& new_value) { |
+ while (!input->focused()) |
+ input_frame->document().frame()->view()->advanceFocus(false); |
+ |
+ size_t previous_length = input->value().length(); |
+ for (size_t i = 0; i < previous_length; ++i) |
+ SimulateUserTypingKeyCodeWithShift(ui::VKEY_BACK, false); |
+ |
+ EXPECT_TRUE(input->value().utf8().empty()); |
+ ASSERT_TRUE(base::IsStringASCII(new_value)); |
+ for (size_t i = 0; i < new_value.size(); ++i) |
+ SimulateUserTypingASCIICharacter(new_value[i]); |
+ |
+ // Compare only beginning, because autocomplete may have filled out the |
+ // form. |
+ EXPECT_EQ(new_value, input->value().utf8().substr(0, new_value.length())); |
+} |
+ |
bool RenderViewTest::OnMessageReceived(const IPC::Message& msg) { |
RenderViewImpl* impl = static_cast<RenderViewImpl*>(view_); |
return impl->OnMessageReceived(msg); |
@@ -421,7 +617,6 @@ blink::WebWidget* RenderViewTest::GetWebWidget() { |
return impl->webwidget(); |
} |
- |
ContentClient* RenderViewTest::CreateContentClient() { |
return new TestContentClient; |
} |