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/shell/renderer/webkit_test_runner.h"
6
7 #include <algorithm>
8 #include <clocale>
9 #include <cmath>
10
11 #include "base/base64.h"
12 #include "base/command_line.h"
13 #include "base/debug/debugger.h"
14 #include "base/files/file_path.h"
15 #include "base/md5.h"
16 #include "base/memory/scoped_ptr.h"
17 #include "base/message_loop/message_loop.h"
18 #include "base/strings/string_util.h"
19 #include "base/strings/stringprintf.h"
20 #include "base/strings/sys_string_conversions.h"
21 #include "base/strings/utf_string_conversions.h"
22 #include "base/time/time.h"
23 #include "content/public/common/content_switches.h"
24 #include "content/public/common/url_constants.h"
25 #include "content/public/renderer/history_item_serialization.h"
26 #include "content/public/renderer/render_view.h"
27 #include "content/public/renderer/render_view_visitor.h"
28 #include "content/public/test/layouttest_support.h"
29 #include "content/shell/common/shell_messages.h"
30 #include "content/shell/common/webkit_test_helpers.h"
31 #include "content/shell/renderer/shell_render_process_observer.h"
32 #include "net/base/net_errors.h"
33 #include "net/base/net_util.h"
34 #include "skia/ext/platform_canvas.h"
35 #include "third_party/WebKit/public/platform/Platform.h"
36 #include "third_party/WebKit/public/platform/WebCString.h"
37 #include "third_party/WebKit/public/platform/WebPoint.h"
38 #include "third_party/WebKit/public/platform/WebRect.h"
39 #include "third_party/WebKit/public/platform/WebSize.h"
40 #include "third_party/WebKit/public/platform/WebString.h"
41 #include "third_party/WebKit/public/platform/WebURL.h"
42 #include "third_party/WebKit/public/platform/WebURLError.h"
43 #include "third_party/WebKit/public/platform/WebURLRequest.h"
44 #include "third_party/WebKit/public/platform/WebURLResponse.h"
45 #include "third_party/WebKit/public/testing/WebTask.h"
46 #include "third_party/WebKit/public/testing/WebTestInterfaces.h"
47 #include "third_party/WebKit/public/testing/WebTestProxy.h"
48 #include "third_party/WebKit/public/testing/WebTestRunner.h"
49 #include "third_party/WebKit/public/web/WebArrayBufferView.h"
50 #include "third_party/WebKit/public/web/WebContextMenuData.h"
51 #include "third_party/WebKit/public/web/WebDataSource.h"
52 #include "third_party/WebKit/public/web/WebDevToolsAgent.h"
53 #include "third_party/WebKit/public/web/WebDocument.h"
54 #include "third_party/WebKit/public/web/WebElement.h"
55 #include "third_party/WebKit/public/web/WebFrame.h"
56 #include "third_party/WebKit/public/web/WebHistoryItem.h"
57 #include "third_party/WebKit/public/web/WebKit.h"
58 #include "third_party/WebKit/public/web/WebScriptSource.h"
59 #include "third_party/WebKit/public/web/WebTestingSupport.h"
60 #include "third_party/WebKit/public/web/WebView.h"
61 #include "ui/gfx/rect.h"
62 #include "webkit/common/webpreferences.h"
63
64 using blink::Platform;
65 using blink::WebArrayBufferView;
66 using blink::WebContextMenuData;
67 using blink::WebDevToolsAgent;
68 using blink::WebDeviceMotionData;
69 using blink::WebDeviceOrientationData;
70 using blink::WebElement;
71 using blink::WebFrame;
72 using blink::WebGamepads;
73 using blink::WebHistoryItem;
74 using blink::WebPoint;
75 using blink::WebRect;
76 using blink::WebScriptSource;
77 using blink::WebSize;
78 using blink::WebString;
79 using blink::WebURL;
80 using blink::WebURLError;
81 using blink::WebURLRequest;
82 using blink::WebTestingSupport;
83 using blink::WebVector;
84 using blink::WebView;
85 using WebTestRunner::WebTask;
86 using WebTestRunner::WebTestInterfaces;
87 using WebTestRunner::WebTestProxyBase;
88
89 namespace content {
90
91 namespace {
92
InvokeTaskHelper(void * context)93 void InvokeTaskHelper(void* context) {
94 WebTask* task = reinterpret_cast<WebTask*>(context);
95 task->run();
96 delete task;
97 }
98
99 #if !defined(OS_MACOSX)
MakeBitmapOpaque(SkBitmap * bitmap)100 void MakeBitmapOpaque(SkBitmap* bitmap) {
101 SkAutoLockPixels lock(*bitmap);
102 DCHECK_EQ(bitmap->config(), SkBitmap::kARGB_8888_Config);
103 for (int y = 0; y < bitmap->height(); ++y) {
104 uint32_t* row = bitmap->getAddr32(0, y);
105 for (int x = 0; x < bitmap->width(); ++x)
106 row[x] |= 0xFF000000; // Set alpha bits to 1.
107 }
108 }
109 #endif
110
CopyCanvasToBitmap(SkCanvas * canvas,SkBitmap * snapshot)111 void CopyCanvasToBitmap(SkCanvas* canvas, SkBitmap* snapshot) {
112 SkBaseDevice* device = skia::GetTopDevice(*canvas);
113 const SkBitmap& bitmap = device->accessBitmap(false);
114 const bool success = bitmap.copyTo(snapshot, SkBitmap::kARGB_8888_Config);
115 DCHECK(success);
116
117 #if !defined(OS_MACOSX)
118 // Only the expected PNGs for Mac have a valid alpha channel.
119 if (!CommandLine::ForCurrentProcess()->HasSwitch(
120 switches::kEnableOverlayFullscreenVideo))
121 MakeBitmapOpaque(snapshot);
122 #endif
123 }
124
125 class SyncNavigationStateVisitor : public RenderViewVisitor {
126 public:
SyncNavigationStateVisitor()127 SyncNavigationStateVisitor() {}
~SyncNavigationStateVisitor()128 virtual ~SyncNavigationStateVisitor() {}
129
Visit(RenderView * render_view)130 virtual bool Visit(RenderView* render_view) OVERRIDE {
131 SyncNavigationState(render_view);
132 return true;
133 }
134 private:
135 DISALLOW_COPY_AND_ASSIGN(SyncNavigationStateVisitor);
136 };
137
138 class ProxyToRenderViewVisitor : public RenderViewVisitor {
139 public:
ProxyToRenderViewVisitor(WebTestProxyBase * proxy)140 explicit ProxyToRenderViewVisitor(WebTestProxyBase* proxy)
141 : proxy_(proxy),
142 render_view_(NULL) {
143 }
~ProxyToRenderViewVisitor()144 virtual ~ProxyToRenderViewVisitor() {}
145
render_view() const146 RenderView* render_view() const { return render_view_; }
147
Visit(RenderView * render_view)148 virtual bool Visit(RenderView* render_view) OVERRIDE {
149 WebKitTestRunner* test_runner = WebKitTestRunner::Get(render_view);
150 if (!test_runner) {
151 NOTREACHED();
152 return true;
153 }
154 if (test_runner->proxy() == proxy_) {
155 render_view_ = render_view;
156 return false;
157 }
158 return true;
159 }
160
161 private:
162 WebTestProxyBase* proxy_;
163 RenderView* render_view_;
164
165 DISALLOW_COPY_AND_ASSIGN(ProxyToRenderViewVisitor);
166 };
167
168 class NavigateAwayVisitor : public RenderViewVisitor {
169 public:
NavigateAwayVisitor(RenderView * main_render_view)170 explicit NavigateAwayVisitor(RenderView* main_render_view)
171 : main_render_view_(main_render_view) {}
~NavigateAwayVisitor()172 virtual ~NavigateAwayVisitor() {}
173
Visit(RenderView * render_view)174 virtual bool Visit(RenderView* render_view) OVERRIDE {
175 if (render_view == main_render_view_)
176 return true;
177 render_view->GetWebView()->mainFrame()->loadRequest(
178 WebURLRequest(GURL(kAboutBlankURL)));
179 return true;
180 }
181
182 private:
183 RenderView* main_render_view_;
184
185 DISALLOW_COPY_AND_ASSIGN(NavigateAwayVisitor);
186 };
187
188 class UseSynchronousResizeModeVisitor : public RenderViewVisitor {
189 public:
UseSynchronousResizeModeVisitor(bool enable)190 explicit UseSynchronousResizeModeVisitor(bool enable) : enable_(enable) {}
~UseSynchronousResizeModeVisitor()191 virtual ~UseSynchronousResizeModeVisitor() {}
192
Visit(RenderView * render_view)193 virtual bool Visit(RenderView* render_view) OVERRIDE {
194 UseSynchronousResizeMode(render_view, enable_);
195 return true;
196 }
197
198 private:
199 bool enable_;
200 };
201
202 } // namespace
203
WebKitTestRunner(RenderView * render_view)204 WebKitTestRunner::WebKitTestRunner(RenderView* render_view)
205 : RenderViewObserver(render_view),
206 RenderViewObserverTracker<WebKitTestRunner>(render_view),
207 proxy_(NULL),
208 focused_view_(NULL),
209 is_main_window_(false),
210 focus_on_next_commit_(false) {
211 UseMockMediaStreams(render_view);
212 }
213
~WebKitTestRunner()214 WebKitTestRunner::~WebKitTestRunner() {
215 }
216
217 // WebTestDelegate -----------------------------------------------------------
218
clearEditCommand()219 void WebKitTestRunner::clearEditCommand() {
220 render_view()->ClearEditCommands();
221 }
222
setEditCommand(const std::string & name,const std::string & value)223 void WebKitTestRunner::setEditCommand(const std::string& name,
224 const std::string& value) {
225 render_view()->SetEditCommandForNextKeyEvent(name, value);
226 }
227
setGamepadData(const WebGamepads & gamepads)228 void WebKitTestRunner::setGamepadData(const WebGamepads& gamepads) {
229 SetMockGamepads(gamepads);
230 }
231
setDeviceMotionData(const WebDeviceMotionData & data)232 void WebKitTestRunner::setDeviceMotionData(const WebDeviceMotionData& data) {
233 SetMockDeviceMotionData(data);
234 }
235
setDeviceOrientationData(const WebDeviceOrientationData & data)236 void WebKitTestRunner::setDeviceOrientationData(
237 const WebDeviceOrientationData& data) {
238 SetMockDeviceOrientationData(data);
239 }
240
printMessage(const std::string & message)241 void WebKitTestRunner::printMessage(const std::string& message) {
242 Send(new ShellViewHostMsg_PrintMessage(routing_id(), message));
243 }
244
postTask(WebTask * task)245 void WebKitTestRunner::postTask(WebTask* task) {
246 Platform::current()->callOnMainThread(InvokeTaskHelper, task);
247 }
248
postDelayedTask(WebTask * task,long long ms)249 void WebKitTestRunner::postDelayedTask(WebTask* task, long long ms) {
250 base::MessageLoop::current()->PostDelayedTask(
251 FROM_HERE,
252 base::Bind(&WebTask::run, base::Owned(task)),
253 base::TimeDelta::FromMilliseconds(ms));
254 }
255
registerIsolatedFileSystem(const blink::WebVector<blink::WebString> & absolute_filenames)256 WebString WebKitTestRunner::registerIsolatedFileSystem(
257 const blink::WebVector<blink::WebString>& absolute_filenames) {
258 std::vector<base::FilePath> files;
259 for (size_t i = 0; i < absolute_filenames.size(); ++i)
260 files.push_back(base::FilePath::FromUTF16Unsafe(absolute_filenames[i]));
261 std::string filesystem_id;
262 Send(new ShellViewHostMsg_RegisterIsolatedFileSystem(
263 routing_id(), files, &filesystem_id));
264 return WebString::fromUTF8(filesystem_id);
265 }
266
getCurrentTimeInMillisecond()267 long long WebKitTestRunner::getCurrentTimeInMillisecond() {
268 return base::TimeDelta(base::Time::Now() -
269 base::Time::UnixEpoch()).ToInternalValue() /
270 base::Time::kMicrosecondsPerMillisecond;
271 }
272
getAbsoluteWebStringFromUTF8Path(const std::string & utf8_path)273 WebString WebKitTestRunner::getAbsoluteWebStringFromUTF8Path(
274 const std::string& utf8_path) {
275 base::FilePath path = base::FilePath::FromUTF8Unsafe(utf8_path);
276 if (!path.IsAbsolute()) {
277 GURL base_url =
278 net::FilePathToFileURL(test_config_.current_working_directory.Append(
279 FILE_PATH_LITERAL("foo")));
280 net::FileURLToFilePath(base_url.Resolve(utf8_path), &path);
281 }
282 return path.AsUTF16Unsafe();
283 }
284
localFileToDataURL(const WebURL & file_url)285 WebURL WebKitTestRunner::localFileToDataURL(const WebURL& file_url) {
286 base::FilePath local_path;
287 if (!net::FileURLToFilePath(file_url, &local_path))
288 return WebURL();
289
290 std::string contents;
291 Send(new ShellViewHostMsg_ReadFileToString(
292 routing_id(), local_path, &contents));
293
294 std::string contents_base64;
295 base::Base64Encode(contents, &contents_base64);
296
297 const char data_url_prefix[] = "data:text/css:charset=utf-8;base64,";
298 return WebURL(GURL(data_url_prefix + contents_base64));
299 }
300
rewriteLayoutTestsURL(const std::string & utf8_url)301 WebURL WebKitTestRunner::rewriteLayoutTestsURL(const std::string& utf8_url) {
302 const char kPrefix[] = "file:///tmp/LayoutTests/";
303 const int kPrefixLen = arraysize(kPrefix) - 1;
304
305 if (utf8_url.compare(0, kPrefixLen, kPrefix, kPrefixLen))
306 return WebURL(GURL(utf8_url));
307
308 base::FilePath replace_path =
309 ShellRenderProcessObserver::GetInstance()->webkit_source_dir().Append(
310 FILE_PATH_LITERAL("LayoutTests/"));
311 #if defined(OS_WIN)
312 std::string utf8_path = WideToUTF8(replace_path.value());
313 #else
314 std::string utf8_path =
315 WideToUTF8(base::SysNativeMBToWide(replace_path.value()));
316 #endif
317 std::string new_url =
318 std::string("file://") + utf8_path + utf8_url.substr(kPrefixLen);
319 return WebURL(GURL(new_url));
320 }
321
preferences()322 WebTestRunner::WebPreferences* WebKitTestRunner::preferences() {
323 return &prefs_;
324 }
325
applyPreferences()326 void WebKitTestRunner::applyPreferences() {
327 WebPreferences prefs = render_view()->GetWebkitPreferences();
328 ExportLayoutTestSpecificPreferences(prefs_, &prefs);
329 render_view()->SetWebkitPreferences(prefs);
330 Send(new ShellViewHostMsg_OverridePreferences(routing_id(), prefs));
331 }
332
makeURLErrorDescription(const WebURLError & error)333 std::string WebKitTestRunner::makeURLErrorDescription(
334 const WebURLError& error) {
335 std::string domain = error.domain.utf8();
336 int code = error.reason;
337
338 if (domain == net::kErrorDomain) {
339 domain = "NSURLErrorDomain";
340 switch (error.reason) {
341 case net::ERR_ABORTED:
342 code = -999; // NSURLErrorCancelled
343 break;
344 case net::ERR_UNSAFE_PORT:
345 // Our unsafe port checking happens at the network stack level, but we
346 // make this translation here to match the behavior of stock WebKit.
347 domain = "WebKitErrorDomain";
348 code = 103;
349 break;
350 case net::ERR_ADDRESS_INVALID:
351 case net::ERR_ADDRESS_UNREACHABLE:
352 case net::ERR_NETWORK_ACCESS_DENIED:
353 code = -1004; // NSURLErrorCannotConnectToHost
354 break;
355 }
356 } else {
357 DLOG(WARNING) << "Unknown error domain";
358 }
359
360 return base::StringPrintf("<NSError domain %s, code %d, failing URL \"%s\">",
361 domain.c_str(), code, error.unreachableURL.spec().data());
362 }
363
useUnfortunateSynchronousResizeMode(bool enable)364 void WebKitTestRunner::useUnfortunateSynchronousResizeMode(bool enable) {
365 UseSynchronousResizeModeVisitor visitor(enable);
366 RenderView::ForEach(&visitor);
367 }
368
enableAutoResizeMode(const WebSize & min_size,const WebSize & max_size)369 void WebKitTestRunner::enableAutoResizeMode(const WebSize& min_size,
370 const WebSize& max_size) {
371 EnableAutoResizeMode(render_view(), min_size, max_size);
372 }
373
disableAutoResizeMode(const WebSize & new_size)374 void WebKitTestRunner::disableAutoResizeMode(const WebSize& new_size) {
375 DisableAutoResizeMode(render_view(), new_size);
376 if (!new_size.isEmpty())
377 ForceResizeRenderView(render_view(), new_size);
378 }
379
showDevTools()380 void WebKitTestRunner::showDevTools() {
381 Send(new ShellViewHostMsg_ShowDevTools(routing_id()));
382 }
383
closeDevTools()384 void WebKitTestRunner::closeDevTools() {
385 Send(new ShellViewHostMsg_CloseDevTools(routing_id()));
386 WebDevToolsAgent* agent = render_view()->GetWebView()->devToolsAgent();
387 if (agent)
388 agent->detach();
389 }
390
evaluateInWebInspector(long call_id,const std::string & script)391 void WebKitTestRunner::evaluateInWebInspector(long call_id,
392 const std::string& script) {
393 WebDevToolsAgent* agent = render_view()->GetWebView()->devToolsAgent();
394 if (agent)
395 agent->evaluateInWebInspector(call_id, WebString::fromUTF8(script));
396 }
397
clearAllDatabases()398 void WebKitTestRunner::clearAllDatabases() {
399 Send(new ShellViewHostMsg_ClearAllDatabases(routing_id()));
400 }
401
setDatabaseQuota(int quota)402 void WebKitTestRunner::setDatabaseQuota(int quota) {
403 Send(new ShellViewHostMsg_SetDatabaseQuota(routing_id(), quota));
404 }
405
setDeviceScaleFactor(float factor)406 void WebKitTestRunner::setDeviceScaleFactor(float factor) {
407 SetDeviceScaleFactor(render_view(), factor);
408 }
409
setFocus(WebTestProxyBase * proxy,bool focus)410 void WebKitTestRunner::setFocus(WebTestProxyBase* proxy, bool focus) {
411 ProxyToRenderViewVisitor visitor(proxy);
412 RenderView::ForEach(&visitor);
413 if (!visitor.render_view()) {
414 NOTREACHED();
415 return;
416 }
417
418 // Check whether the focused view was closed meanwhile.
419 if (!WebKitTestRunner::Get(focused_view_))
420 focused_view_ = NULL;
421
422 if (focus) {
423 if (focused_view_ != visitor.render_view()) {
424 if (focused_view_)
425 SetFocusAndActivate(focused_view_, false);
426 SetFocusAndActivate(visitor.render_view(), true);
427 focused_view_ = visitor.render_view();
428 }
429 } else {
430 if (focused_view_ == visitor.render_view()) {
431 SetFocusAndActivate(visitor.render_view(), false);
432 focused_view_ = NULL;
433 }
434 }
435 }
436
setAcceptAllCookies(bool accept)437 void WebKitTestRunner::setAcceptAllCookies(bool accept) {
438 Send(new ShellViewHostMsg_AcceptAllCookies(routing_id(), accept));
439 }
440
pathToLocalResource(const std::string & resource)441 std::string WebKitTestRunner::pathToLocalResource(const std::string& resource) {
442 #if defined(OS_WIN)
443 if (resource.find("/tmp/") == 0) {
444 // We want a temp file.
445 GURL base_url = net::FilePathToFileURL(test_config_.temp_path);
446 return base_url.Resolve(resource.substr(strlen("/tmp/"))).spec();
447 }
448 #endif
449
450 // Some layout tests use file://// which we resolve as a UNC path. Normalize
451 // them to just file:///.
452 std::string result = resource;
453 while (StringToLowerASCII(result).find("file:////") == 0) {
454 result = result.substr(0, strlen("file:///")) +
455 result.substr(strlen("file:////"));
456 }
457 return rewriteLayoutTestsURL(result).spec();
458 }
459
setLocale(const std::string & locale)460 void WebKitTestRunner::setLocale(const std::string& locale) {
461 setlocale(LC_ALL, locale.c_str());
462 }
463
testFinished()464 void WebKitTestRunner::testFinished() {
465 if (!is_main_window_) {
466 Send(new ShellViewHostMsg_TestFinishedInSecondaryWindow(routing_id()));
467 return;
468 }
469 WebTestInterfaces* interfaces =
470 ShellRenderProcessObserver::GetInstance()->test_interfaces();
471 interfaces->setTestIsRunning(false);
472 if (interfaces->testRunner()->shouldDumpBackForwardList()) {
473 SyncNavigationStateVisitor visitor;
474 RenderView::ForEach(&visitor);
475 Send(new ShellViewHostMsg_CaptureSessionHistory(routing_id()));
476 } else {
477 CaptureDump();
478 }
479 }
480
closeRemainingWindows()481 void WebKitTestRunner::closeRemainingWindows() {
482 NavigateAwayVisitor visitor(render_view());
483 RenderView::ForEach(&visitor);
484 Send(new ShellViewHostMsg_CloseRemainingWindows(routing_id()));
485 }
486
deleteAllCookies()487 void WebKitTestRunner::deleteAllCookies() {
488 Send(new ShellViewHostMsg_DeleteAllCookies(routing_id()));
489 }
490
navigationEntryCount()491 int WebKitTestRunner::navigationEntryCount() {
492 return GetLocalSessionHistoryLength(render_view());
493 }
494
goToOffset(int offset)495 void WebKitTestRunner::goToOffset(int offset) {
496 Send(new ShellViewHostMsg_GoToOffset(routing_id(), offset));
497 }
498
reload()499 void WebKitTestRunner::reload() {
500 Send(new ShellViewHostMsg_Reload(routing_id()));
501 }
502
loadURLForFrame(const WebURL & url,const std::string & frame_name)503 void WebKitTestRunner::loadURLForFrame(const WebURL& url,
504 const std::string& frame_name) {
505 Send(new ShellViewHostMsg_LoadURLForFrame(
506 routing_id(), url, frame_name));
507 }
508
allowExternalPages()509 bool WebKitTestRunner::allowExternalPages() {
510 return test_config_.allow_external_pages;
511 }
512
captureHistoryForWindow(WebTestProxyBase * proxy,WebVector<blink::WebHistoryItem> * history,size_t * currentEntryIndex)513 void WebKitTestRunner::captureHistoryForWindow(
514 WebTestProxyBase* proxy,
515 WebVector<blink::WebHistoryItem>* history,
516 size_t* currentEntryIndex) {
517 size_t pos = 0;
518 std::vector<int>::iterator id;
519 for (id = routing_ids_.begin(); id != routing_ids_.end(); ++id, ++pos) {
520 RenderView* render_view = RenderView::FromRoutingID(*id);
521 if (!render_view) {
522 NOTREACHED();
523 continue;
524 }
525 if (WebKitTestRunner::Get(render_view)->proxy() == proxy)
526 break;
527 }
528
529 if (id == routing_ids_.end()) {
530 NOTREACHED();
531 return;
532 }
533 size_t num_entries = session_histories_[pos].size();
534 *currentEntryIndex = current_entry_indexes_[pos];
535 WebVector<WebHistoryItem> result(num_entries);
536 for (size_t entry = 0; entry < num_entries; ++entry) {
537 result[entry] =
538 PageStateToHistoryItem(session_histories_[pos][entry]);
539 }
540 history->swap(result);
541 }
542
543 // RenderViewObserver --------------------------------------------------------
544
DidClearWindowObject(WebFrame * frame)545 void WebKitTestRunner::DidClearWindowObject(WebFrame* frame) {
546 WebTestingSupport::injectInternalsObject(frame);
547 ShellRenderProcessObserver::GetInstance()->test_interfaces()->bindTo(frame);
548 }
549
OnMessageReceived(const IPC::Message & message)550 bool WebKitTestRunner::OnMessageReceived(const IPC::Message& message) {
551 bool handled = true;
552 IPC_BEGIN_MESSAGE_MAP(WebKitTestRunner, message)
553 IPC_MESSAGE_HANDLER(ShellViewMsg_SetTestConfiguration,
554 OnSetTestConfiguration)
555 IPC_MESSAGE_HANDLER(ShellViewMsg_SessionHistory, OnSessionHistory)
556 IPC_MESSAGE_HANDLER(ShellViewMsg_Reset, OnReset)
557 IPC_MESSAGE_HANDLER(ShellViewMsg_NotifyDone, OnNotifyDone)
558 IPC_MESSAGE_UNHANDLED(handled = false)
559 IPC_END_MESSAGE_MAP()
560
561 return handled;
562 }
563
Navigate(const GURL & url)564 void WebKitTestRunner::Navigate(const GURL& url) {
565 focus_on_next_commit_ = true;
566 if (!is_main_window_ &&
567 ShellRenderProcessObserver::GetInstance()->main_test_runner() == this) {
568 WebTestInterfaces* interfaces =
569 ShellRenderProcessObserver::GetInstance()->test_interfaces();
570 interfaces->setTestIsRunning(true);
571 interfaces->configureForTestWithURL(GURL(), false);
572 ForceResizeRenderView(render_view(), WebSize(800, 600));
573 }
574 }
575
DidCommitProvisionalLoad(WebFrame * frame,bool is_new_navigation)576 void WebKitTestRunner::DidCommitProvisionalLoad(WebFrame* frame,
577 bool is_new_navigation) {
578 if (!focus_on_next_commit_)
579 return;
580 focus_on_next_commit_ = false;
581 render_view()->GetWebView()->setFocusedFrame(frame);
582 }
583
DidFailProvisionalLoad(WebFrame * frame,const WebURLError & error)584 void WebKitTestRunner::DidFailProvisionalLoad(WebFrame* frame,
585 const WebURLError& error) {
586 focus_on_next_commit_ = false;
587 }
588
589 // Public methods - -----------------------------------------------------------
590
Reset()591 void WebKitTestRunner::Reset() {
592 // The proxy_ is always non-NULL, it is set right after construction.
593 proxy_->setWidget(render_view()->GetWebView());
594 proxy_->reset();
595 prefs_.reset();
596 routing_ids_.clear();
597 session_histories_.clear();
598 current_entry_indexes_.clear();
599
600 render_view()->ClearEditCommands();
601 render_view()->GetWebView()->mainFrame()->setName(WebString());
602 render_view()->GetWebView()->mainFrame()->clearOpener();
603 render_view()->GetWebView()->setPageScaleFactorLimits(-1, -1);
604 render_view()->GetWebView()->setPageScaleFactor(1, WebPoint(0, 0));
605
606 // Resetting the internals object also overrides the WebPreferences, so we
607 // have to sync them to WebKit again.
608 WebTestingSupport::resetInternalsObject(
609 render_view()->GetWebView()->mainFrame());
610 render_view()->SetWebkitPreferences(render_view()->GetWebkitPreferences());
611 }
612
613 // Private methods -----------------------------------------------------------
614
CaptureDump()615 void WebKitTestRunner::CaptureDump() {
616 WebTestInterfaces* interfaces =
617 ShellRenderProcessObserver::GetInstance()->test_interfaces();
618
619 if (interfaces->testRunner()->shouldDumpAsAudio()) {
620 const WebArrayBufferView* audio_data =
621 interfaces->testRunner()->audioData();
622 std::vector<unsigned char> vector_data(
623 static_cast<const unsigned char*>(audio_data->baseAddress()),
624 static_cast<const unsigned char*>(audio_data->baseAddress()) +
625 audio_data->byteLength());
626 Send(new ShellViewHostMsg_AudioDump(routing_id(), vector_data));
627 } else {
628 Send(new ShellViewHostMsg_TextDump(routing_id(),
629 proxy()->captureTree(false)));
630
631 if (test_config_.enable_pixel_dumping &&
632 interfaces->testRunner()->shouldGeneratePixelResults()) {
633 SkBitmap snapshot;
634 CopyCanvasToBitmap(proxy()->capturePixels(), &snapshot);
635
636 SkAutoLockPixels snapshot_lock(snapshot);
637 base::MD5Digest digest;
638 base::MD5Sum(snapshot.getPixels(), snapshot.getSize(), &digest);
639 std::string actual_pixel_hash = base::MD5DigestToBase16(digest);
640
641 if (actual_pixel_hash == test_config_.expected_pixel_hash) {
642 SkBitmap empty_image;
643 Send(new ShellViewHostMsg_ImageDump(
644 routing_id(), actual_pixel_hash, empty_image));
645 } else {
646 Send(new ShellViewHostMsg_ImageDump(
647 routing_id(), actual_pixel_hash, snapshot));
648 }
649 }
650 }
651
652 render_view()->GetWebView()->mainFrame()->stopLoading();
653
654 base::MessageLoop::current()->PostTask(
655 FROM_HERE,
656 base::Bind(base::IgnoreResult(&WebKitTestRunner::Send),
657 base::Unretained(this),
658 new ShellViewHostMsg_TestFinished(routing_id())));
659 }
660
OnSetTestConfiguration(const ShellTestConfiguration & params)661 void WebKitTestRunner::OnSetTestConfiguration(
662 const ShellTestConfiguration& params) {
663 test_config_ = params;
664 is_main_window_ = true;
665
666 ForceResizeRenderView(
667 render_view(),
668 WebSize(params.initial_size.width(), params.initial_size.height()));
669 setFocus(proxy_, true);
670
671 WebTestInterfaces* interfaces =
672 ShellRenderProcessObserver::GetInstance()->test_interfaces();
673 interfaces->setTestIsRunning(true);
674 interfaces->configureForTestWithURL(params.test_url,
675 params.enable_pixel_dumping);
676 }
677
OnSessionHistory(const std::vector<int> & routing_ids,const std::vector<std::vector<PageState>> & session_histories,const std::vector<unsigned> & current_entry_indexes)678 void WebKitTestRunner::OnSessionHistory(
679 const std::vector<int>& routing_ids,
680 const std::vector<std::vector<PageState> >& session_histories,
681 const std::vector<unsigned>& current_entry_indexes) {
682 routing_ids_ = routing_ids;
683 session_histories_ = session_histories;
684 current_entry_indexes_ = current_entry_indexes;
685 CaptureDump();
686 }
687
OnReset()688 void WebKitTestRunner::OnReset() {
689 ShellRenderProcessObserver::GetInstance()->test_interfaces()->resetAll();
690 Reset();
691 // Navigating to about:blank will make sure that no new loads are initiated
692 // by the renderer.
693 render_view()->GetWebView()->mainFrame()->loadRequest(
694 WebURLRequest(GURL(kAboutBlankURL)));
695 Send(new ShellViewHostMsg_ResetDone(routing_id()));
696 }
697
OnNotifyDone()698 void WebKitTestRunner::OnNotifyDone() {
699 render_view()->GetWebView()->mainFrame()->executeScript(
700 WebScriptSource(WebString::fromUTF8("testRunner.notifyDone();")));
701 }
702
703 } // namespace content
704