1 /* 2 Copyright (C) 2010 Robert Hogan <robert (at) 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 91 using namespace WebCore; 92 93 QMap<int, QWebScriptWorld*> m_worldMap; 94 95 #if ENABLE(CLIENT_BASED_GEOLOCATION) 96 GeolocationClientMock* toGeolocationClientMock(GeolocationClient* client) 97 { 98 ASSERT(QWebPagePrivate::drtRun); 99 return static_cast<GeolocationClientMock*>(client); 100 } 101 #endif 102 103 QDRTNode::QDRTNode() 104 : m_node(0) 105 { 106 } 107 108 QDRTNode::QDRTNode(WebCore::Node* node) 109 : m_node(0) 110 { 111 if (node) { 112 m_node = node; 113 m_node->ref(); 114 } 115 } 116 117 QDRTNode::~QDRTNode() 118 { 119 if (m_node) 120 m_node->deref(); 121 } 122 123 QDRTNode::QDRTNode(const QDRTNode& other) 124 :m_node(other.m_node) 125 { 126 if (m_node) 127 m_node->ref(); 128 } 129 130 QDRTNode& 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 144 DumpRenderTreeSupportQt::DumpRenderTreeSupportQt() 145 { 146 } 147 148 DumpRenderTreeSupportQt::~DumpRenderTreeSupportQt() 149 { 150 } 151 152 void 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 164 int DumpRenderTreeSupportQt::workerThreadCount() 165 { 166 #if ENABLE(WORKERS) 167 return WebCore::WorkerThread::workerThreadCount(); 168 #else 169 return 0; 170 #endif 171 } 172 173 void DumpRenderTreeSupportQt::setDumpRenderTreeModeEnabled(bool b) 174 { 175 QWebPagePrivate::drtRun = b; 176 } 177 178 void DumpRenderTreeSupportQt::setFrameFlatteningEnabled(QWebPage* page, bool enabled) 179 { 180 QWebPagePrivate::core(page)->settings()->setFrameFlatteningEnabled(enabled); 181 } 182 183 void DumpRenderTreeSupportQt::webPageSetGroupName(QWebPage* page, const QString& groupName) 184 { 185 page->handle()->page->setGroupName(groupName); 186 } 187 188 QString DumpRenderTreeSupportQt::webPageGroupName(QWebPage* page) 189 { 190 return page->handle()->page->groupName(); 191 } 192 193 void 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 202 void 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 211 void 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 220 void 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 233 bool DumpRenderTreeSupportQt::hasDocumentElement(QWebFrame* frame) 234 { 235 return QWebFramePrivate::core(frame)->document()->documentElement(); 236 } 237 238 void 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. 255 bool 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 275 bool 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. 297 bool 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). 321 int 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 334 void 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 347 void 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 360 void DumpRenderTreeSupportQt::clearFrameName(QWebFrame* frame) 361 { 362 Frame* coreFrame = QWebFramePrivate::core(frame); 363 coreFrame->tree()->clearName(); 364 } 365 366 int 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 376 void DumpRenderTreeSupportQt::garbageCollectorCollect() 377 { 378 #if USE(JSC) 379 gcController().garbageCollectNow(); 380 #elif USE(V8) 381 v8::V8::LowMemoryNotification(); 382 #endif 383 } 384 385 void 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. 396 QString 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 406 int 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 419 int 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. 429 void 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. 439 void DumpRenderTreeSupportQt::resumeActiveDOMObjects(QWebFrame* frame) 440 { 441 Frame* coreFrame = QWebFramePrivate::core(frame); 442 if (coreFrame->document()) 443 coreFrame->document()->resumeActiveDOMObjects(); 444 } 445 446 void 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 451 void 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 456 void DumpRenderTreeSupportQt::resetOriginAccessWhiteLists() 457 { 458 SecurityOrigin::resetOriginAccessWhitelists(); 459 } 460 461 void DumpRenderTreeSupportQt::setDomainRelaxationForbiddenForURLScheme(bool forbidden, const QString& scheme) 462 { 463 SecurityOrigin::setDomainRelaxationForbiddenForURLScheme(forbidden, scheme); 464 } 465 466 void DumpRenderTreeSupportQt::setCaretBrowsingEnabled(QWebPage* page, bool value) 467 { 468 page->handle()->page->settings()->setCaretBrowsingEnabled(value); 469 } 470 471 void 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 480 void DumpRenderTreeSupportQt::setSmartInsertDeleteEnabled(QWebPage* page, bool enabled) 481 { 482 page->d->smartInsertDeleteEnabled = enabled; 483 } 484 485 486 void DumpRenderTreeSupportQt::setSelectTrailingWhitespaceEnabled(QWebPage* page, bool enabled) 487 { 488 page->d->selectTrailingWhitespaceEnabled = enabled; 489 } 490 491 492 void DumpRenderTreeSupportQt::executeCoreCommandByName(QWebPage* page, const QString& name, const QString& value) 493 { 494 page->handle()->page->focusController()->focusedOrMainFrame()->editor()->command(name).execute(value); 495 } 496 497 bool DumpRenderTreeSupportQt::isCommandEnabled(QWebPage* page, const QString& name) 498 { 499 return page->handle()->page->focusController()->focusedOrMainFrame()->editor()->command(name).isEnabled(); 500 } 501 502 bool 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 528 QString DumpRenderTreeSupportQt::markerTextForListItem(const QWebElement& listItem) 529 { 530 return WebCore::markerTextForListItem(listItem.m_element); 531 } 532 533 static 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 547 QVariantMap 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 564 QVariantList 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 588 QVariantList 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 608 bool 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 626 void 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 648 void DumpRenderTreeSupportQt::clearAllApplicationCaches() 649 { 650 #if ENABLE(OFFLINE_WEB_APPLICATIONS) 651 WebCore::cacheStorage().empty(); 652 WebCore::cacheStorage().vacuumDatabaseFile(); 653 #endif 654 } 655 656 void DumpRenderTreeSupportQt::dumpFrameLoader(bool b) 657 { 658 FrameLoaderClientQt::dumpFrameLoaderCallbacks = b; 659 } 660 661 void DumpRenderTreeSupportQt::dumpUserGestureInFrameLoader(bool b) 662 { 663 FrameLoaderClientQt::dumpUserGestureInFrameLoaderCallbacks = b; 664 } 665 666 void DumpRenderTreeSupportQt::dumpResourceLoadCallbacks(bool b) 667 { 668 FrameLoaderClientQt::dumpResourceLoadCallbacks = b; 669 } 670 671 void DumpRenderTreeSupportQt::dumpResourceLoadCallbacksPath(const QString& path) 672 { 673 FrameLoaderClientQt::dumpResourceLoadCallbacksPath = path; 674 } 675 676 void DumpRenderTreeSupportQt::dumpResourceResponseMIMETypes(bool b) 677 { 678 FrameLoaderClientQt::dumpResourceResponseMIMETypes = b; 679 } 680 681 void DumpRenderTreeSupportQt::setWillSendRequestReturnsNullOnRedirect(bool b) 682 { 683 FrameLoaderClientQt::sendRequestReturnsNullOnRedirect = b; 684 } 685 686 void DumpRenderTreeSupportQt::setWillSendRequestReturnsNull(bool b) 687 { 688 FrameLoaderClientQt::sendRequestReturnsNull = b; 689 } 690 691 void DumpRenderTreeSupportQt::setWillSendRequestClearHeaders(const QStringList& headers) 692 { 693 FrameLoaderClientQt::sendRequestClearHeaders = headers; 694 } 695 696 void DumpRenderTreeSupportQt::setDeferMainResourceDataLoad(bool b) 697 { 698 FrameLoaderClientQt::deferMainResourceDataLoad = b; 699 } 700 701 void DumpRenderTreeSupportQt::setCustomPolicyDelegate(bool enabled, bool permissive) 702 { 703 FrameLoaderClientQt::policyDelegateEnabled = enabled; 704 FrameLoaderClientQt::policyDelegatePermissive = permissive; 705 } 706 707 void DumpRenderTreeSupportQt::dumpHistoryCallbacks(bool b) 708 { 709 FrameLoaderClientQt::dumpHistoryCallbacks = b; 710 } 711 712 void DumpRenderTreeSupportQt::dumpVisitedLinksCallbacks(bool b) 713 { 714 ChromeClientQt::dumpVisitedLinksCallbacks = b; 715 } 716 717 void DumpRenderTreeSupportQt::dumpEditingCallbacks(bool b) 718 { 719 EditorClientQt::dumpEditingCallbacks = b; 720 } 721 722 void DumpRenderTreeSupportQt::dumpSetAcceptsEditing(bool b) 723 { 724 EditorClientQt::acceptsEditing = b; 725 } 726 727 void DumpRenderTreeSupportQt::dumpNotification(bool b) 728 { 729 #if ENABLE(NOTIFICATIONS) 730 NotificationPresenterClientQt::dumpNotification = b; 731 #endif 732 } 733 734 QString 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 757 void DumpRenderTreeSupportQt::activeMockDeviceOrientationClient(bool b) 758 { 759 #if ENABLE(DEVICE_ORIENTATION) 760 DeviceOrientationClientMockQt::mockIsActive = b; 761 #endif 762 } 763 764 void DumpRenderTreeSupportQt::removeMockDeviceOrientation() 765 { 766 #if ENABLE(DEVICE_ORIENTATION) 767 DeviceOrientationClientMockQt* client = DeviceOrientationClientMockQt::client(); 768 delete client; 769 #endif 770 } 771 772 void 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 779 void 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 788 void 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 797 void 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 806 void 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 826 int 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 837 bool DumpRenderTreeSupportQt::isTargetItem(const QWebHistoryItem& historyItem) 838 { 839 QWebHistoryItem it = historyItem; 840 if (QWebHistoryItemPrivate::core(&it)->isTargetItem()) 841 return true; 842 return false; 843 } 844 845 QString DumpRenderTreeSupportQt::historyItemTarget(const QWebHistoryItem& historyItem) 846 { 847 QWebHistoryItem it = historyItem; 848 return (QWebHistoryItemPrivate::core(&it)->target()); 849 } 850 851 QMap<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 866 bool DumpRenderTreeSupportQt::shouldClose(QWebFrame* frame) 867 { 868 WebCore::Frame* coreFrame = QWebFramePrivate::core(frame); 869 return coreFrame->loader()->shouldClose(); 870 } 871 872 void DumpRenderTreeSupportQt::clearScriptWorlds() 873 { 874 m_worldMap.clear(); 875 } 876 877 void 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 904 bool DumpRenderTreeSupportQt::isPageBoxVisible(QWebFrame* frame, int pageIndex) 905 { 906 WebCore::Frame* coreFrame = QWebFramePrivate::core(frame); 907 return coreFrame->document()->isPageBoxVisible(pageIndex); 908 } 909 910 QString 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 917 QString 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 923 void DumpRenderTreeSupportQt::addUserStyleSheet(QWebPage* page, const QString& sourceCode) 924 { 925 page->handle()->page->group().addUserStyleSheetToWorld(mainThreadNormalWorld(), sourceCode, QUrl(), 0, 0, WebCore::InjectInAllFrames); 926 } 927 928 void DumpRenderTreeSupportQt::simulateDesktopNotificationClick(const QString& title) 929 { 930 #if ENABLE(NOTIFICATIONS) 931 NotificationPresenterClientQt::notificationPresenter()->notificationClicked(title); 932 #endif 933 } 934 935 QString 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 944 QVariantList 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? 966 QString 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 973 void DumpRenderTreeSupportQt::clearOpener(QWebFrame* frame) 974 { 975 WebCore::Frame* coreFrame = QWebFramePrivate::core(frame); 976 coreFrame->loader()->setOpener(0); 977 } 978 979 void DumpRenderTreeSupportQt::addURLToRedirect(const QString& origin, const QString& destination) 980 { 981 FrameLoaderClientQt::URLsToRedirect[origin] = destination; 982 } 983 984 static 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 1002 QStringList 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 1011 double DumpRenderTreeSupportQt::defaultMinimumTimerInterval() 1012 { 1013 return Settings::defaultMinDOMTimerInterval(); 1014 } 1015 1016 void 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 1025 QUrl 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? 1056 void 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 1067 QVariant 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 1082 void QWEBKIT_EXPORT qt_resumeActiveDOMObjects(QWebFrame* frame) 1083 { 1084 DumpRenderTreeSupportQt::resumeActiveDOMObjects(frame); 1085 } 1086 1087 void QWEBKIT_EXPORT qt_suspendActiveDOMObjects(QWebFrame* frame) 1088 { 1089 DumpRenderTreeSupportQt::suspendActiveDOMObjects(frame); 1090 } 1091 1092 void QWEBKIT_EXPORT qt_drt_clearFrameName(QWebFrame* frame) 1093 { 1094 DumpRenderTreeSupportQt::clearFrameName(frame); 1095 } 1096 1097 void QWEBKIT_EXPORT qt_drt_garbageCollector_collect() 1098 { 1099 DumpRenderTreeSupportQt::garbageCollectorCollect(); 1100 } 1101 1102 void QWEBKIT_EXPORT qt_drt_garbageCollector_collectOnAlternateThread(bool waitUntilDone) 1103 { 1104 DumpRenderTreeSupportQt::garbageCollectorCollectOnAlternateThread(waitUntilDone); 1105 } 1106 1107 int QWEBKIT_EXPORT qt_drt_javaScriptObjectsCount() 1108 { 1109 return DumpRenderTreeSupportQt::javaScriptObjectsCount(); 1110 } 1111 1112 int QWEBKIT_EXPORT qt_drt_numberOfActiveAnimations(QWebFrame* frame) 1113 { 1114 return DumpRenderTreeSupportQt::numberOfActiveAnimations(frame); 1115 } 1116 1117 void QWEBKIT_EXPORT qt_drt_overwritePluginDirectories() 1118 { 1119 DumpRenderTreeSupportQt::overwritePluginDirectories(); 1120 } 1121 1122 bool 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 1127 bool 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 1132 void QWEBKIT_EXPORT qt_drt_resetOriginAccessWhiteLists() 1133 { 1134 DumpRenderTreeSupportQt::resetOriginAccessWhiteLists(); 1135 } 1136 1137 void QWEBKIT_EXPORT qt_drt_run(bool b) 1138 { 1139 DumpRenderTreeSupportQt::setDumpRenderTreeModeEnabled(b); 1140 } 1141 1142 void QWEBKIT_EXPORT qt_drt_setJavaScriptProfilingEnabled(QWebFrame* frame, bool enabled) 1143 { 1144 DumpRenderTreeSupportQt::setJavaScriptProfilingEnabled(frame, enabled); 1145 } 1146 1147 void 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 1152 QString QWEBKIT_EXPORT qt_webpage_groupName(QWebPage* page) 1153 { 1154 return DumpRenderTreeSupportQt::webPageGroupName(page); 1155 } 1156 1157 void QWEBKIT_EXPORT qt_webpage_setGroupName(QWebPage* page, const QString& groupName) 1158 { 1159 DumpRenderTreeSupportQt::webPageSetGroupName(page, groupName); 1160 } 1161 1162 void QWEBKIT_EXPORT qt_dump_frame_loader(bool b) 1163 { 1164 DumpRenderTreeSupportQt::dumpFrameLoader(b); 1165 } 1166 1167 void QWEBKIT_EXPORT qt_dump_resource_load_callbacks(bool b) 1168 { 1169 DumpRenderTreeSupportQt::dumpResourceLoadCallbacks(b); 1170 } 1171 1172 void QWEBKIT_EXPORT qt_dump_editing_callbacks(bool b) 1173 { 1174 DumpRenderTreeSupportQt::dumpEditingCallbacks(b); 1175 } 1176 1177 void QWEBKIT_EXPORT qt_dump_set_accepts_editing(bool b) 1178 { 1179 DumpRenderTreeSupportQt::dumpSetAcceptsEditing(b); 1180 } 1181 1182