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