OLD | NEW |
| (Empty) |
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 | |
3 // found in the LICENSE file. | |
4 | |
5 #include "content/public/test/render_view_test.h" | |
6 | |
7 #include "content/common/view_messages.h" | |
8 #include "content/public/browser/native_web_keyboard_event.h" | |
9 #include "content/public/common/renderer_preferences.h" | |
10 #include "content/renderer/render_thread_impl.h" | |
11 #include "content/renderer/render_view_impl.h" | |
12 #include "content/renderer/renderer_main_platform_delegate.h" | |
13 #include "content/renderer/renderer_webkitplatformsupport_impl.h" | |
14 #include "content/test/mock_render_process.h" | |
15 #include "third_party/WebKit/Source/WebKit/chromium/public/WebFrame.h" | |
16 #include "third_party/WebKit/Source/WebKit/chromium/public/WebHistoryItem.h" | |
17 #include "third_party/WebKit/Source/WebKit/chromium/public/WebInputEvent.h" | |
18 #include "third_party/WebKit/Source/WebKit/chromium/public/WebKit.h" | |
19 #include "third_party/WebKit/Source/WebKit/chromium/public/WebScreenInfo.h" | |
20 #include "third_party/WebKit/Source/WebKit/chromium/public/WebScriptController.h
" | |
21 #include "third_party/WebKit/Source/WebKit/chromium/public/WebScriptSource.h" | |
22 #include "third_party/WebKit/Source/WebKit/chromium/public/platform/WebURLReques
t.h" | |
23 #include "third_party/WebKit/Source/WebKit/chromium/public/WebView.h" | |
24 #include "webkit/dom_storage/dom_storage_types.h" | |
25 #include "webkit/glue/glue_serialize.h" | |
26 #include "webkit/glue/webkit_glue.h" | |
27 | |
28 using WebKit::WebFrame; | |
29 using WebKit::WebInputEvent; | |
30 using WebKit::WebMouseEvent; | |
31 using WebKit::WebScriptController; | |
32 using WebKit::WebScriptSource; | |
33 using WebKit::WebString; | |
34 using WebKit::WebURLRequest; | |
35 using content::NativeWebKeyboardEvent; | |
36 | |
37 namespace { | |
38 const int32 kOpenerId = -2; | |
39 const int32 kRouteId = 5; | |
40 const int32 kNewWindowRouteId = 6; | |
41 const int32 kSurfaceId = 42; | |
42 | |
43 } // namespace | |
44 | |
45 namespace content { | |
46 | |
47 class RendererWebKitPlatformSupportImplNoSandboxImpl : | |
48 public RendererWebKitPlatformSupportImpl { | |
49 public: | |
50 virtual WebKit::WebSandboxSupport* sandboxSupport() { | |
51 return NULL; | |
52 } | |
53 }; | |
54 | |
55 RenderViewTest::RendererWebKitPlatformSupportImplNoSandbox:: | |
56 RendererWebKitPlatformSupportImplNoSandbox() { | |
57 webkit_platform_support_.reset( | |
58 new RendererWebKitPlatformSupportImplNoSandboxImpl()); | |
59 } | |
60 | |
61 RenderViewTest::RendererWebKitPlatformSupportImplNoSandbox:: | |
62 ~RendererWebKitPlatformSupportImplNoSandbox() { | |
63 } | |
64 | |
65 WebKit::WebKitPlatformSupport* | |
66 RenderViewTest::RendererWebKitPlatformSupportImplNoSandbox::Get() { | |
67 return webkit_platform_support_.get(); | |
68 } | |
69 | |
70 RenderViewTest::RenderViewTest() | |
71 : view_(NULL) { | |
72 } | |
73 | |
74 RenderViewTest::~RenderViewTest() { | |
75 } | |
76 | |
77 void RenderViewTest::ProcessPendingMessages() { | |
78 msg_loop_.PostTask(FROM_HERE, MessageLoop::QuitClosure()); | |
79 msg_loop_.Run(); | |
80 } | |
81 | |
82 WebFrame* RenderViewTest::GetMainFrame() { | |
83 return view_->GetWebView()->mainFrame(); | |
84 } | |
85 | |
86 void RenderViewTest::ExecuteJavaScript(const char* js) { | |
87 GetMainFrame()->executeScript(WebScriptSource(WebString::fromUTF8(js))); | |
88 } | |
89 | |
90 bool RenderViewTest::ExecuteJavaScriptAndReturnIntValue( | |
91 const string16& script, | |
92 int* int_result) { | |
93 v8::Handle<v8::Value> result = | |
94 GetMainFrame()->executeScriptAndReturnValue(WebScriptSource(script)); | |
95 if (result.IsEmpty() || !result->IsInt32()) | |
96 return false; | |
97 | |
98 if (int_result) | |
99 *int_result = result->Int32Value(); | |
100 | |
101 return true; | |
102 } | |
103 | |
104 void RenderViewTest::LoadHTML(const char* html) { | |
105 std::string url_str = "data:text/html;charset=utf-8,"; | |
106 url_str.append(html); | |
107 GURL url(url_str); | |
108 | |
109 GetMainFrame()->loadRequest(WebURLRequest(url)); | |
110 | |
111 // The load actually happens asynchronously, so we pump messages to process | |
112 // the pending continuation. | |
113 ProcessPendingMessages(); | |
114 } | |
115 | |
116 void RenderViewTest::GoBack(const WebKit::WebHistoryItem& item) { | |
117 GoToOffset(-1, item); | |
118 } | |
119 | |
120 void RenderViewTest::GoForward(const WebKit::WebHistoryItem& item) { | |
121 GoToOffset(1, item); | |
122 } | |
123 | |
124 void RenderViewTest::SetUp() { | |
125 // Subclasses can set the ContentClient's renderer before calling | |
126 // RenderViewTest::SetUp(). | |
127 if (!GetContentClient()->renderer()) | |
128 GetContentClient()->set_renderer_for_testing(&content_renderer_client_); | |
129 | |
130 // Subclasses can set render_thread_ with their own implementation before | |
131 // calling RenderViewTest::SetUp(). | |
132 if (!render_thread_.get()) | |
133 render_thread_.reset(new MockRenderThread()); | |
134 render_thread_->set_routing_id(kRouteId); | |
135 render_thread_->set_surface_id(kSurfaceId); | |
136 render_thread_->set_new_window_routing_id(kNewWindowRouteId); | |
137 | |
138 command_line_.reset(new CommandLine(CommandLine::NO_PROGRAM)); | |
139 params_.reset(new content::MainFunctionParams(*command_line_)); | |
140 platform_.reset(new RendererMainPlatformDelegate(*params_)); | |
141 platform_->PlatformInitialize(); | |
142 | |
143 // Setting flags and really doing anything with WebKit is fairly fragile and | |
144 // hacky, but this is the world we live in... | |
145 webkit_glue::SetJavaScriptFlags(" --expose-gc"); | |
146 WebKit::initialize(webkit_platform_support_.Get()); | |
147 | |
148 // Ensure that we register any necessary schemes when initializing WebKit, | |
149 // since we are using a MockRenderThread. | |
150 RenderThreadImpl::RegisterSchemes(); | |
151 | |
152 mock_process_.reset(new MockRenderProcess); | |
153 | |
154 // This needs to pass the mock render thread to the view. | |
155 RenderViewImpl* view = RenderViewImpl::Create( | |
156 0, | |
157 kOpenerId, | |
158 content::RendererPreferences(), | |
159 webkit_glue::WebPreferences(), | |
160 new SharedRenderViewCounter(0), | |
161 kRouteId, | |
162 kSurfaceId, | |
163 dom_storage::kInvalidSessionStorageNamespaceId, | |
164 string16(), | |
165 false, | |
166 false, | |
167 1, | |
168 WebKit::WebScreenInfo(), | |
169 NULL, | |
170 AccessibilityModeOff); | |
171 view->AddRef(); | |
172 view_ = view; | |
173 } | |
174 | |
175 void RenderViewTest::TearDown() { | |
176 // Try very hard to collect garbage before shutting down. | |
177 GetMainFrame()->collectGarbage(); | |
178 GetMainFrame()->collectGarbage(); | |
179 | |
180 // Run the loop so the release task from the renderwidget executes. | |
181 ProcessPendingMessages(); | |
182 | |
183 render_thread_->SendCloseMessage(); | |
184 view_ = NULL; | |
185 mock_process_.reset(); | |
186 | |
187 // After telling the view to close and resetting mock_process_ we may get | |
188 // some new tasks which need to be processed before shutting down WebKit | |
189 // (http://crbug.com/21508). | |
190 msg_loop_.RunAllPending(); | |
191 | |
192 WebKit::shutdown(); | |
193 | |
194 platform_->PlatformUninitialize(); | |
195 platform_.reset(); | |
196 params_.reset(); | |
197 command_line_.reset(); | |
198 } | |
199 | |
200 void RenderViewTest::SendNativeKeyEvent( | |
201 const NativeWebKeyboardEvent& key_event) { | |
202 SendWebKeyboardEvent(key_event); | |
203 } | |
204 | |
205 void RenderViewTest::SendWebKeyboardEvent( | |
206 const WebKit::WebKeyboardEvent& key_event) { | |
207 scoped_ptr<IPC::Message> input_message(new ViewMsg_HandleInputEvent(0)); | |
208 input_message->WriteData(reinterpret_cast<const char*>(&key_event), | |
209 sizeof(WebKit::WebKeyboardEvent)); | |
210 RenderViewImpl* impl = static_cast<RenderViewImpl*>(view_); | |
211 impl->OnMessageReceived(*input_message); | |
212 } | |
213 | |
214 void RenderViewTest::SendWebMouseEvent( | |
215 const WebKit::WebMouseEvent& mouse_event) { | |
216 scoped_ptr<IPC::Message> input_message(new ViewMsg_HandleInputEvent(0)); | |
217 input_message->WriteData(reinterpret_cast<const char*>(&mouse_event), | |
218 sizeof(WebKit::WebMouseEvent)); | |
219 RenderViewImpl* impl = static_cast<RenderViewImpl*>(view_); | |
220 impl->OnMessageReceived(*input_message); | |
221 } | |
222 | |
223 const char* const kGetCoordinatesScript = | |
224 "(function() {" | |
225 " function GetCoordinates(elem) {" | |
226 " if (!elem)" | |
227 " return [ 0, 0];" | |
228 " var coordinates = [ elem.offsetLeft, elem.offsetTop];" | |
229 " var parent_coordinates = GetCoordinates(elem.offsetParent);" | |
230 " coordinates[0] += parent_coordinates[0];" | |
231 " coordinates[1] += parent_coordinates[1];" | |
232 " return coordinates;" | |
233 " };" | |
234 " var elem = document.getElementById('$1');" | |
235 " if (!elem)" | |
236 " return null;" | |
237 " var bounds = GetCoordinates(elem);" | |
238 " bounds[2] = elem.offsetWidth;" | |
239 " bounds[3] = elem.offsetHeight;" | |
240 " return bounds;" | |
241 "})();"; | |
242 gfx::Rect RenderViewTest::GetElementBounds(const std::string& element_id) { | |
243 std::vector<std::string> params; | |
244 params.push_back(element_id); | |
245 std::string script = | |
246 ReplaceStringPlaceholders(kGetCoordinatesScript, params, NULL); | |
247 | |
248 v8::HandleScope handle_scope; | |
249 v8::Handle<v8::Value> value = GetMainFrame()->executeScriptAndReturnValue( | |
250 WebScriptSource(WebString::fromUTF8(script))); | |
251 if (value.IsEmpty() || !value->IsArray()) | |
252 return gfx::Rect(); | |
253 | |
254 v8::Handle<v8::Array> array = value.As<v8::Array>(); | |
255 if (array->Length() != 4) | |
256 return gfx::Rect(); | |
257 std::vector<int> coords; | |
258 for (int i = 0; i < 4; ++i) { | |
259 v8::Handle<v8::Number> index = v8::Number::New(i); | |
260 v8::Local<v8::Value> value = array->Get(index); | |
261 if (value.IsEmpty() || !value->IsInt32()) | |
262 return gfx::Rect(); | |
263 coords.push_back(value->Int32Value()); | |
264 } | |
265 return gfx::Rect(coords[0], coords[1], coords[2], coords[3]); | |
266 } | |
267 | |
268 bool RenderViewTest::SimulateElementClick(const std::string& element_id) { | |
269 gfx::Rect bounds = GetElementBounds(element_id); | |
270 if (bounds.IsEmpty()) | |
271 return false; | |
272 WebMouseEvent mouse_event; | |
273 mouse_event.type = WebInputEvent::MouseDown; | |
274 mouse_event.button = WebMouseEvent::ButtonLeft; | |
275 mouse_event.x = bounds.CenterPoint().x(); | |
276 mouse_event.y = bounds.CenterPoint().y(); | |
277 mouse_event.clickCount = 1; | |
278 ViewMsg_HandleInputEvent input_event(0); | |
279 scoped_ptr<IPC::Message> input_message(new ViewMsg_HandleInputEvent(0)); | |
280 input_message->WriteData(reinterpret_cast<const char*>(&mouse_event), | |
281 sizeof(WebMouseEvent)); | |
282 RenderViewImpl* impl = static_cast<RenderViewImpl*>(view_); | |
283 impl->OnMessageReceived(*input_message); | |
284 return true; | |
285 } | |
286 | |
287 void RenderViewTest::SetFocused(const WebKit::WebNode& node) { | |
288 RenderViewImpl* impl = static_cast<RenderViewImpl*>(view_); | |
289 impl->focusedNodeChanged(node); | |
290 } | |
291 | |
292 void RenderViewTest::ClearHistory() { | |
293 RenderViewImpl* impl = static_cast<RenderViewImpl*>(view_); | |
294 impl->page_id_ = -1; | |
295 impl->history_list_offset_ = -1; | |
296 impl->history_list_length_ = 0; | |
297 impl->history_page_ids_.clear(); | |
298 } | |
299 | |
300 void RenderViewTest::Reload(const GURL& url) { | |
301 ViewMsg_Navigate_Params params; | |
302 params.url = url; | |
303 params.navigation_type = ViewMsg_Navigate_Type::RELOAD; | |
304 RenderViewImpl* impl = static_cast<RenderViewImpl*>(view_); | |
305 impl->OnNavigate(params); | |
306 } | |
307 | |
308 uint32 RenderViewTest::GetNavigationIPCType() { | |
309 return ViewHostMsg_FrameNavigate::ID; | |
310 } | |
311 | |
312 bool RenderViewTest::OnMessageReceived(const IPC::Message& msg) { | |
313 RenderViewImpl* impl = static_cast<RenderViewImpl*>(view_); | |
314 return impl->OnMessageReceived(msg); | |
315 } | |
316 | |
317 void RenderViewTest::DidNavigateWithinPage(WebKit::WebFrame* frame, | |
318 bool is_new_navigation) { | |
319 RenderViewImpl* impl = static_cast<RenderViewImpl*>(view_); | |
320 impl->didNavigateWithinPage(frame, is_new_navigation); | |
321 } | |
322 | |
323 void RenderViewTest::SendContentStateImmediately() { | |
324 RenderViewImpl* impl = static_cast<RenderViewImpl*>(view_); | |
325 impl->set_send_content_state_immediately(true); | |
326 } | |
327 | |
328 WebKit::WebWidget* RenderViewTest::GetWebWidget() { | |
329 RenderViewImpl* impl = static_cast<RenderViewImpl*>(view_); | |
330 return impl->webwidget(); | |
331 } | |
332 | |
333 void RenderViewTest::GoToOffset(int offset, | |
334 const WebKit::WebHistoryItem& history_item) { | |
335 RenderViewImpl* impl = static_cast<RenderViewImpl*>(view_); | |
336 | |
337 int history_list_length = impl->historyBackListCount() + | |
338 impl->historyForwardListCount() + 1; | |
339 int pending_offset = offset + impl->history_list_offset(); | |
340 | |
341 ViewMsg_Navigate_Params navigate_params; | |
342 navigate_params.navigation_type = ViewMsg_Navigate_Type::NORMAL; | |
343 navigate_params.transition = content::PAGE_TRANSITION_FORWARD_BACK; | |
344 navigate_params.current_history_list_length = history_list_length; | |
345 navigate_params.current_history_list_offset = impl->history_list_offset(); | |
346 navigate_params.pending_history_list_offset = pending_offset; | |
347 navigate_params.page_id = impl->GetPageId() + offset; | |
348 navigate_params.state = webkit_glue::HistoryItemToString(history_item); | |
349 navigate_params.request_time = base::Time::Now(); | |
350 | |
351 ViewMsg_Navigate navigate_message(impl->GetRoutingID(), navigate_params); | |
352 OnMessageReceived(navigate_message); | |
353 | |
354 // The load actually happens asynchronously, so we pump messages to process | |
355 // the pending continuation. | |
356 ProcessPendingMessages(); | |
357 } | |
358 | |
359 } // namespace content | |
OLD | NEW |