| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "content/test/render_view_test.h" | 5 #include "content/public/test/render_view_test.h" |
| 6 | 6 |
| 7 #include "content/common/view_messages.h" | 7 #include "content/common/view_messages.h" |
| 8 #include "content/public/browser/native_web_keyboard_event.h" | 8 #include "content/public/browser/native_web_keyboard_event.h" |
| 9 #include "content/public/common/renderer_preferences.h" | 9 #include "content/public/common/renderer_preferences.h" |
| 10 #include "content/renderer/render_thread_impl.h" | 10 #include "content/renderer/render_thread_impl.h" |
| 11 #include "content/renderer/render_view_impl.h" | 11 #include "content/renderer/render_view_impl.h" |
| 12 #include "content/renderer/renderer_main_platform_delegate.h" | 12 #include "content/renderer/renderer_main_platform_delegate.h" |
| 13 #include "content/renderer/renderer_webkitplatformsupport_impl.h" |
| 13 #include "content/test/mock_render_process.h" | 14 #include "content/test/mock_render_process.h" |
| 14 #include "third_party/WebKit/Source/WebKit/chromium/public/WebFrame.h" | 15 #include "third_party/WebKit/Source/WebKit/chromium/public/WebFrame.h" |
| 15 #include "third_party/WebKit/Source/WebKit/chromium/public/WebHistoryItem.h" | 16 #include "third_party/WebKit/Source/WebKit/chromium/public/WebHistoryItem.h" |
| 16 #include "third_party/WebKit/Source/WebKit/chromium/public/WebInputEvent.h" | 17 #include "third_party/WebKit/Source/WebKit/chromium/public/WebInputEvent.h" |
| 17 #include "third_party/WebKit/Source/WebKit/chromium/public/WebKit.h" | 18 #include "third_party/WebKit/Source/WebKit/chromium/public/WebKit.h" |
| 18 #include "third_party/WebKit/Source/WebKit/chromium/public/WebScriptController.h
" | 19 #include "third_party/WebKit/Source/WebKit/chromium/public/WebScriptController.h
" |
| 19 #include "third_party/WebKit/Source/WebKit/chromium/public/WebScriptSource.h" | 20 #include "third_party/WebKit/Source/WebKit/chromium/public/WebScriptSource.h" |
| 20 #include "third_party/WebKit/Source/WebKit/chromium/public/platform/WebURLReques
t.h" | 21 #include "third_party/WebKit/Source/WebKit/chromium/public/platform/WebURLReques
t.h" |
| 21 #include "third_party/WebKit/Source/WebKit/chromium/public/WebView.h" | 22 #include "third_party/WebKit/Source/WebKit/chromium/public/WebView.h" |
| 22 #include "webkit/dom_storage/dom_storage_types.h" | 23 #include "webkit/dom_storage/dom_storage_types.h" |
| 23 #include "webkit/glue/glue_serialize.h" | 24 #include "webkit/glue/glue_serialize.h" |
| 24 #include "webkit/glue/webkit_glue.h" | 25 #include "webkit/glue/webkit_glue.h" |
| 25 | 26 |
| 26 #if defined(OS_LINUX) && !defined(USE_AURA) | |
| 27 #include "ui/base/gtk/event_synthesis_gtk.h" | |
| 28 #endif | |
| 29 | |
| 30 #if defined(USE_AURA) | |
| 31 #include "ui/aura/event.h" | |
| 32 #endif | |
| 33 | |
| 34 #if defined(USE_AURA) && defined(USE_X11) | |
| 35 #include <X11/Xlib.h> | |
| 36 #include "ui/base/events.h" | |
| 37 #include "ui/base/keycodes/keyboard_code_conversion.h" | |
| 38 #include "ui/base/x/x11_util.h" | |
| 39 #endif | |
| 40 | |
| 41 using WebKit::WebFrame; | 27 using WebKit::WebFrame; |
| 42 using WebKit::WebInputEvent; | 28 using WebKit::WebInputEvent; |
| 43 using WebKit::WebMouseEvent; | 29 using WebKit::WebMouseEvent; |
| 44 using WebKit::WebScriptController; | 30 using WebKit::WebScriptController; |
| 45 using WebKit::WebScriptSource; | 31 using WebKit::WebScriptSource; |
| 46 using WebKit::WebString; | 32 using WebKit::WebString; |
| 47 using WebKit::WebURLRequest; | 33 using WebKit::WebURLRequest; |
| 48 using content::NativeWebKeyboardEvent; | 34 using content::NativeWebKeyboardEvent; |
| 49 | 35 |
| 50 namespace { | 36 namespace { |
| 51 const int32 kOpenerId = -2; | 37 const int32 kOpenerId = -2; |
| 52 const int32 kRouteId = 5; | 38 const int32 kRouteId = 5; |
| 53 const int32 kNewWindowRouteId = 6; | 39 const int32 kNewWindowRouteId = 6; |
| 54 const int32 kSurfaceId = 42; | 40 const int32 kSurfaceId = 42; |
| 55 | 41 |
| 56 #if defined(USE_AURA) && defined(USE_X11) | |
| 57 // Converts MockKeyboard::Modifiers to ui::EventFlags. | |
| 58 int ConvertMockKeyboardModifier(MockKeyboard::Modifiers modifiers) { | |
| 59 static struct ModifierMap { | |
| 60 MockKeyboard::Modifiers src; | |
| 61 int dst; | |
| 62 } kModifierMap[] = { | |
| 63 { MockKeyboard::LEFT_SHIFT, ui::EF_SHIFT_DOWN }, | |
| 64 { MockKeyboard::RIGHT_SHIFT, ui::EF_SHIFT_DOWN }, | |
| 65 { MockKeyboard::LEFT_CONTROL, ui::EF_CONTROL_DOWN }, | |
| 66 { MockKeyboard::RIGHT_CONTROL, ui::EF_CONTROL_DOWN }, | |
| 67 { MockKeyboard::LEFT_ALT, ui::EF_ALT_DOWN }, | |
| 68 { MockKeyboard::RIGHT_ALT, ui::EF_ALT_DOWN }, | |
| 69 }; | |
| 70 int flags = 0; | |
| 71 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(kModifierMap); ++i) { | |
| 72 if (kModifierMap[i].src & modifiers) { | |
| 73 flags |= kModifierMap[i].dst; | |
| 74 } | |
| 75 } | |
| 76 return flags; | |
| 77 } | |
| 78 #endif | |
| 79 } // namespace | 42 } // namespace |
| 80 | 43 |
| 81 namespace content { | 44 namespace content { |
| 82 | 45 |
| 46 class RendererWebKitPlatformSupportImplNoSandboxImpl : |
| 47 public RendererWebKitPlatformSupportImpl { |
| 48 public: |
| 49 virtual WebKit::WebSandboxSupport* sandboxSupport() { |
| 50 return NULL; |
| 51 } |
| 52 }; |
| 53 |
| 54 RenderViewTest::RendererWebKitPlatformSupportImplNoSandbox:: |
| 55 RendererWebKitPlatformSupportImplNoSandbox() { |
| 56 webkit_platform_support_.reset( |
| 57 new RendererWebKitPlatformSupportImplNoSandboxImpl()); |
| 58 } |
| 59 |
| 60 RenderViewTest::RendererWebKitPlatformSupportImplNoSandbox:: |
| 61 ~RendererWebKitPlatformSupportImplNoSandbox() { |
| 62 } |
| 63 |
| 64 WebKit::WebKitPlatformSupport* |
| 65 RenderViewTest::RendererWebKitPlatformSupportImplNoSandbox::Get() { |
| 66 return webkit_platform_support_.get(); |
| 67 } |
| 68 |
| 83 RenderViewTest::RenderViewTest() | 69 RenderViewTest::RenderViewTest() |
| 84 : view_(NULL) { | 70 : view_(NULL) { |
| 85 } | 71 } |
| 86 | 72 |
| 87 RenderViewTest::~RenderViewTest() { | 73 RenderViewTest::~RenderViewTest() { |
| 88 } | 74 } |
| 89 | 75 |
| 90 void RenderViewTest::ProcessPendingMessages() { | 76 void RenderViewTest::ProcessPendingMessages() { |
| 91 msg_loop_.PostTask(FROM_HERE, MessageLoop::QuitClosure()); | 77 msg_loop_.PostTask(FROM_HERE, MessageLoop::QuitClosure()); |
| 92 msg_loop_.Run(); | 78 msg_loop_.Run(); |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 131 } | 117 } |
| 132 | 118 |
| 133 void RenderViewTest::GoForward(const WebKit::WebHistoryItem& item) { | 119 void RenderViewTest::GoForward(const WebKit::WebHistoryItem& item) { |
| 134 GoToOffset(1, item); | 120 GoToOffset(1, item); |
| 135 } | 121 } |
| 136 | 122 |
| 137 void RenderViewTest::SetUp() { | 123 void RenderViewTest::SetUp() { |
| 138 // Subclasses can set the ContentClient's renderer before calling | 124 // Subclasses can set the ContentClient's renderer before calling |
| 139 // RenderViewTest::SetUp(). | 125 // RenderViewTest::SetUp(). |
| 140 if (!GetContentClient()->renderer()) | 126 if (!GetContentClient()->renderer()) |
| 141 GetContentClient()->set_renderer(&mock_content_renderer_client_); | 127 GetContentClient()->set_renderer(&content_renderer_client_); |
| 142 | 128 |
| 143 // Subclasses can set render_thread_ with their own implementation before | 129 // Subclasses can set render_thread_ with their own implementation before |
| 144 // calling RenderViewTest::SetUp(). | 130 // calling RenderViewTest::SetUp(). |
| 145 if (!render_thread_.get()) | 131 if (!render_thread_.get()) |
| 146 render_thread_.reset(new MockRenderThread()); | 132 render_thread_.reset(new MockRenderThread()); |
| 147 render_thread_->set_routing_id(kRouteId); | 133 render_thread_->set_routing_id(kRouteId); |
| 148 render_thread_->set_surface_id(kSurfaceId); | 134 render_thread_->set_surface_id(kSurfaceId); |
| 149 render_thread_->set_new_window_routing_id(kNewWindowRouteId); | 135 render_thread_->set_new_window_routing_id(kNewWindowRouteId); |
| 150 | 136 |
| 151 command_line_.reset(new CommandLine(CommandLine::NO_PROGRAM)); | 137 command_line_.reset(new CommandLine(CommandLine::NO_PROGRAM)); |
| 152 params_.reset(new content::MainFunctionParams(*command_line_)); | 138 params_.reset(new content::MainFunctionParams(*command_line_)); |
| 153 platform_.reset(new RendererMainPlatformDelegate(*params_)); | 139 platform_.reset(new RendererMainPlatformDelegate(*params_)); |
| 154 platform_->PlatformInitialize(); | 140 platform_->PlatformInitialize(); |
| 155 | 141 |
| 156 // Setting flags and really doing anything with WebKit is fairly fragile and | 142 // Setting flags and really doing anything with WebKit is fairly fragile and |
| 157 // hacky, but this is the world we live in... | 143 // hacky, but this is the world we live in... |
| 158 webkit_glue::SetJavaScriptFlags(" --expose-gc"); | 144 webkit_glue::SetJavaScriptFlags(" --expose-gc"); |
| 159 WebKit::initialize(&webkit_platform_support_); | 145 WebKit::initialize(webkit_platform_support_.Get()); |
| 160 | 146 |
| 161 // Ensure that we register any necessary schemes when initializing WebKit, | 147 // Ensure that we register any necessary schemes when initializing WebKit, |
| 162 // since we are using a MockRenderThread. | 148 // since we are using a MockRenderThread. |
| 163 RenderThreadImpl::RegisterSchemes(); | 149 RenderThreadImpl::RegisterSchemes(); |
| 164 | 150 |
| 165 mock_process_.reset(new MockRenderProcess); | 151 mock_process_.reset(new MockRenderProcess); |
| 166 | 152 |
| 167 // This needs to pass the mock render thread to the view. | 153 // This needs to pass the mock render thread to the view. |
| 168 RenderViewImpl* view = RenderViewImpl::Create( | 154 RenderViewImpl* view = RenderViewImpl::Create( |
| 169 0, | 155 0, |
| 170 kOpenerId, | 156 kOpenerId, |
| 171 content::RendererPreferences(), | 157 content::RendererPreferences(), |
| 172 webkit_glue::WebPreferences(), | 158 webkit_glue::WebPreferences(), |
| 173 new SharedRenderViewCounter(0), | 159 new SharedRenderViewCounter(0), |
| 174 kRouteId, | 160 kRouteId, |
| 175 kSurfaceId, | 161 kSurfaceId, |
| 176 dom_storage::kInvalidSessionStorageNamespaceId, | 162 dom_storage::kInvalidSessionStorageNamespaceId, |
| 177 string16(), | 163 string16(), |
| 178 false, | 164 false, |
| 179 false, | 165 false, |
| 180 1, | 166 1, |
| 181 NULL, | 167 NULL, |
| 182 AccessibilityModeOff); | 168 AccessibilityModeOff); |
| 183 view->AddRef(); | 169 view->AddRef(); |
| 184 view_ = view; | 170 view_ = view; |
| 185 | |
| 186 // Attach a pseudo keyboard device to this object. | |
| 187 mock_keyboard_.reset(new MockKeyboard()); | |
| 188 } | 171 } |
| 189 | 172 |
| 190 void RenderViewTest::TearDown() { | 173 void RenderViewTest::TearDown() { |
| 191 // Try very hard to collect garbage before shutting down. | 174 // Try very hard to collect garbage before shutting down. |
| 192 GetMainFrame()->collectGarbage(); | 175 GetMainFrame()->collectGarbage(); |
| 193 GetMainFrame()->collectGarbage(); | 176 GetMainFrame()->collectGarbage(); |
| 194 | 177 |
| 195 // Run the loop so the release task from the renderwidget executes. | 178 // Run the loop so the release task from the renderwidget executes. |
| 196 ProcessPendingMessages(); | 179 ProcessPendingMessages(); |
| 197 | 180 |
| 198 render_thread_->SendCloseMessage(); | 181 render_thread_->SendCloseMessage(); |
| 199 view_ = NULL; | 182 view_ = NULL; |
| 200 mock_process_.reset(); | 183 mock_process_.reset(); |
| 201 | 184 |
| 202 // After telling the view to close and resetting mock_process_ we may get | 185 // After telling the view to close and resetting mock_process_ we may get |
| 203 // some new tasks which need to be processed before shutting down WebKit | 186 // some new tasks which need to be processed before shutting down WebKit |
| 204 // (http://crbug.com/21508). | 187 // (http://crbug.com/21508). |
| 205 msg_loop_.RunAllPending(); | 188 msg_loop_.RunAllPending(); |
| 206 | 189 |
| 207 WebKit::shutdown(); | 190 WebKit::shutdown(); |
| 208 | 191 |
| 209 mock_keyboard_.reset(); | |
| 210 | |
| 211 platform_->PlatformUninitialize(); | 192 platform_->PlatformUninitialize(); |
| 212 platform_.reset(); | 193 platform_.reset(); |
| 213 params_.reset(); | 194 params_.reset(); |
| 214 command_line_.reset(); | 195 command_line_.reset(); |
| 215 } | 196 } |
| 216 | 197 |
| 217 int RenderViewTest::SendKeyEvent(MockKeyboard::Layout layout, | |
| 218 int key_code, | |
| 219 MockKeyboard::Modifiers modifiers, | |
| 220 string16* output) { | |
| 221 #if defined(OS_WIN) | |
| 222 // Retrieve the Unicode character for the given tuple (keyboard-layout, | |
| 223 // key-code, and modifiers). | |
| 224 // Exit when a keyboard-layout driver cannot assign a Unicode character to | |
| 225 // the tuple to prevent sending an invalid key code to the RenderView object. | |
| 226 CHECK(mock_keyboard_.get()); | |
| 227 CHECK(output); | |
| 228 int length = mock_keyboard_->GetCharacters(layout, key_code, modifiers, | |
| 229 output); | |
| 230 if (length != 1) | |
| 231 return -1; | |
| 232 | |
| 233 // Create IPC messages from Windows messages and send them to our | |
| 234 // back-end. | |
| 235 // A keyboard event of Windows consists of three Windows messages: | |
| 236 // WM_KEYDOWN, WM_CHAR, and WM_KEYUP. | |
| 237 // WM_KEYDOWN and WM_KEYUP sends virtual-key codes. On the other hand, | |
| 238 // WM_CHAR sends a composed Unicode character. | |
| 239 MSG msg1 = { NULL, WM_KEYDOWN, key_code, 0 }; | |
| 240 #if defined(USE_AURA) | |
| 241 aura::KeyEvent evt1(msg1, false); | |
| 242 NativeWebKeyboardEvent keydown_event(&evt1); | |
| 243 #else | |
| 244 NativeWebKeyboardEvent keydown_event(msg1); | |
| 245 #endif | |
| 246 SendNativeKeyEvent(keydown_event); | |
| 247 | |
| 248 MSG msg2 = { NULL, WM_CHAR, (*output)[0], 0 }; | |
| 249 #if defined(USE_AURA) | |
| 250 aura::KeyEvent evt2(msg2, true); | |
| 251 NativeWebKeyboardEvent char_event(&evt2); | |
| 252 #else | |
| 253 NativeWebKeyboardEvent char_event(msg2); | |
| 254 #endif | |
| 255 SendNativeKeyEvent(char_event); | |
| 256 | |
| 257 MSG msg3 = { NULL, WM_KEYUP, key_code, 0 }; | |
| 258 #if defined(USE_AURA) | |
| 259 aura::KeyEvent evt3(msg3, false); | |
| 260 NativeWebKeyboardEvent keyup_event(&evt3); | |
| 261 #else | |
| 262 NativeWebKeyboardEvent keyup_event(msg3); | |
| 263 #endif | |
| 264 SendNativeKeyEvent(keyup_event); | |
| 265 | |
| 266 return length; | |
| 267 #elif defined(USE_AURA) && defined(USE_X11) | |
| 268 // We ignore |layout|, which means we are only testing the layout of the | |
| 269 // current locale. TODO(mazda): fix this to respect |layout|. | |
| 270 CHECK(output); | |
| 271 const int flags = ConvertMockKeyboardModifier(modifiers); | |
| 272 | |
| 273 XEvent xevent1; | |
| 274 InitXKeyEventForTesting(ui::ET_KEY_PRESSED, | |
| 275 static_cast<ui::KeyboardCode>(key_code), | |
| 276 flags, | |
| 277 &xevent1); | |
| 278 aura::KeyEvent event1(&xevent1, false); | |
| 279 NativeWebKeyboardEvent keydown_event(&event1); | |
| 280 SendNativeKeyEvent(keydown_event); | |
| 281 | |
| 282 XEvent xevent2; | |
| 283 InitXKeyEventForTesting(ui::ET_KEY_PRESSED, | |
| 284 static_cast<ui::KeyboardCode>(key_code), | |
| 285 flags, | |
| 286 &xevent2); | |
| 287 aura::KeyEvent event2(&xevent2, true); | |
| 288 NativeWebKeyboardEvent char_event(&event2); | |
| 289 SendNativeKeyEvent(char_event); | |
| 290 | |
| 291 XEvent xevent3; | |
| 292 InitXKeyEventForTesting(ui::ET_KEY_RELEASED, | |
| 293 static_cast<ui::KeyboardCode>(key_code), | |
| 294 flags, | |
| 295 &xevent3); | |
| 296 aura::KeyEvent event3(&xevent3, false); | |
| 297 NativeWebKeyboardEvent keyup_event(&event3); | |
| 298 SendNativeKeyEvent(keyup_event); | |
| 299 | |
| 300 long c = GetCharacterFromKeyCode(static_cast<ui::KeyboardCode>(key_code), | |
| 301 flags); | |
| 302 output->assign(1, static_cast<char16>(c)); | |
| 303 return 1; | |
| 304 #elif defined(OS_LINUX) | |
| 305 // We ignore |layout|, which means we are only testing the layout of the | |
| 306 // current locale. TODO(estade): fix this to respect |layout|. | |
| 307 std::vector<GdkEvent*> events; | |
| 308 ui::SynthesizeKeyPressEvents( | |
| 309 NULL, static_cast<ui::KeyboardCode>(key_code), | |
| 310 modifiers & (MockKeyboard::LEFT_CONTROL | MockKeyboard::RIGHT_CONTROL), | |
| 311 modifiers & (MockKeyboard::LEFT_SHIFT | MockKeyboard::RIGHT_SHIFT), | |
| 312 modifiers & (MockKeyboard::LEFT_ALT | MockKeyboard::RIGHT_ALT), | |
| 313 &events); | |
| 314 | |
| 315 guint32 unicode_key = 0; | |
| 316 for (size_t i = 0; i < events.size(); ++i) { | |
| 317 // Only send the up/down events for key press itself (skip the up/down | |
| 318 // events for the modifier keys). | |
| 319 if ((i + 1) == (events.size() / 2) || i == (events.size() / 2)) { | |
| 320 unicode_key = gdk_keyval_to_unicode(events[i]->key.keyval); | |
| 321 NativeWebKeyboardEvent webkit_event(events[i]); | |
| 322 SendNativeKeyEvent(webkit_event); | |
| 323 | |
| 324 // Need to add a char event after the key down. | |
| 325 if (webkit_event.type == WebKit::WebInputEvent::RawKeyDown) { | |
| 326 NativeWebKeyboardEvent char_event = webkit_event; | |
| 327 char_event.type = WebKit::WebInputEvent::Char; | |
| 328 char_event.skip_in_browser = true; | |
| 329 SendNativeKeyEvent(char_event); | |
| 330 } | |
| 331 } | |
| 332 gdk_event_free(events[i]); | |
| 333 } | |
| 334 | |
| 335 output->assign(1, static_cast<char16>(unicode_key)); | |
| 336 return 1; | |
| 337 #else | |
| 338 NOTIMPLEMENTED(); | |
| 339 return L'\0'; | |
| 340 #endif | |
| 341 } | |
| 342 | |
| 343 void RenderViewTest::SendNativeKeyEvent( | 198 void RenderViewTest::SendNativeKeyEvent( |
| 344 const NativeWebKeyboardEvent& key_event) { | 199 const NativeWebKeyboardEvent& key_event) { |
| 345 SendWebKeyboardEvent(key_event); | 200 SendWebKeyboardEvent(key_event); |
| 346 } | 201 } |
| 347 | 202 |
| 348 void RenderViewTest::SendWebKeyboardEvent( | 203 void RenderViewTest::SendWebKeyboardEvent( |
| 349 const WebKit::WebKeyboardEvent& key_event) { | 204 const WebKit::WebKeyboardEvent& key_event) { |
| 350 scoped_ptr<IPC::Message> input_message(new ViewMsg_HandleInputEvent(0)); | 205 scoped_ptr<IPC::Message> input_message(new ViewMsg_HandleInputEvent(0)); |
| 351 input_message->WriteData(reinterpret_cast<const char*>(&key_event), | 206 input_message->WriteData(reinterpret_cast<const char*>(&key_event), |
| 352 sizeof(WebKit::WebKeyboardEvent)); | 207 sizeof(WebKit::WebKeyboardEvent)); |
| (...skipping 140 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 493 | 348 |
| 494 ViewMsg_Navigate navigate_message(impl->GetRoutingID(), navigate_params); | 349 ViewMsg_Navigate navigate_message(impl->GetRoutingID(), navigate_params); |
| 495 OnMessageReceived(navigate_message); | 350 OnMessageReceived(navigate_message); |
| 496 | 351 |
| 497 // The load actually happens asynchronously, so we pump messages to process | 352 // The load actually happens asynchronously, so we pump messages to process |
| 498 // the pending continuation. | 353 // the pending continuation. |
| 499 ProcessPendingMessages(); | 354 ProcessPendingMessages(); |
| 500 } | 355 } |
| 501 | 356 |
| 502 } // namespace content | 357 } // namespace content |
| OLD | NEW |