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