1/* 2 Copyright (C) 2010 Robert Hogan <robert@roberthogan.net> 3 Copyright (C) 2008,2009,2010 Nokia Corporation and/or its subsidiary(-ies) 4 Copyright (C) 2007 Staikos Computing Services Inc. 5 Copyright (C) 2007, 2012 Apple Inc. 6 7 This library is free software; you can redistribute it and/or 8 modify it under the terms of the GNU Library General Public 9 License as published by the Free Software Foundation; either 10 version 2 of the License, or (at your option) any later version. 11 12 This library is distributed in the hope that it will be useful, 13 but WITHOUT ANY WARRANTY; without even the implied warranty of 14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 Library General Public License for more details. 16 17 You should have received a copy of the GNU Library General Public License 18 along with this library; see the file COPYING.LIB. If not, write to 19 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 20 Boston, MA 02110-1301, USA. 21*/ 22 23#include "config.h" 24#include "DumpRenderTreeSupportQt.h" 25 26#include "APICast.h" 27#include "ApplicationCacheStorage.h" 28#include "ChromeClientQt.h" 29#include "ContainerNode.h" 30#include "ContextMenu.h" 31#include "ContextMenuClientQt.h" 32#include "ContextMenuController.h" 33#include "DeviceOrientationClientMock.h" 34#include "DeviceOrientationController.h" 35#include "DeviceOrientationData.h" 36#include "DocumentLoader.h" 37#include "Editor.h" 38#include "EditorClientQt.h" 39#include "Element.h" 40#include "FocusController.h" 41#include "Font.h" 42#include "Frame.h" 43#include "FrameLoadRequest.h" 44#include "FrameLoaderClientQt.h" 45#include "FrameView.h" 46#include "GCController.h" 47#include "GeolocationClient.h" 48#include "GeolocationClientMock.h" 49#include "GeolocationController.h" 50#include "GeolocationError.h" 51#include "GeolocationPosition.h" 52#include "HTMLFormElement.h" 53#include "HTMLInputElement.h" 54#include "HistoryItem.h" 55#include "InspectorController.h" 56#include "JSNode.h" 57#include "NodeList.h" 58#include "NotificationPresenterClientQt.h" 59#include "Page.h" 60#include "PageGroup.h" 61#include "PluginDatabase.h" 62#include "PluginView.h" 63#include "PositionError.h" 64#include "PrintContext.h" 65#include "QWebFrameAdapter.h" 66#include "QWebPageAdapter.h" 67#include "RenderListItem.h" 68#include "RenderTreeAsText.h" 69#include "RuntimeEnabledFeatures.h" 70#include "SchemeRegistry.h" 71#include "ScriptController.h" 72#include "ScriptSourceCode.h" 73#include "ScriptValue.h" 74#include "SecurityOrigin.h" 75#include "SecurityPolicy.h" 76#include "Settings.h" 77#include "TextIterator.h" 78#include "ThirdPartyCookiesQt.h" 79#include "WebCoreTestSupport.h" 80#include "qt_runtime.h" 81#include "qwebelement.h" 82#include "qwebhistory.h" 83#include "qwebhistory_p.h" 84#include "qwebscriptworld.h" 85 86#if ENABLE(VIDEO) && USE(QT_MULTIMEDIA) 87#include "HTMLVideoElement.h" 88#include "MediaPlayerPrivateQt.h" 89#endif 90 91#include <QPainter> 92#include <wtf/CurrentTime.h> 93 94using namespace WebCore; 95 96QMap<int, QWebScriptWorld*> m_worldMap; 97 98#if ENABLE(GEOLOCATION) 99GeolocationClientMock* toGeolocationClientMock(GeolocationClient* client) 100{ 101 ASSERT(QWebPageAdapter::drtRun); 102 return static_cast<GeolocationClientMock*>(client); 103} 104#endif 105 106#if ENABLE(DEVICE_ORIENTATION) 107DeviceOrientationClientMock* toDeviceOrientationClientMock(DeviceOrientationClient* client) 108{ 109 ASSERT(QWebPageAdapter::drtRun); 110 return static_cast<DeviceOrientationClientMock*>(client); 111} 112#endif 113 114QDRTNode::QDRTNode() 115 : m_node(0) 116{ 117} 118 119QDRTNode::QDRTNode(WebCore::Node* node) 120 : m_node(0) 121{ 122 if (node) { 123 m_node = node; 124 m_node->ref(); 125 } 126} 127 128QDRTNode::~QDRTNode() 129{ 130 if (m_node) 131 m_node->deref(); 132} 133 134QDRTNode::QDRTNode(const QDRTNode& other) 135 :m_node(other.m_node) 136{ 137 if (m_node) 138 m_node->ref(); 139} 140 141QDRTNode& QDRTNode::operator=(const QDRTNode& other) 142{ 143 if (this != &other) { 144 Node* otherNode = other.m_node; 145 if (otherNode) 146 otherNode->ref(); 147 if (m_node) 148 m_node->deref(); 149 m_node = otherNode; 150 } 151 return *this; 152} 153 154QDRTNode QtDRTNodeRuntime::create(WebCore::Node* node) 155{ 156 return QDRTNode(node); 157} 158 159WebCore::Node* QtDRTNodeRuntime::get(const QDRTNode& node) 160{ 161 return node.m_node; 162} 163 164static QVariant convertJSValueToNodeVariant(JSC::JSObject* object, int *distance, HashSet<JSObjectRef>*) 165{ 166 if (!object || !object->inherits(&JSNode::s_info)) 167 return QVariant(); 168 return QVariant::fromValue<QDRTNode>(QtDRTNodeRuntime::create((static_cast<JSNode*>(object))->impl())); 169} 170 171static JSC::JSValue convertNodeVariantToJSValue(JSC::ExecState* exec, WebCore::JSDOMGlobalObject* globalObject, const QVariant& variant) 172{ 173 return toJS(exec, globalObject, QtDRTNodeRuntime::get(variant.value<QDRTNode>())); 174} 175 176void QtDRTNodeRuntime::initialize() 177{ 178 static bool initialized = false; 179 if (initialized) 180 return; 181 initialized = true; 182 int id = qRegisterMetaType<QDRTNode>(); 183 JSC::Bindings::registerCustomType(id, convertJSValueToNodeVariant, convertNodeVariantToJSValue); 184} 185 186DumpRenderTreeSupportQt::DumpRenderTreeSupportQt() 187{ 188} 189 190DumpRenderTreeSupportQt::~DumpRenderTreeSupportQt() 191{ 192} 193 194void DumpRenderTreeSupportQt::initialize() 195{ 196 QtDRTNodeRuntime::initialize(); 197} 198 199void DumpRenderTreeSupportQt::overwritePluginDirectories() 200{ 201 PluginDatabase* db = PluginDatabase::installedPlugins(/* populate */ false); 202 203 Vector<String> paths; 204 String qtPath(qgetenv("QTWEBKIT_PLUGIN_PATH").data()); 205 qtPath.split(UChar(':'), /* allowEmptyEntries */ false, paths); 206 207 db->setPluginDirectories(paths); 208 db->refresh(); 209} 210 211void DumpRenderTreeSupportQt::setDumpRenderTreeModeEnabled(bool b) 212{ 213 QWebPageAdapter::drtRun = b; 214#if ENABLE(NETSCAPE_PLUGIN_API) && defined(XP_UNIX) 215 // PluginViewQt (X11) needs a few workarounds when running under DRT 216 PluginView::setIsRunningUnderDRT(b); 217#endif 218} 219 220void DumpRenderTreeSupportQt::setFrameFlatteningEnabled(QWebPageAdapter* adapter, bool enabled) 221{ 222 adapter->page->settings()->setFrameFlatteningEnabled(enabled); 223} 224 225void DumpRenderTreeSupportQt::webPageSetGroupName(QWebPageAdapter *adapter, const QString& groupName) 226{ 227 adapter->page->setGroupName(groupName); 228} 229 230QString DumpRenderTreeSupportQt::webPageGroupName(QWebPageAdapter* adapter) 231{ 232 return adapter->page->groupName(); 233} 234 235void DumpRenderTreeSupportQt::webInspectorExecuteScript(QWebPageAdapter* adapter, long callId, const QString& script) 236{ 237#if ENABLE(INSPECTOR) 238 if (!adapter->page->inspectorController()) 239 return; 240 adapter->page->inspectorController()->evaluateForTestInFrontend(callId, script); 241#endif 242} 243 244void DumpRenderTreeSupportQt::webInspectorShow(QWebPageAdapter* adapter) 245{ 246#if ENABLE(INSPECTOR) 247 if (!adapter->page->inspectorController()) 248 return; 249 adapter->page->inspectorController()->show(); 250#endif 251} 252 253void DumpRenderTreeSupportQt::webInspectorClose(QWebPageAdapter* adapter) 254{ 255#if ENABLE(INSPECTOR) 256 if (!adapter->page->inspectorController()) 257 return; 258 adapter->page->inspectorController()->close(); 259#endif 260} 261 262bool DumpRenderTreeSupportQt::hasDocumentElement(QWebFrameAdapter *adapter) 263{ 264 return adapter->frame->document()->documentElement(); 265} 266 267void DumpRenderTreeSupportQt::setValueForUser(const QWebElement& element, const QString& value) 268{ 269 WebCore::Element* webElement = element.m_element; 270 if (!webElement) 271 return; 272 HTMLInputElement* inputElement = webElement->toInputElement(); 273 if (!inputElement) 274 return; 275 276 inputElement->setValueForUser(value); 277} 278 279void DumpRenderTreeSupportQt::clearFrameName(QWebFrameAdapter *adapter) 280{ 281 Frame* coreFrame = adapter->frame; 282 coreFrame->tree()->clearName(); 283} 284 285int DumpRenderTreeSupportQt::javaScriptObjectsCount() 286{ 287 return JSDOMWindowBase::commonVM()->heap.globalObjectCount(); 288} 289 290void DumpRenderTreeSupportQt::garbageCollectorCollect() 291{ 292 gcController().garbageCollectNow(); 293} 294 295void DumpRenderTreeSupportQt::garbageCollectorCollectOnAlternateThread(bool waitUntilDone) 296{ 297 gcController().garbageCollectOnAlternateThreadForDebugging(waitUntilDone); 298} 299 300void DumpRenderTreeSupportQt::whiteListAccessFromOrigin(const QString& sourceOrigin, const QString& destinationProtocol, const QString& destinationHost, bool allowDestinationSubdomains) 301{ 302 SecurityPolicy::addOriginAccessWhitelistEntry(*SecurityOrigin::createFromString(sourceOrigin), destinationProtocol, destinationHost, allowDestinationSubdomains); 303} 304 305void DumpRenderTreeSupportQt::removeWhiteListAccessFromOrigin(const QString& sourceOrigin, const QString& destinationProtocol, const QString& destinationHost, bool allowDestinationSubdomains) 306{ 307 SecurityPolicy::removeOriginAccessWhitelistEntry(*SecurityOrigin::createFromString(sourceOrigin), destinationProtocol, destinationHost, allowDestinationSubdomains); 308} 309 310void DumpRenderTreeSupportQt::resetOriginAccessWhiteLists() 311{ 312 SecurityPolicy::resetOriginAccessWhitelists(); 313} 314 315void DumpRenderTreeSupportQt::setDomainRelaxationForbiddenForURLScheme(bool forbidden, const QString& scheme) 316{ 317 SchemeRegistry::setDomainRelaxationForbiddenForURLScheme(forbidden, scheme); 318} 319 320void DumpRenderTreeSupportQt::setCaretBrowsingEnabled(QWebPageAdapter* adapter, bool value) 321{ 322 adapter->page->settings()->setCaretBrowsingEnabled(value); 323} 324 325void DumpRenderTreeSupportQt::setAuthorAndUserStylesEnabled(QWebPageAdapter* adapter, bool value) 326{ 327 adapter->page->settings()->setAuthorAndUserStylesEnabled(value); 328} 329 330void DumpRenderTreeSupportQt::executeCoreCommandByName(QWebPageAdapter* adapter, const QString& name, const QString& value) 331{ 332 adapter->page->focusController()->focusedOrMainFrame()->editor().command(name).execute(value); 333} 334 335bool DumpRenderTreeSupportQt::isCommandEnabled(QWebPageAdapter *adapter, const QString& name) 336{ 337 return adapter->page->focusController()->focusedOrMainFrame()->editor().command(name).isEnabled(); 338} 339 340QVariantList DumpRenderTreeSupportQt::selectedRange(QWebPageAdapter *adapter) 341{ 342 WebCore::Frame* frame = adapter->page->focusController()->focusedOrMainFrame(); 343 QVariantList selectedRange; 344 RefPtr<Range> range = frame->selection()->toNormalizedRange().get(); 345 346 Element* selectionRoot = frame->selection()->rootEditableElement(); 347 Element* scope = selectionRoot ? selectionRoot : frame->document()->documentElement(); 348 349 RefPtr<Range> testRange = Range::create(scope->document(), scope, 0, range->startContainer(), range->startOffset()); 350 ASSERT(testRange->startContainer() == scope); 351 int startPosition = TextIterator::rangeLength(testRange.get()); 352 353 ExceptionCode ec; 354 testRange->setEnd(range->endContainer(), range->endOffset(), ec); 355 ASSERT(testRange->startContainer() == scope); 356 int endPosition = TextIterator::rangeLength(testRange.get()); 357 358 selectedRange << startPosition << (endPosition - startPosition); 359 360 return selectedRange; 361 362} 363 364QVariantList DumpRenderTreeSupportQt::firstRectForCharacterRange(QWebPageAdapter *adapter, int location, int length) 365{ 366 WebCore::Frame* frame = adapter->page->focusController()->focusedOrMainFrame(); 367 QVariantList rect; 368 369 if ((location + length < location) && (location + length)) 370 length = 0; 371 372 RefPtr<Range> range = TextIterator::rangeFromLocationAndLength(frame->selection()->rootEditableElementOrDocumentElement(), location, length); 373 374 if (!range) 375 return QVariantList(); 376 377 QRect resultRect = frame->editor().firstRectForRange(range.get()); 378 rect << resultRect.x() << resultRect.y() << resultRect.width() << resultRect.height(); 379 return rect; 380} 381 382void DumpRenderTreeSupportQt::setWindowsBehaviorAsEditingBehavior(QWebPageAdapter* adapter) 383{ 384 Page* corePage = adapter->page; 385 if (!corePage) 386 return; 387 corePage->settings()->setEditingBehaviorType(EditingWindowsBehavior); 388} 389 390void DumpRenderTreeSupportQt::clearAllApplicationCaches() 391{ 392 WebCore::cacheStorage().empty(); 393 WebCore::cacheStorage().vacuumDatabaseFile(); 394} 395 396void DumpRenderTreeSupportQt::dumpFrameLoader(bool b) 397{ 398 FrameLoaderClientQt::dumpFrameLoaderCallbacks = b; 399} 400 401void DumpRenderTreeSupportQt::dumpProgressFinishedCallback(bool b) 402{ 403 FrameLoaderClientQt::dumpProgressFinishedCallback = b; 404} 405 406void DumpRenderTreeSupportQt::dumpUserGestureInFrameLoader(bool b) 407{ 408 FrameLoaderClientQt::dumpUserGestureInFrameLoaderCallbacks = b; 409} 410 411void DumpRenderTreeSupportQt::dumpResourceLoadCallbacks(bool b) 412{ 413 FrameLoaderClientQt::dumpResourceLoadCallbacks = b; 414} 415 416void DumpRenderTreeSupportQt::dumpResourceLoadCallbacksPath(const QString& path) 417{ 418 FrameLoaderClientQt::dumpResourceLoadCallbacksPath = path; 419} 420 421void DumpRenderTreeSupportQt::dumpResourceResponseMIMETypes(bool b) 422{ 423 FrameLoaderClientQt::dumpResourceResponseMIMETypes = b; 424} 425 426void DumpRenderTreeSupportQt::dumpWillCacheResponseCallbacks(bool b) 427{ 428 FrameLoaderClientQt::dumpWillCacheResponseCallbacks = b; 429} 430 431void DumpRenderTreeSupportQt::setWillSendRequestReturnsNullOnRedirect(bool b) 432{ 433 FrameLoaderClientQt::sendRequestReturnsNullOnRedirect = b; 434} 435 436void DumpRenderTreeSupportQt::setWillSendRequestReturnsNull(bool b) 437{ 438 FrameLoaderClientQt::sendRequestReturnsNull = b; 439} 440 441void DumpRenderTreeSupportQt::setWillSendRequestClearHeaders(const QStringList& headers) 442{ 443 FrameLoaderClientQt::sendRequestClearHeaders = headers; 444} 445 446void DumpRenderTreeSupportQt::setDeferMainResourceDataLoad(bool b) 447{ 448 FrameLoaderClientQt::deferMainResourceDataLoad = b; 449} 450 451void DumpRenderTreeSupportQt::setCustomPolicyDelegate(bool enabled, bool permissive) 452{ 453 FrameLoaderClientQt::policyDelegateEnabled = enabled; 454 FrameLoaderClientQt::policyDelegatePermissive = permissive; 455} 456 457void DumpRenderTreeSupportQt::dumpHistoryCallbacks(bool b) 458{ 459 FrameLoaderClientQt::dumpHistoryCallbacks = b; 460} 461 462void DumpRenderTreeSupportQt::dumpVisitedLinksCallbacks(bool b) 463{ 464 ChromeClientQt::dumpVisitedLinksCallbacks = b; 465} 466 467void DumpRenderTreeSupportQt::dumpEditingCallbacks(bool b) 468{ 469 EditorClientQt::dumpEditingCallbacks = b; 470} 471 472void DumpRenderTreeSupportQt::dumpSetAcceptsEditing(bool b) 473{ 474 EditorClientQt::acceptsEditing = b; 475} 476 477void DumpRenderTreeSupportQt::dumpNotification(bool b) 478{ 479#if ENABLE(NOTIFICATIONS) || ENABLE(LEGACY_NOTIFICATIONS) 480 NotificationPresenterClientQt::dumpNotification = b; 481#endif 482} 483 484QString DumpRenderTreeSupportQt::viewportAsText(QWebPageAdapter* adapter, int deviceDPI, const QSize& deviceSize, const QSize& availableSize) 485{ 486 WebCore::ViewportArguments args = adapter->viewportArguments(); 487 488 float devicePixelRatio = deviceDPI / WebCore::ViewportArguments::deprecatedTargetDPI; 489 WebCore::ViewportAttributes conf = WebCore::computeViewportAttributes(args, 490 /* desktop-width */980, 491 /* device-width */deviceSize.width(), 492 /* device-height */deviceSize.height(), 493 devicePixelRatio, 494 availableSize); 495 WebCore::restrictMinimumScaleFactorToViewportSize(conf, availableSize, devicePixelRatio); 496 WebCore::restrictScaleFactorToInitialScaleIfNotUserScalable(conf); 497 498 QString res; 499 res = res.sprintf("viewport size %dx%d scale %f with limits [%f, %f] and userScalable %f\n", 500 static_cast<int>(conf.layoutSize.width()), 501 static_cast<int>(conf.layoutSize.height()), 502 conf.initialScale, 503 conf.minimumScale, 504 conf.maximumScale, 505 conf.userScalable); 506 507 return res; 508} 509 510void DumpRenderTreeSupportQt::scalePageBy(QWebFrameAdapter* adapter, float scalefactor, const QPoint& origin) 511{ 512 WebCore::Frame* coreFrame = adapter->frame; 513 if (Page* page = coreFrame->page()) 514 page->setPageScaleFactor(scalefactor, origin); 515} 516 517void DumpRenderTreeSupportQt::setMockDeviceOrientation(QWebPageAdapter* adapter, bool canProvideAlpha, double alpha, bool canProvideBeta, double beta, bool canProvideGamma, double gamma) 518{ 519#if ENABLE(DEVICE_ORIENTATION) 520 Page* corePage = adapter->page; 521 DeviceOrientationClientMock* mockClient = toDeviceOrientationClientMock(DeviceOrientationController::from(corePage)->deviceOrientationClient()); 522 mockClient->setOrientation(DeviceOrientationData::create(canProvideAlpha, alpha, canProvideBeta, beta, canProvideGamma, gamma)); 523#endif 524} 525 526void DumpRenderTreeSupportQt::resetGeolocationMock(QWebPageAdapter* adapter) 527{ 528#if ENABLE(GEOLOCATION) 529 Page* corePage = adapter->page; 530 GeolocationClientMock* mockClient = toGeolocationClientMock(GeolocationController::from(corePage)->client()); 531 mockClient->reset(); 532#endif 533} 534 535void DumpRenderTreeSupportQt::setMockGeolocationPermission(QWebPageAdapter* adapter, bool allowed) 536{ 537#if ENABLE(GEOLOCATION) 538 Page* corePage = adapter->page; 539 GeolocationClientMock* mockClient = toGeolocationClientMock(GeolocationController::from(corePage)->client()); 540 mockClient->setPermission(allowed); 541#endif 542} 543 544void DumpRenderTreeSupportQt::setMockGeolocationPosition(QWebPageAdapter* adapter, double latitude, double longitude, double accuracy) 545{ 546#if ENABLE(GEOLOCATION) 547 Page* corePage = adapter->page; 548 GeolocationClientMock* mockClient = toGeolocationClientMock(GeolocationController::from(corePage)->client()); 549 mockClient->setPosition(GeolocationPosition::create(currentTime(), latitude, longitude, accuracy)); 550#endif 551} 552 553void DumpRenderTreeSupportQt::setMockGeolocationPositionUnavailableError(QWebPageAdapter* adapter, const QString& message) 554{ 555#if ENABLE(GEOLOCATION) 556 Page* corePage = adapter->page; 557 GeolocationClientMock* mockClient = static_cast<GeolocationClientMock*>(GeolocationController::from(corePage)->client()); 558 mockClient->setPositionUnavailableError(message); 559#endif 560} 561 562int DumpRenderTreeSupportQt::numberOfPendingGeolocationPermissionRequests(QWebPageAdapter* adapter) 563{ 564#if ENABLE(GEOLOCATION) 565 Page* corePage = adapter->page; 566 GeolocationClientMock* mockClient = toGeolocationClientMock(GeolocationController::from(corePage)->client()); 567 return mockClient->numberOfPendingPermissionRequests(); 568#else 569 return -1; 570#endif 571} 572 573bool DumpRenderTreeSupportQt::isTargetItem(const QWebHistoryItem& historyItem) 574{ 575 QWebHistoryItem it = historyItem; 576 if (QWebHistoryItemPrivate::core(&it)->isTargetItem()) 577 return true; 578 return false; 579} 580 581QString DumpRenderTreeSupportQt::historyItemTarget(const QWebHistoryItem& historyItem) 582{ 583 QWebHistoryItem it = historyItem; 584 return (QWebHistoryItemPrivate::core(&it)->target()); 585} 586 587QMap<QString, QWebHistoryItem> DumpRenderTreeSupportQt::getChildHistoryItems(const QWebHistoryItem& historyItem) 588{ 589 QWebHistoryItem it = historyItem; 590 HistoryItem* item = QWebHistoryItemPrivate::core(&it); 591 const WebCore::HistoryItemVector& children = item->children(); 592 593 unsigned size = children.size(); 594 QMap<QString, QWebHistoryItem> kids; 595 for (unsigned i = 0; i < size; ++i) { 596 QWebHistoryItem kid(new QWebHistoryItemPrivate(children[i].get())); 597 kids.insert(DumpRenderTreeSupportQt::historyItemTarget(kid), kid); 598 } 599 return kids; 600} 601 602bool DumpRenderTreeSupportQt::shouldClose(QWebFrameAdapter *adapter) 603{ 604 WebCore::Frame* coreFrame = adapter->frame; 605 return coreFrame->loader()->shouldClose(); 606} 607 608void DumpRenderTreeSupportQt::clearScriptWorlds() 609{ 610 m_worldMap.clear(); 611} 612 613void DumpRenderTreeSupportQt::evaluateScriptInIsolatedWorld(QWebFrameAdapter *adapter, int worldID, const QString& script) 614{ 615 QWebScriptWorld* scriptWorld; 616 if (!worldID) { 617 scriptWorld = new QWebScriptWorld(); 618 } else if (!m_worldMap.contains(worldID)) { 619 scriptWorld = new QWebScriptWorld(); 620 m_worldMap.insert(worldID, scriptWorld); 621 } else 622 scriptWorld = m_worldMap.value(worldID); 623 624 WebCore::Frame* coreFrame = adapter->frame; 625 626 ScriptController* proxy = coreFrame->script(); 627 628 if (!proxy) 629 return; 630 proxy->executeScriptInWorld(scriptWorld->world(), script, true); 631} 632 633void DumpRenderTreeSupportQt::addUserStyleSheet(QWebPageAdapter* adapter, const QString& sourceCode) 634{ 635 adapter->page->group().addUserStyleSheetToWorld(mainThreadNormalWorld(), sourceCode, QUrl(), Vector<String>(), Vector<String>(), WebCore::InjectInAllFrames); 636} 637 638void DumpRenderTreeSupportQt::removeUserStyleSheets(QWebPageAdapter* adapter) 639{ 640 adapter->page->group().removeUserStyleSheetsFromWorld(mainThreadNormalWorld()); 641} 642 643void DumpRenderTreeSupportQt::simulateDesktopNotificationClick(const QString& title) 644{ 645#if ENABLE(NOTIFICATIONS) || ENABLE(LEGACY_NOTIFICATIONS) 646 NotificationPresenterClientQt::notificationPresenter()->notificationClicked(title); 647#endif 648} 649 650void DumpRenderTreeSupportQt::setDefersLoading(QWebPageAdapter* adapter, bool flag) 651{ 652 Page* corePage = adapter->page; 653 if (corePage) 654 corePage->setDefersLoading(flag); 655} 656 657void DumpRenderTreeSupportQt::goBack(QWebPageAdapter* adapter) 658{ 659 Page* corePage = adapter->page; 660 if (corePage) 661 corePage->goBack(); 662} 663 664// API Candidate? 665QString DumpRenderTreeSupportQt::responseMimeType(QWebFrameAdapter* adapter) 666{ 667 WebCore::Frame* coreFrame = adapter->frame; 668 WebCore::DocumentLoader* docLoader = coreFrame->loader()->documentLoader(); 669 return docLoader->responseMIMEType(); 670} 671 672void DumpRenderTreeSupportQt::clearOpener(QWebFrameAdapter* adapter) 673{ 674 WebCore::Frame* coreFrame = adapter->frame; 675 coreFrame->loader()->setOpener(0); 676} 677 678void DumpRenderTreeSupportQt::addURLToRedirect(const QString& origin, const QString& destination) 679{ 680 FrameLoaderClientQt::URLsToRedirect[origin] = destination; 681} 682 683void DumpRenderTreeSupportQt::setInteractiveFormValidationEnabled(QWebPageAdapter* adapter, bool enable) 684{ 685 Page* corePage = adapter->page; 686 if (corePage) 687 corePage->settings()->setInteractiveFormValidationEnabled(enable); 688} 689 690QStringList DumpRenderTreeSupportQt::contextMenu(QWebPageAdapter* page) 691{ 692 return page->menuActionsAsText(); 693} 694 695bool DumpRenderTreeSupportQt::thirdPartyCookiePolicyAllows(QWebPageAdapter *adapter, const QUrl& url, const QUrl& firstPartyUrl) 696{ 697 Page* corePage = adapter->page; 698 return thirdPartyCookiePolicyPermits(corePage->mainFrame()->loader()->networkingContext(), url, firstPartyUrl); 699} 700 701void DumpRenderTreeSupportQt::enableMockScrollbars() 702{ 703 Settings::setMockScrollbarsEnabled(true); 704} 705 706QUrl DumpRenderTreeSupportQt::mediaContentUrlByElementId(QWebFrameAdapter* adapter, const QString& elementId) 707{ 708 QUrl res; 709 710#if ENABLE(VIDEO) && USE(QT_MULTIMEDIA) 711 Frame* coreFrame = adapter->frame; 712 if (!coreFrame) 713 return res; 714 715 Document* doc = coreFrame->document(); 716 if (!doc) 717 return res; 718 719 Node* coreNode = doc->getElementById(elementId); 720 if (!coreNode) 721 return res; 722 723 HTMLVideoElement* videoElement = static_cast<HTMLVideoElement*>(coreNode); 724 PlatformMedia platformMedia = videoElement->platformMedia(); 725 if (platformMedia.type != PlatformMedia::QtMediaPlayerType) 726 return res; 727 728 MediaPlayerPrivateQt* mediaPlayerQt = static_cast<MediaPlayerPrivateQt*>(platformMedia.media.qtMediaPlayer); 729 if (mediaPlayerQt && mediaPlayerQt->mediaPlayer()) 730 res = mediaPlayerQt->mediaPlayer()->media().canonicalUrl(); 731#endif 732 733 return res; 734} 735 736// API Candidate? 737void DumpRenderTreeSupportQt::setAlternateHtml(QWebFrameAdapter* adapter, const QString& html, const QUrl& baseUrl, const QUrl& failingUrl) 738{ 739 KURL kurl(baseUrl); 740 WebCore::Frame* coreFrame = adapter->frame; 741 WebCore::ResourceRequest request(kurl); 742 const QByteArray utf8 = html.toUtf8(); 743 WTF::RefPtr<WebCore::SharedBuffer> data = WebCore::SharedBuffer::create(utf8.constData(), utf8.length()); 744 WebCore::SubstituteData substituteData(data, WTF::String("text/html"), WTF::String("utf-8"), failingUrl); 745 coreFrame->loader()->load(WebCore::FrameLoadRequest(coreFrame, request, substituteData)); 746} 747 748void DumpRenderTreeSupportQt::confirmComposition(QWebPageAdapter *adapter, const char* text) 749{ 750 Frame* frame = adapter->page->focusController()->focusedOrMainFrame(); 751 if (!frame) 752 return; 753 754 Editor& editor = frame->editor(); 755 if (!editor.hasComposition() && !text) 756 return; 757 758 if (editor.hasComposition()) { 759 if (text) 760 editor.confirmComposition(String::fromUTF8(text)); 761 else 762 editor.confirmComposition(); 763 } else 764 editor.insertText(String::fromUTF8(text), 0); 765} 766 767void DumpRenderTreeSupportQt::injectInternalsObject(QWebFrameAdapter* adapter) 768{ 769 WebCore::Frame* coreFrame = adapter->frame; 770 JSDOMWindow* window = toJSDOMWindow(coreFrame, mainThreadNormalWorld()); 771 Q_ASSERT(window); 772 773 JSC::ExecState* exec = window->globalExec(); 774 Q_ASSERT(exec); 775 JSC::JSLockHolder lock(exec); 776 777 JSContextRef context = toRef(exec); 778 WebCoreTestSupport::injectInternalsObject(context); 779} 780 781void DumpRenderTreeSupportQt::injectInternalsObject(JSContextRef context) 782{ 783 WebCoreTestSupport::injectInternalsObject(context); 784} 785 786void DumpRenderTreeSupportQt::resetInternalsObject(QWebFrameAdapter* adapter) 787{ 788 WebCore::Frame* coreFrame = adapter->frame; 789 JSDOMWindow* window = toJSDOMWindow(coreFrame, mainThreadNormalWorld()); 790 Q_ASSERT(window); 791 792 JSC::ExecState* exec = window->globalExec(); 793 Q_ASSERT(exec); 794 JSC::JSLockHolder lock(exec); 795 796 JSContextRef context = toRef(exec); 797 WebCoreTestSupport::resetInternalsObject(context); 798} 799 800void DumpRenderTreeSupportQt::resetInternalsObject(JSContextRef context) 801{ 802 WebCoreTestSupport::resetInternalsObject(context); 803} 804 805QImage DumpRenderTreeSupportQt::paintPagesWithBoundaries(QWebFrameAdapter* adapter) 806{ 807 Frame* frame = adapter->frame; 808 PrintContext printContext(frame); 809 810 QRect rect = frame->view()->frameRect(); 811 812 IntRect pageRect(0, 0, rect.width(), rect.height()); 813 814 printContext.begin(pageRect.width(), pageRect.height()); 815 float pageHeight = 0; 816 printContext.computePageRects(pageRect, /* headerHeight */ 0, /* footerHeight */ 0, /* userScaleFactor */ 1.0, pageHeight); 817 818 QPainter painter; 819 int pageCount = printContext.pageCount(); 820 // pages * pageHeight and 1px line between each page 821 int totalHeight = pageCount * (pageRect.height() + 1) - 1; 822 QImage image(pageRect.width(), totalHeight, QImage::Format_ARGB32); 823 image.fill(Qt::white); 824 painter.begin(&image); 825 826 GraphicsContext ctx(&painter); 827 for (int i = 0; i < printContext.pageCount(); ++i) { 828 printContext.spoolPage(ctx, i, pageRect.width()); 829 // translate to next page coordinates 830 ctx.translate(0, pageRect.height() + 1); 831 832 // if there is a next page, draw a blue line between these two 833 if (i + 1 < printContext.pageCount()) { 834 ctx.save(); 835 ctx.setStrokeColor(Color(0, 0, 255), ColorSpaceDeviceRGB); 836 ctx.setFillColor(Color(0, 0, 255), ColorSpaceDeviceRGB); 837 ctx.drawLine(IntPoint(0, -1), IntPoint(pageRect.width(), -1)); 838 ctx.restore(); 839 } 840 } 841 842 painter.end(); 843 printContext.end(); 844 845 return image; 846} 847 848void DumpRenderTreeSupportQt::setTrackRepaintRects(QWebFrameAdapter* adapter, bool enable) 849{ 850 adapter->frame->view()->setTracksRepaints(enable); 851} 852 853bool DumpRenderTreeSupportQt::trackRepaintRects(QWebFrameAdapter* adapter) 854{ 855 return adapter->frame->view()->isTrackingRepaints(); 856} 857 858void DumpRenderTreeSupportQt::getTrackedRepaintRects(QWebFrameAdapter* adapter, QVector<QRect>& result) 859{ 860 Frame* coreFrame = adapter->frame; 861 const Vector<IntRect>& rects = coreFrame->view()->trackedRepaintRects(); 862 result.resize(rects.size()); 863 for (size_t i = 0; i < rects.size(); ++i) 864 result.append(rects[i]); 865} 866 867void DumpRenderTreeSupportQt::setSeamlessIFramesEnabled(bool enabled) 868{ 869#if ENABLE(IFRAME_SEAMLESS) 870 WebCore::RuntimeEnabledFeatures::setSeamlessIFramesEnabled(enabled); 871#else 872 UNUSED_PARAM(enabled); 873#endif 874} 875 876void DumpRenderTreeSupportQt::setShouldUseFontSmoothing(bool enabled) 877{ 878 WebCore::Font::setShouldUseSmoothing(enabled); 879} 880 881QString DumpRenderTreeSupportQt::frameRenderTreeDump(QWebFrameAdapter* adapter) 882{ 883 if (adapter->frame->view() && adapter->frame->view()->layoutPending()) 884 adapter->frame->view()->layout(); 885 886 return externalRepresentation(adapter->frame); 887} 888 889void DumpRenderTreeSupportQt::clearNotificationPermissions() 890{ 891#if ENABLE(NOTIFICATIONS) || ENABLE(LEGACY_NOTIFICATIONS) 892 WebCore::NotificationPresenterClientQt::notificationPresenter()->clearCachedPermissions(); 893#endif 894} 895 896void DumpRenderTreeSupportQt::disableDefaultTypesettingFeatures() 897{ 898 WebCore::Font::setDefaultTypesettingFeatures(0); 899} 900 901void DumpRenderTreeSupportQt::getJSWindowObject(QWebFrameAdapter* adapter, JSContextRef* context, JSObjectRef* object) 902{ 903 JSDOMWindow* window = toJSDOMWindow(adapter->frame, mainThreadNormalWorld()); 904 *object = toRef(window); 905 *context = toRef(window->globalExec()); 906} 907