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 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 "ApplicationCacheStorage.h" 27#include "CSSComputedStyleDeclaration.h" 28#include "ChromeClientQt.h" 29#include "ContainerNode.h" 30#include "ContextMenu.h" 31#include "ContextMenuClientQt.h" 32#include "ContextMenuController.h" 33#include "DeviceOrientation.h" 34#include "DeviceOrientationClientMockQt.h" 35#include "DocumentLoader.h" 36#include "Editor.h" 37#include "EditorClientQt.h" 38#include "Element.h" 39#include "FocusController.h" 40#include "Frame.h" 41#include "FrameLoaderClientQt.h" 42#include "FrameView.h" 43#if USE(JSC) 44#include "GCController.h" 45#elif USE(V8) 46#include "V8GCController.h" 47#include "V8Proxy.h" 48#endif 49#include "GeolocationClient.h" 50#include "GeolocationClientMock.h" 51#include "GeolocationController.h" 52#include "GeolocationError.h" 53#include "GeolocationPosition.h" 54#include "HistoryItem.h" 55#include "HTMLInputElement.h" 56#include "InspectorController.h" 57#include "NodeList.h" 58#include "NotificationPresenterClientQt.h" 59#include "Page.h" 60#include "PageGroup.h" 61#include "PluginDatabase.h" 62#include "PositionError.h" 63#include "PrintContext.h" 64#include "RenderListItem.h" 65#include "RenderTreeAsText.h" 66#include "ScriptController.h" 67#include "SecurityOrigin.h" 68#include "Settings.h" 69#if ENABLE(SVG) 70#include "SVGDocumentExtensions.h" 71#include "SVGSMILElement.h" 72#endif 73#include "TextIterator.h" 74#include "WorkerThread.h" 75#include <wtf/CurrentTime.h> 76 77#include "qwebelement.h" 78#include "qwebframe.h" 79#include "qwebframe_p.h" 80#include "qwebhistory.h" 81#include "qwebhistory_p.h" 82#include "qwebpage.h" 83#include "qwebpage_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 91using namespace WebCore; 92 93QMap<int, QWebScriptWorld*> m_worldMap; 94 95#if ENABLE(CLIENT_BASED_GEOLOCATION) 96GeolocationClientMock* toGeolocationClientMock(GeolocationClient* client) 97{ 98 ASSERT(QWebPagePrivate::drtRun); 99 return static_cast<GeolocationClientMock*>(client); 100} 101#endif 102 103QDRTNode::QDRTNode() 104 : m_node(0) 105{ 106} 107 108QDRTNode::QDRTNode(WebCore::Node* node) 109 : m_node(0) 110{ 111 if (node) { 112 m_node = node; 113 m_node->ref(); 114 } 115} 116 117QDRTNode::~QDRTNode() 118{ 119 if (m_node) 120 m_node->deref(); 121} 122 123QDRTNode::QDRTNode(const QDRTNode& other) 124 :m_node(other.m_node) 125{ 126 if (m_node) 127 m_node->ref(); 128} 129 130QDRTNode& QDRTNode::operator=(const QDRTNode& other) 131{ 132 if (this != &other) { 133 Node* otherNode = other.m_node; 134 if (otherNode) 135 otherNode->ref(); 136 if (m_node) 137 m_node->deref(); 138 m_node = otherNode; 139 } 140 return *this; 141} 142 143 144DumpRenderTreeSupportQt::DumpRenderTreeSupportQt() 145{ 146} 147 148DumpRenderTreeSupportQt::~DumpRenderTreeSupportQt() 149{ 150} 151 152void DumpRenderTreeSupportQt::overwritePluginDirectories() 153{ 154 PluginDatabase* db = PluginDatabase::installedPlugins(/* populate */ false); 155 156 Vector<String> paths; 157 String qtPath(qgetenv("QTWEBKIT_PLUGIN_PATH").data()); 158 qtPath.split(UChar(':'), /* allowEmptyEntries */ false, paths); 159 160 db->setPluginDirectories(paths); 161 db->refresh(); 162} 163 164int DumpRenderTreeSupportQt::workerThreadCount() 165{ 166#if ENABLE(WORKERS) 167 return WebCore::WorkerThread::workerThreadCount(); 168#else 169 return 0; 170#endif 171} 172 173void DumpRenderTreeSupportQt::setDumpRenderTreeModeEnabled(bool b) 174{ 175 QWebPagePrivate::drtRun = b; 176} 177 178void DumpRenderTreeSupportQt::setFrameFlatteningEnabled(QWebPage* page, bool enabled) 179{ 180 QWebPagePrivate::core(page)->settings()->setFrameFlatteningEnabled(enabled); 181} 182 183void DumpRenderTreeSupportQt::webPageSetGroupName(QWebPage* page, const QString& groupName) 184{ 185 page->handle()->page->setGroupName(groupName); 186} 187 188QString DumpRenderTreeSupportQt::webPageGroupName(QWebPage* page) 189{ 190 return page->handle()->page->groupName(); 191} 192 193void DumpRenderTreeSupportQt::webInspectorExecuteScript(QWebPage* page, long callId, const QString& script) 194{ 195#if ENABLE(INSPECTOR) 196 if (!page->handle()->page->inspectorController()) 197 return; 198 page->handle()->page->inspectorController()->evaluateForTestInFrontend(callId, script); 199#endif 200} 201 202void DumpRenderTreeSupportQt::webInspectorClose(QWebPage* page) 203{ 204#if ENABLE(INSPECTOR) 205 if (!page->handle()->page->inspectorController()) 206 return; 207 page->handle()->page->inspectorController()->close(); 208#endif 209} 210 211void DumpRenderTreeSupportQt::webInspectorShow(QWebPage* page) 212{ 213#if ENABLE(INSPECTOR) 214 if (!page->handle()->page->inspectorController()) 215 return; 216 page->handle()->page->inspectorController()->show(); 217#endif 218} 219 220void DumpRenderTreeSupportQt::setTimelineProfilingEnabled(QWebPage* page, bool enabled) 221{ 222#if ENABLE(INSPECTOR) 223 InspectorController* controller = page->handle()->page->inspectorController(); 224 if (!controller) 225 return; 226 if (enabled) 227 controller->startTimelineProfiler(); 228 else 229 controller->stopTimelineProfiler(); 230#endif 231} 232 233bool DumpRenderTreeSupportQt::hasDocumentElement(QWebFrame* frame) 234{ 235 return QWebFramePrivate::core(frame)->document()->documentElement(); 236} 237 238void DumpRenderTreeSupportQt::setJavaScriptProfilingEnabled(QWebFrame* frame, bool enabled) 239{ 240#if ENABLE(JAVASCRIPT_DEBUGGER) && ENABLE(INSPECTOR) 241 Frame* coreFrame = QWebFramePrivate::core(frame); 242 InspectorController* controller = coreFrame->page()->inspectorController(); 243 if (!controller) 244 return; 245 if (enabled) 246 controller->enableProfiler(); 247 else 248 controller->disableProfiler(); 249#endif 250} 251 252// Pause a given CSS animation or transition on the target node at a specific time. 253// If the animation or transition is already paused, it will update its pause time. 254// This method is only intended to be used for testing the CSS animation and transition system. 255bool DumpRenderTreeSupportQt::pauseAnimation(QWebFrame *frame, const QString &animationName, double time, const QString &elementId) 256{ 257 Frame* coreFrame = QWebFramePrivate::core(frame); 258 if (!coreFrame) 259 return false; 260 261 AnimationController* controller = coreFrame->animation(); 262 if (!controller) 263 return false; 264 265 Document* doc = coreFrame->document(); 266 Q_ASSERT(doc); 267 268 Node* coreNode = doc->getElementById(elementId); 269 if (!coreNode || !coreNode->renderer()) 270 return false; 271 272 return controller->pauseAnimationAtTime(coreNode->renderer(), animationName, time); 273} 274 275bool DumpRenderTreeSupportQt::pauseTransitionOfProperty(QWebFrame *frame, const QString &propertyName, double time, const QString &elementId) 276{ 277 Frame* coreFrame = QWebFramePrivate::core(frame); 278 if (!coreFrame) 279 return false; 280 281 AnimationController* controller = coreFrame->animation(); 282 if (!controller) 283 return false; 284 285 Document* doc = coreFrame->document(); 286 Q_ASSERT(doc); 287 288 Node* coreNode = doc->getElementById(elementId); 289 if (!coreNode || !coreNode->renderer()) 290 return false; 291 292 return controller->pauseTransitionAtTime(coreNode->renderer(), propertyName, time); 293} 294 295// Pause a given SVG animation on the target node at a specific time. 296// This method is only intended to be used for testing the SVG animation system. 297bool DumpRenderTreeSupportQt::pauseSVGAnimation(QWebFrame *frame, const QString &animationId, double time, const QString &elementId) 298{ 299#if !ENABLE(SVG) 300 return false; 301#else 302 Frame* coreFrame = QWebFramePrivate::core(frame); 303 if (!coreFrame) 304 return false; 305 306 Document* doc = coreFrame->document(); 307 Q_ASSERT(doc); 308 309 if (!doc->svgExtensions()) 310 return false; 311 312 Node* coreNode = doc->getElementById(animationId); 313 if (!coreNode || !SVGSMILElement::isSMILElement(coreNode)) 314 return false; 315 316 return doc->accessSVGExtensions()->sampleAnimationAtTime(elementId, static_cast<SVGSMILElement*>(coreNode), time); 317#endif 318} 319 320// Returns the total number of currently running animations (includes both CSS transitions and CSS animations). 321int DumpRenderTreeSupportQt::numberOfActiveAnimations(QWebFrame *frame) 322{ 323 Frame* coreFrame = QWebFramePrivate::core(frame); 324 if (!coreFrame) 325 return false; 326 327 AnimationController* controller = coreFrame->animation(); 328 if (!controller) 329 return false; 330 331 return controller->numberOfActiveAnimations(); 332} 333 334void DumpRenderTreeSupportQt::suspendAnimations(QWebFrame *frame) 335{ 336 Frame* coreFrame = QWebFramePrivate::core(frame); 337 if (!coreFrame) 338 return; 339 340 AnimationController* controller = coreFrame->animation(); 341 if (!controller) 342 return; 343 344 controller->suspendAnimations(); 345} 346 347void DumpRenderTreeSupportQt::resumeAnimations(QWebFrame *frame) 348{ 349 Frame* coreFrame = QWebFramePrivate::core(frame); 350 if (!coreFrame) 351 return; 352 353 AnimationController* controller = coreFrame->animation(); 354 if (!controller) 355 return; 356 357 controller->resumeAnimations(); 358} 359 360void DumpRenderTreeSupportQt::clearFrameName(QWebFrame* frame) 361{ 362 Frame* coreFrame = QWebFramePrivate::core(frame); 363 coreFrame->tree()->clearName(); 364} 365 366int DumpRenderTreeSupportQt::javaScriptObjectsCount() 367{ 368#if USE(JSC) 369 return JSDOMWindowBase::commonJSGlobalData()->heap.globalObjectCount(); 370#elif USE(V8) 371 // FIXME: Find a way to do this using V8. 372 return 1; 373#endif 374} 375 376void DumpRenderTreeSupportQt::garbageCollectorCollect() 377{ 378#if USE(JSC) 379 gcController().garbageCollectNow(); 380#elif USE(V8) 381 v8::V8::LowMemoryNotification(); 382#endif 383} 384 385void DumpRenderTreeSupportQt::garbageCollectorCollectOnAlternateThread(bool waitUntilDone) 386{ 387#if USE(JSC) 388 gcController().garbageCollectOnAlternateThreadForDebugging(waitUntilDone); 389#elif USE(V8) 390 // FIXME: Find a way to do this using V8. 391 garbageCollectorCollect(); 392#endif 393} 394 395// Returns the value of counter in the element specified by \a id. 396QString DumpRenderTreeSupportQt::counterValueForElementById(QWebFrame* frame, const QString& id) 397{ 398 Frame* coreFrame = QWebFramePrivate::core(frame); 399 if (Document* document = coreFrame->document()) { 400 if (Element* element = document->getElementById(id)) 401 return WebCore::counterValueForElement(element); 402 } 403 return QString(); 404} 405 406int DumpRenderTreeSupportQt::pageNumberForElementById(QWebFrame* frame, const QString& id, float width, float height) 407{ 408 Frame* coreFrame = QWebFramePrivate::core(frame); 409 if (!coreFrame) 410 return -1; 411 412 Element* element = coreFrame->document()->getElementById(AtomicString(id)); 413 if (!element) 414 return -1; 415 416 return PrintContext::pageNumberForElement(element, FloatSize(width, height)); 417} 418 419int DumpRenderTreeSupportQt::numberOfPages(QWebFrame* frame, float width, float height) 420{ 421 Frame* coreFrame = QWebFramePrivate::core(frame); 422 if (!coreFrame) 423 return -1; 424 425 return PrintContext::numberOfPages(coreFrame, FloatSize(width, height)); 426} 427 428// Suspend active DOM objects in this frame. 429void DumpRenderTreeSupportQt::suspendActiveDOMObjects(QWebFrame* frame) 430{ 431 Frame* coreFrame = QWebFramePrivate::core(frame); 432 if (coreFrame->document()) 433 // FIXME: This function should be changed take a ReasonForSuspension parameter 434 // https://bugs.webkit.org/show_bug.cgi?id=45732 435 coreFrame->document()->suspendActiveDOMObjects(ActiveDOMObject::JavaScriptDebuggerPaused); 436} 437 438// Resume active DOM objects in this frame. 439void DumpRenderTreeSupportQt::resumeActiveDOMObjects(QWebFrame* frame) 440{ 441 Frame* coreFrame = QWebFramePrivate::core(frame); 442 if (coreFrame->document()) 443 coreFrame->document()->resumeActiveDOMObjects(); 444} 445 446void DumpRenderTreeSupportQt::whiteListAccessFromOrigin(const QString& sourceOrigin, const QString& destinationProtocol, const QString& destinationHost, bool allowDestinationSubdomains) 447{ 448 SecurityOrigin::addOriginAccessWhitelistEntry(*SecurityOrigin::createFromString(sourceOrigin), destinationProtocol, destinationHost, allowDestinationSubdomains); 449} 450 451void DumpRenderTreeSupportQt::removeWhiteListAccessFromOrigin(const QString& sourceOrigin, const QString& destinationProtocol, const QString& destinationHost, bool allowDestinationSubdomains) 452{ 453 SecurityOrigin::removeOriginAccessWhitelistEntry(*SecurityOrigin::createFromString(sourceOrigin), destinationProtocol, destinationHost, allowDestinationSubdomains); 454} 455 456void DumpRenderTreeSupportQt::resetOriginAccessWhiteLists() 457{ 458 SecurityOrigin::resetOriginAccessWhitelists(); 459} 460 461void DumpRenderTreeSupportQt::setDomainRelaxationForbiddenForURLScheme(bool forbidden, const QString& scheme) 462{ 463 SecurityOrigin::setDomainRelaxationForbiddenForURLScheme(forbidden, scheme); 464} 465 466void DumpRenderTreeSupportQt::setCaretBrowsingEnabled(QWebPage* page, bool value) 467{ 468 page->handle()->page->settings()->setCaretBrowsingEnabled(value); 469} 470 471void DumpRenderTreeSupportQt::setMediaType(QWebFrame* frame, const QString& type) 472{ 473 WebCore::Frame* coreFrame = QWebFramePrivate::core(frame); 474 WebCore::FrameView* view = coreFrame->view(); 475 view->setMediaType(type); 476 coreFrame->document()->styleSelectorChanged(RecalcStyleImmediately); 477 view->layout(); 478} 479 480void DumpRenderTreeSupportQt::setSmartInsertDeleteEnabled(QWebPage* page, bool enabled) 481{ 482 page->d->smartInsertDeleteEnabled = enabled; 483} 484 485 486void DumpRenderTreeSupportQt::setSelectTrailingWhitespaceEnabled(QWebPage* page, bool enabled) 487{ 488 page->d->selectTrailingWhitespaceEnabled = enabled; 489} 490 491 492void DumpRenderTreeSupportQt::executeCoreCommandByName(QWebPage* page, const QString& name, const QString& value) 493{ 494 page->handle()->page->focusController()->focusedOrMainFrame()->editor()->command(name).execute(value); 495} 496 497bool DumpRenderTreeSupportQt::isCommandEnabled(QWebPage* page, const QString& name) 498{ 499 return page->handle()->page->focusController()->focusedOrMainFrame()->editor()->command(name).isEnabled(); 500} 501 502bool DumpRenderTreeSupportQt::findString(QWebPage* page, const QString& string, const QStringList& optionArray) 503{ 504 // 1. Parse the options from the array 505 WebCore::FindOptions options = 0; 506 const int optionCount = optionArray.size(); 507 for (int i = 0; i < optionCount; ++i) { 508 const QString& option = optionArray.at(i); 509 if (option == QLatin1String("CaseInsensitive")) 510 options |= WebCore::CaseInsensitive; 511 else if (option == QLatin1String("AtWordStarts")) 512 options |= WebCore::AtWordStarts; 513 else if (option == QLatin1String("TreatMedialCapitalAsWordStart")) 514 options |= WebCore::TreatMedialCapitalAsWordStart; 515 else if (option == QLatin1String("Backwards")) 516 options |= WebCore::Backwards; 517 else if (option == QLatin1String("WrapAround")) 518 options |= WebCore::WrapAround; 519 else if (option == QLatin1String("StartInSelection")) 520 options |= WebCore::StartInSelection; 521 } 522 523 // 2. find the string 524 WebCore::Frame* frame = page->handle()->page->focusController()->focusedOrMainFrame(); 525 return frame && frame->editor()->findString(string, options); 526} 527 528QString DumpRenderTreeSupportQt::markerTextForListItem(const QWebElement& listItem) 529{ 530 return WebCore::markerTextForListItem(listItem.m_element); 531} 532 533static QString convertToPropertyName(const QString& name) 534{ 535 QStringList parts = name.split(QLatin1Char('-')); 536 QString camelCaseName; 537 for (int j = 0; j < parts.count(); ++j) { 538 QString part = parts.at(j); 539 if (j) 540 camelCaseName.append(part.replace(0, 1, part.left(1).toUpper())); 541 else 542 camelCaseName.append(part); 543 } 544 return camelCaseName; 545} 546 547QVariantMap DumpRenderTreeSupportQt::computedStyleIncludingVisitedInfo(const QWebElement& element) 548{ 549 QVariantMap res; 550 551 WebCore::Element* webElement = element.m_element; 552 if (!webElement) 553 return res; 554 555 RefPtr<WebCore::CSSComputedStyleDeclaration> style = computedStyle(webElement, true); 556 for (int i = 0; i < style->length(); i++) { 557 QString name = style->item(i); 558 QString value = (static_cast<WebCore::CSSStyleDeclaration*>(style.get()))->getPropertyValue(name); 559 res[convertToPropertyName(name)] = QVariant(value); 560 } 561 return res; 562} 563 564QVariantList DumpRenderTreeSupportQt::selectedRange(QWebPage* page) 565{ 566 WebCore::Frame* frame = page->handle()->page->focusController()->focusedOrMainFrame(); 567 QVariantList selectedRange; 568 RefPtr<Range> range = frame->selection()->toNormalizedRange().get(); 569 570 Element* selectionRoot = frame->selection()->rootEditableElement(); 571 Element* scope = selectionRoot ? selectionRoot : frame->document()->documentElement(); 572 573 RefPtr<Range> testRange = Range::create(scope->document(), scope, 0, range->startContainer(), range->startOffset()); 574 ASSERT(testRange->startContainer() == scope); 575 int startPosition = TextIterator::rangeLength(testRange.get()); 576 577 ExceptionCode ec; 578 testRange->setEnd(range->endContainer(), range->endOffset(), ec); 579 ASSERT(testRange->startContainer() == scope); 580 int endPosition = TextIterator::rangeLength(testRange.get()); 581 582 selectedRange << startPosition << (endPosition - startPosition); 583 584 return selectedRange; 585 586} 587 588QVariantList DumpRenderTreeSupportQt::firstRectForCharacterRange(QWebPage* page, int location, int length) 589{ 590 WebCore::Frame* frame = page->handle()->page->focusController()->focusedOrMainFrame(); 591 QVariantList rect; 592 593 if ((location + length < location) && (location + length)) 594 length = 0; 595 596 Element* selectionRoot = frame->selection()->rootEditableElement(); 597 Element* scope = selectionRoot ? selectionRoot : frame->document()->documentElement(); 598 RefPtr<Range> range = TextIterator::rangeFromLocationAndLength(scope, location, length); 599 600 if (!range) 601 return QVariantList(); 602 603 QRect resultRect = frame->editor()->firstRectForRange(range.get()); 604 rect << resultRect.x() << resultRect.y() << resultRect.width() << resultRect.height(); 605 return rect; 606} 607 608bool DumpRenderTreeSupportQt::elementDoesAutoCompleteForElementWithId(QWebFrame* frame, const QString& elementId) 609{ 610 Frame* coreFrame = QWebFramePrivate::core(frame); 611 if (!coreFrame) 612 return false; 613 614 Document* doc = coreFrame->document(); 615 Q_ASSERT(doc); 616 617 Node* coreNode = doc->getElementById(elementId); 618 if (!coreNode || !coreNode->renderer()) 619 return false; 620 621 HTMLInputElement* inputElement = static_cast<HTMLInputElement*>(coreNode); 622 623 return inputElement->isTextField() && !inputElement->isPasswordField() && inputElement->autoComplete(); 624} 625 626void DumpRenderTreeSupportQt::setEditingBehavior(QWebPage* page, const QString& editingBehavior) 627{ 628 WebCore::EditingBehaviorType coreEditingBehavior; 629 630 if (editingBehavior == QLatin1String("win")) 631 coreEditingBehavior = EditingWindowsBehavior; 632 else if (editingBehavior == QLatin1String("mac")) 633 coreEditingBehavior = EditingMacBehavior; 634 else if (editingBehavior == QLatin1String("unix")) 635 coreEditingBehavior = EditingUnixBehavior; 636 else { 637 ASSERT_NOT_REACHED(); 638 return; 639 } 640 641 Page* corePage = QWebPagePrivate::core(page); 642 if (!corePage) 643 return; 644 645 corePage->settings()->setEditingBehaviorType(coreEditingBehavior); 646} 647 648void DumpRenderTreeSupportQt::clearAllApplicationCaches() 649{ 650#if ENABLE(OFFLINE_WEB_APPLICATIONS) 651 WebCore::cacheStorage().empty(); 652 WebCore::cacheStorage().vacuumDatabaseFile(); 653#endif 654} 655 656void DumpRenderTreeSupportQt::dumpFrameLoader(bool b) 657{ 658 FrameLoaderClientQt::dumpFrameLoaderCallbacks = b; 659} 660 661void DumpRenderTreeSupportQt::dumpUserGestureInFrameLoader(bool b) 662{ 663 FrameLoaderClientQt::dumpUserGestureInFrameLoaderCallbacks = b; 664} 665 666void DumpRenderTreeSupportQt::dumpResourceLoadCallbacks(bool b) 667{ 668 FrameLoaderClientQt::dumpResourceLoadCallbacks = b; 669} 670 671void DumpRenderTreeSupportQt::dumpResourceLoadCallbacksPath(const QString& path) 672{ 673 FrameLoaderClientQt::dumpResourceLoadCallbacksPath = path; 674} 675 676void DumpRenderTreeSupportQt::dumpResourceResponseMIMETypes(bool b) 677{ 678 FrameLoaderClientQt::dumpResourceResponseMIMETypes = b; 679} 680 681void DumpRenderTreeSupportQt::setWillSendRequestReturnsNullOnRedirect(bool b) 682{ 683 FrameLoaderClientQt::sendRequestReturnsNullOnRedirect = b; 684} 685 686void DumpRenderTreeSupportQt::setWillSendRequestReturnsNull(bool b) 687{ 688 FrameLoaderClientQt::sendRequestReturnsNull = b; 689} 690 691void DumpRenderTreeSupportQt::setWillSendRequestClearHeaders(const QStringList& headers) 692{ 693 FrameLoaderClientQt::sendRequestClearHeaders = headers; 694} 695 696void DumpRenderTreeSupportQt::setDeferMainResourceDataLoad(bool b) 697{ 698 FrameLoaderClientQt::deferMainResourceDataLoad = b; 699} 700 701void DumpRenderTreeSupportQt::setCustomPolicyDelegate(bool enabled, bool permissive) 702{ 703 FrameLoaderClientQt::policyDelegateEnabled = enabled; 704 FrameLoaderClientQt::policyDelegatePermissive = permissive; 705} 706 707void DumpRenderTreeSupportQt::dumpHistoryCallbacks(bool b) 708{ 709 FrameLoaderClientQt::dumpHistoryCallbacks = b; 710} 711 712void DumpRenderTreeSupportQt::dumpVisitedLinksCallbacks(bool b) 713{ 714 ChromeClientQt::dumpVisitedLinksCallbacks = b; 715} 716 717void DumpRenderTreeSupportQt::dumpEditingCallbacks(bool b) 718{ 719 EditorClientQt::dumpEditingCallbacks = b; 720} 721 722void DumpRenderTreeSupportQt::dumpSetAcceptsEditing(bool b) 723{ 724 EditorClientQt::acceptsEditing = b; 725} 726 727void DumpRenderTreeSupportQt::dumpNotification(bool b) 728{ 729#if ENABLE(NOTIFICATIONS) 730 NotificationPresenterClientQt::dumpNotification = b; 731#endif 732} 733 734QString DumpRenderTreeSupportQt::viewportAsText(QWebPage* page, int deviceDPI, const QSize& deviceSize, const QSize& availableSize) 735{ 736 WebCore::ViewportArguments args = page->d->viewportArguments(); 737 738 WebCore::ViewportAttributes conf = WebCore::computeViewportAttributes(args, 739 /* desktop-width */ 980, 740 /* device-width */ deviceSize.width(), 741 /* device-height */ deviceSize.height(), 742 /* device-dpi */ deviceDPI, 743 availableSize); 744 745 QString res; 746 res = res.sprintf("viewport size %dx%d scale %f with limits [%f, %f] and userScalable %f\n", 747 conf.layoutSize.width(), 748 conf.layoutSize.height(), 749 conf.initialScale, 750 conf.minimumScale, 751 conf.maximumScale, 752 conf.userScalable); 753 754 return res; 755} 756 757void DumpRenderTreeSupportQt::activeMockDeviceOrientationClient(bool b) 758{ 759#if ENABLE(DEVICE_ORIENTATION) 760 DeviceOrientationClientMockQt::mockIsActive = b; 761#endif 762} 763 764void DumpRenderTreeSupportQt::removeMockDeviceOrientation() 765{ 766#if ENABLE(DEVICE_ORIENTATION) 767 DeviceOrientationClientMockQt* client = DeviceOrientationClientMockQt::client(); 768 delete client; 769#endif 770} 771 772void DumpRenderTreeSupportQt::setMockDeviceOrientation(bool canProvideAlpha, double alpha, bool canProvideBeta, double beta, bool canProvideGamma, double gamma) 773{ 774#if ENABLE(DEVICE_ORIENTATION) 775 DeviceOrientationClientMockQt::client()->setOrientation(canProvideAlpha, alpha, canProvideBeta, beta, canProvideGamma, gamma); 776#endif 777} 778 779void DumpRenderTreeSupportQt::resetGeolocationMock(QWebPage* page) 780{ 781#if ENABLE(CLIENT_BASED_GEOLOCATION) 782 Page* corePage = QWebPagePrivate::core(page); 783 GeolocationClientMock* mockClient = toGeolocationClientMock(corePage->geolocationController()->client()); 784 mockClient->reset(); 785#endif 786} 787 788void DumpRenderTreeSupportQt::setMockGeolocationPermission(QWebPage* page, bool allowed) 789{ 790#if ENABLE(CLIENT_BASED_GEOLOCATION) 791 Page* corePage = QWebPagePrivate::core(page); 792 GeolocationClientMock* mockClient = toGeolocationClientMock(corePage->geolocationController()->client()); 793 mockClient->setPermission(allowed); 794#endif 795} 796 797void DumpRenderTreeSupportQt::setMockGeolocationPosition(QWebPage* page, double latitude, double longitude, double accuracy) 798{ 799#if ENABLE(CLIENT_BASED_GEOLOCATION) 800 Page* corePage = QWebPagePrivate::core(page); 801 GeolocationClientMock* mockClient = toGeolocationClientMock(corePage->geolocationController()->client()); 802 mockClient->setPosition(GeolocationPosition::create(currentTime(), latitude, longitude, accuracy)); 803#endif 804} 805 806void DumpRenderTreeSupportQt::setMockGeolocationError(QWebPage* page, int errorCode, const QString& message) 807{ 808#if ENABLE(CLIENT_BASED_GEOLOCATION) 809 Page* corePage = QWebPagePrivate::core(page); 810 811 GeolocationError::ErrorCode code = GeolocationError::PositionUnavailable; 812 switch (errorCode) { 813 case PositionError::PERMISSION_DENIED: 814 code = GeolocationError::PermissionDenied; 815 break; 816 case PositionError::POSITION_UNAVAILABLE: 817 code = GeolocationError::PositionUnavailable; 818 break; 819 } 820 821 GeolocationClientMock* mockClient = static_cast<GeolocationClientMock*>(corePage->geolocationController()->client()); 822 mockClient->setError(GeolocationError::create(code, message)); 823#endif 824} 825 826int DumpRenderTreeSupportQt::numberOfPendingGeolocationPermissionRequests(QWebPage* page) 827{ 828#if ENABLE(CLIENT_BASED_GEOLOCATION) 829 Page* corePage = QWebPagePrivate::core(page); 830 GeolocationClientMock* mockClient = toGeolocationClientMock(corePage->geolocationController()->client()); 831 return mockClient->numberOfPendingPermissionRequests(); 832#else 833 return -1; 834#endif 835} 836 837bool DumpRenderTreeSupportQt::isTargetItem(const QWebHistoryItem& historyItem) 838{ 839 QWebHistoryItem it = historyItem; 840 if (QWebHistoryItemPrivate::core(&it)->isTargetItem()) 841 return true; 842 return false; 843} 844 845QString DumpRenderTreeSupportQt::historyItemTarget(const QWebHistoryItem& historyItem) 846{ 847 QWebHistoryItem it = historyItem; 848 return (QWebHistoryItemPrivate::core(&it)->target()); 849} 850 851QMap<QString, QWebHistoryItem> DumpRenderTreeSupportQt::getChildHistoryItems(const QWebHistoryItem& historyItem) 852{ 853 QWebHistoryItem it = historyItem; 854 HistoryItem* item = QWebHistoryItemPrivate::core(&it); 855 const WebCore::HistoryItemVector& children = item->children(); 856 857 unsigned size = children.size(); 858 QMap<QString, QWebHistoryItem> kids; 859 for (unsigned i = 0; i < size; ++i) { 860 QWebHistoryItem kid(new QWebHistoryItemPrivate(children[i].get())); 861 kids.insert(DumpRenderTreeSupportQt::historyItemTarget(kid), kid); 862 } 863 return kids; 864} 865 866bool DumpRenderTreeSupportQt::shouldClose(QWebFrame* frame) 867{ 868 WebCore::Frame* coreFrame = QWebFramePrivate::core(frame); 869 return coreFrame->loader()->shouldClose(); 870} 871 872void DumpRenderTreeSupportQt::clearScriptWorlds() 873{ 874 m_worldMap.clear(); 875} 876 877void DumpRenderTreeSupportQt::evaluateScriptInIsolatedWorld(QWebFrame* frame, int worldID, const QString& script) 878{ 879 QWebScriptWorld* scriptWorld; 880 if (!worldID) { 881 scriptWorld = new QWebScriptWorld(); 882 } else if (!m_worldMap.contains(worldID)) { 883 scriptWorld = new QWebScriptWorld(); 884 m_worldMap.insert(worldID, scriptWorld); 885 } else 886 scriptWorld = m_worldMap.value(worldID); 887 888 WebCore::Frame* coreFrame = QWebFramePrivate::core(frame); 889 890 ScriptController* proxy = coreFrame->script(); 891 892 if (!proxy) 893 return; 894#if USE(JSC) 895 proxy->executeScriptInWorld(scriptWorld->world(), script, true); 896#elif USE(V8) 897 ScriptSourceCode source(script); 898 Vector<ScriptSourceCode> sources; 899 sources.append(source); 900 proxy->evaluateInIsolatedWorld(0, sources, true); 901#endif 902} 903 904bool DumpRenderTreeSupportQt::isPageBoxVisible(QWebFrame* frame, int pageIndex) 905{ 906 WebCore::Frame* coreFrame = QWebFramePrivate::core(frame); 907 return coreFrame->document()->isPageBoxVisible(pageIndex); 908} 909 910QString DumpRenderTreeSupportQt::pageSizeAndMarginsInPixels(QWebFrame* frame, int pageIndex, int width, int height, int marginTop, int marginRight, int marginBottom, int marginLeft) 911{ 912 WebCore::Frame* coreFrame = QWebFramePrivate::core(frame); 913 return PrintContext::pageSizeAndMarginsInPixels(coreFrame, pageIndex, width, height, 914 marginTop, marginRight, marginBottom, marginLeft); 915} 916 917QString DumpRenderTreeSupportQt::pageProperty(QWebFrame* frame, const QString& propertyName, int pageNumber) 918{ 919 WebCore::Frame* coreFrame = QWebFramePrivate::core(frame); 920 return PrintContext::pageProperty(coreFrame, propertyName.toUtf8().constData(), pageNumber); 921} 922 923void DumpRenderTreeSupportQt::addUserStyleSheet(QWebPage* page, const QString& sourceCode) 924{ 925 page->handle()->page->group().addUserStyleSheetToWorld(mainThreadNormalWorld(), sourceCode, QUrl(), 0, 0, WebCore::InjectInAllFrames); 926} 927 928void DumpRenderTreeSupportQt::simulateDesktopNotificationClick(const QString& title) 929{ 930#if ENABLE(NOTIFICATIONS) 931 NotificationPresenterClientQt::notificationPresenter()->notificationClicked(title); 932#endif 933} 934 935QString DumpRenderTreeSupportQt::plainText(const QVariant& range) 936{ 937 QMap<QString, QVariant> map = range.toMap(); 938 QVariant startContainer = map.value(QLatin1String("startContainer")); 939 map = startContainer.toMap(); 940 941 return map.value(QLatin1String("innerText")).toString(); 942} 943 944QVariantList DumpRenderTreeSupportQt::nodesFromRect(const QWebElement& document, int x, int y, unsigned top, unsigned right, unsigned bottom, unsigned left, bool ignoreClipping) 945{ 946 QVariantList res; 947 WebCore::Element* webElement = document.m_element; 948 if (!webElement) 949 return res; 950 951 Document* doc = webElement->document(); 952 if (!doc) 953 return res; 954 RefPtr<NodeList> nodes = doc->nodesFromRect(x, y, top, right, bottom, left, ignoreClipping); 955 for (int i = 0; i < nodes->length(); i++) { 956 // QWebElement will be null if the Node is not an HTML Element 957 if (nodes->item(i)->isHTMLElement()) 958 res << QVariant::fromValue(QWebElement(nodes->item(i))); 959 else 960 res << QVariant::fromValue(QDRTNode(nodes->item(i))); 961 } 962 return res; 963} 964 965// API Candidate? 966QString DumpRenderTreeSupportQt::responseMimeType(QWebFrame* frame) 967{ 968 WebCore::Frame* coreFrame = QWebFramePrivate::core(frame); 969 WebCore::DocumentLoader* docLoader = coreFrame->loader()->documentLoader(); 970 return docLoader->responseMIMEType(); 971} 972 973void DumpRenderTreeSupportQt::clearOpener(QWebFrame* frame) 974{ 975 WebCore::Frame* coreFrame = QWebFramePrivate::core(frame); 976 coreFrame->loader()->setOpener(0); 977} 978 979void DumpRenderTreeSupportQt::addURLToRedirect(const QString& origin, const QString& destination) 980{ 981 FrameLoaderClientQt::URLsToRedirect[origin] = destination; 982} 983 984static QStringList iterateContextMenu(QMenu* menu) 985{ 986 if (!menu) 987 return QStringList(); 988 989 QStringList items; 990 QList<QAction *> actions = menu->actions(); 991 for (int i = 0; i < actions.count(); ++i) { 992 if (actions.at(i)->isSeparator()) 993 items << QLatin1String("<separator>"); 994 else 995 items << actions.at(i)->text(); 996 if (actions.at(i)->menu()) 997 items << iterateContextMenu(actions.at(i)->menu()); 998 } 999 return items; 1000} 1001 1002QStringList DumpRenderTreeSupportQt::contextMenu(QWebPage* page) 1003{ 1004#ifndef QT_NO_CONTEXTMENU 1005 return iterateContextMenu(page->d->currentContextMenu); 1006#else 1007 return QStringList(); 1008#endif 1009} 1010 1011double DumpRenderTreeSupportQt::defaultMinimumTimerInterval() 1012{ 1013 return Settings::defaultMinDOMTimerInterval(); 1014} 1015 1016void DumpRenderTreeSupportQt::setMinimumTimerInterval(QWebPage* page, double interval) 1017{ 1018 Page* corePage = QWebPagePrivate::core(page); 1019 if (!corePage) 1020 return; 1021 1022 corePage->settings()->setMinDOMTimerInterval(interval); 1023} 1024 1025QUrl DumpRenderTreeSupportQt::mediaContentUrlByElementId(QWebFrame* frame, const QString& elementId) 1026{ 1027 QUrl res; 1028 1029#if ENABLE(VIDEO) && USE(QT_MULTIMEDIA) 1030 Frame* coreFrame = QWebFramePrivate::core(frame); 1031 if (!coreFrame) 1032 return res; 1033 1034 Document* doc = coreFrame->document(); 1035 if (!doc) 1036 return res; 1037 1038 Node* coreNode = doc->getElementById(elementId); 1039 if (!coreNode) 1040 return res; 1041 1042 HTMLVideoElement* videoElement = static_cast<HTMLVideoElement*>(coreNode); 1043 PlatformMedia platformMedia = videoElement->platformMedia(); 1044 if (platformMedia.type != PlatformMedia::QtMediaPlayerType) 1045 return res; 1046 1047 MediaPlayerPrivateQt* mediaPlayerQt = static_cast<MediaPlayerPrivateQt*>(platformMedia.media.qtMediaPlayer); 1048 if (mediaPlayerQt && mediaPlayerQt->mediaPlayer()) 1049 res = mediaPlayerQt->mediaPlayer()->media().canonicalUrl(); 1050#endif 1051 1052 return res; 1053} 1054 1055// API Candidate? 1056void DumpRenderTreeSupportQt::setAlternateHtml(QWebFrame* frame, const QString& html, const QUrl& baseUrl, const QUrl& failingUrl) 1057{ 1058 KURL kurl(baseUrl); 1059 WebCore::Frame* coreFrame = QWebFramePrivate::core(frame); 1060 WebCore::ResourceRequest request(kurl); 1061 const QByteArray utf8 = html.toUtf8(); 1062 WTF::RefPtr<WebCore::SharedBuffer> data = WebCore::SharedBuffer::create(utf8.constData(), utf8.length()); 1063 WebCore::SubstituteData substituteData(data, WTF::String("text/html"), WTF::String("utf-8"), failingUrl); 1064 coreFrame->loader()->load(request, substituteData, false); 1065} 1066 1067QVariant DumpRenderTreeSupportQt::shadowRoot(const QWebElement& element) 1068{ 1069 WebCore::Element* webElement = element.m_element; 1070 if (!webElement) 1071 return QVariant(); 1072 1073 ContainerNode* webShadowRoot = webElement->shadowRoot(); 1074 if (!webShadowRoot) 1075 return QVariant(); 1076 1077 return QVariant::fromValue(QDRTNode(webShadowRoot)); 1078} 1079 1080// Provide a backward compatibility with previously exported private symbols as of QtWebKit 4.6 release 1081 1082void QWEBKIT_EXPORT qt_resumeActiveDOMObjects(QWebFrame* frame) 1083{ 1084 DumpRenderTreeSupportQt::resumeActiveDOMObjects(frame); 1085} 1086 1087void QWEBKIT_EXPORT qt_suspendActiveDOMObjects(QWebFrame* frame) 1088{ 1089 DumpRenderTreeSupportQt::suspendActiveDOMObjects(frame); 1090} 1091 1092void QWEBKIT_EXPORT qt_drt_clearFrameName(QWebFrame* frame) 1093{ 1094 DumpRenderTreeSupportQt::clearFrameName(frame); 1095} 1096 1097void QWEBKIT_EXPORT qt_drt_garbageCollector_collect() 1098{ 1099 DumpRenderTreeSupportQt::garbageCollectorCollect(); 1100} 1101 1102void QWEBKIT_EXPORT qt_drt_garbageCollector_collectOnAlternateThread(bool waitUntilDone) 1103{ 1104 DumpRenderTreeSupportQt::garbageCollectorCollectOnAlternateThread(waitUntilDone); 1105} 1106 1107int QWEBKIT_EXPORT qt_drt_javaScriptObjectsCount() 1108{ 1109 return DumpRenderTreeSupportQt::javaScriptObjectsCount(); 1110} 1111 1112int QWEBKIT_EXPORT qt_drt_numberOfActiveAnimations(QWebFrame* frame) 1113{ 1114 return DumpRenderTreeSupportQt::numberOfActiveAnimations(frame); 1115} 1116 1117void QWEBKIT_EXPORT qt_drt_overwritePluginDirectories() 1118{ 1119 DumpRenderTreeSupportQt::overwritePluginDirectories(); 1120} 1121 1122bool QWEBKIT_EXPORT qt_drt_pauseAnimation(QWebFrame* frame, const QString& animationName, double time, const QString& elementId) 1123{ 1124 return DumpRenderTreeSupportQt::pauseAnimation(frame, animationName, time, elementId); 1125} 1126 1127bool QWEBKIT_EXPORT qt_drt_pauseTransitionOfProperty(QWebFrame* frame, const QString& propertyName, double time, const QString &elementId) 1128{ 1129 return DumpRenderTreeSupportQt::pauseTransitionOfProperty(frame, propertyName, time, elementId); 1130} 1131 1132void QWEBKIT_EXPORT qt_drt_resetOriginAccessWhiteLists() 1133{ 1134 DumpRenderTreeSupportQt::resetOriginAccessWhiteLists(); 1135} 1136 1137void QWEBKIT_EXPORT qt_drt_run(bool b) 1138{ 1139 DumpRenderTreeSupportQt::setDumpRenderTreeModeEnabled(b); 1140} 1141 1142void QWEBKIT_EXPORT qt_drt_setJavaScriptProfilingEnabled(QWebFrame* frame, bool enabled) 1143{ 1144 DumpRenderTreeSupportQt::setJavaScriptProfilingEnabled(frame, enabled); 1145} 1146 1147void QWEBKIT_EXPORT qt_drt_whiteListAccessFromOrigin(const QString& sourceOrigin, const QString& destinationProtocol, const QString& destinationHost, bool allowDestinationSubdomains) 1148{ 1149 DumpRenderTreeSupportQt::whiteListAccessFromOrigin(sourceOrigin, destinationProtocol, destinationHost, allowDestinationSubdomains); 1150} 1151 1152QString QWEBKIT_EXPORT qt_webpage_groupName(QWebPage* page) 1153{ 1154 return DumpRenderTreeSupportQt::webPageGroupName(page); 1155} 1156 1157void QWEBKIT_EXPORT qt_webpage_setGroupName(QWebPage* page, const QString& groupName) 1158{ 1159 DumpRenderTreeSupportQt::webPageSetGroupName(page, groupName); 1160} 1161 1162void QWEBKIT_EXPORT qt_dump_frame_loader(bool b) 1163{ 1164 DumpRenderTreeSupportQt::dumpFrameLoader(b); 1165} 1166 1167void QWEBKIT_EXPORT qt_dump_resource_load_callbacks(bool b) 1168{ 1169 DumpRenderTreeSupportQt::dumpResourceLoadCallbacks(b); 1170} 1171 1172void QWEBKIT_EXPORT qt_dump_editing_callbacks(bool b) 1173{ 1174 DumpRenderTreeSupportQt::dumpEditingCallbacks(b); 1175} 1176 1177void QWEBKIT_EXPORT qt_dump_set_accepts_editing(bool b) 1178{ 1179 DumpRenderTreeSupportQt::dumpSetAcceptsEditing(b); 1180} 1181 1182