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