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 |