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