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