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