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