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