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