/* Copyright (C) 2010 Robert Hogan Copyright (C) 2008,2009,2010 Nokia Corporation and/or its subsidiary(-ies) Copyright (C) 2007 Staikos Computing Services Inc. Copyright (C) 2007 Apple Inc. This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "config.h" #include "DumpRenderTreeSupportQt.h" #include "ApplicationCacheStorage.h" #include "CSSComputedStyleDeclaration.h" #include "ChromeClientQt.h" #include "ContainerNode.h" #include "ContextMenu.h" #include "ContextMenuClientQt.h" #include "ContextMenuController.h" #include "DeviceOrientation.h" #include "DeviceOrientationClientMockQt.h" #include "DocumentLoader.h" #include "Editor.h" #include "EditorClientQt.h" #include "Element.h" #include "FocusController.h" #include "Frame.h" #include "FrameLoaderClientQt.h" #include "FrameView.h" #if USE(JSC) #include "GCController.h" #elif USE(V8) #include "V8GCController.h" #include "V8Proxy.h" #endif #include "GeolocationClient.h" #include "GeolocationClientMock.h" #include "GeolocationController.h" #include "GeolocationError.h" #include "GeolocationPosition.h" #include "HistoryItem.h" #include "HTMLInputElement.h" #include "InspectorController.h" #include "NodeList.h" #include "NotificationPresenterClientQt.h" #include "Page.h" #include "PageGroup.h" #include "PluginDatabase.h" #include "PositionError.h" #include "PrintContext.h" #include "RenderListItem.h" #include "RenderTreeAsText.h" #include "ScriptController.h" #include "SecurityOrigin.h" #include "Settings.h" #if ENABLE(SVG) #include "SVGDocumentExtensions.h" #include "SVGSMILElement.h" #endif #include "TextIterator.h" #include "WorkerThread.h" #include #include "qwebelement.h" #include "qwebframe.h" #include "qwebframe_p.h" #include "qwebhistory.h" #include "qwebhistory_p.h" #include "qwebpage.h" #include "qwebpage_p.h" #include "qwebscriptworld.h" #if ENABLE(VIDEO) && USE(QT_MULTIMEDIA) #include "HTMLVideoElement.h" #include "MediaPlayerPrivateQt.h" #endif using namespace WebCore; QMap m_worldMap; #if ENABLE(CLIENT_BASED_GEOLOCATION) GeolocationClientMock* toGeolocationClientMock(GeolocationClient* client) { ASSERT(QWebPagePrivate::drtRun); return static_cast(client); } #endif QDRTNode::QDRTNode() : m_node(0) { } QDRTNode::QDRTNode(WebCore::Node* node) : m_node(0) { if (node) { m_node = node; m_node->ref(); } } QDRTNode::~QDRTNode() { if (m_node) m_node->deref(); } QDRTNode::QDRTNode(const QDRTNode& other) :m_node(other.m_node) { if (m_node) m_node->ref(); } QDRTNode& QDRTNode::operator=(const QDRTNode& other) { if (this != &other) { Node* otherNode = other.m_node; if (otherNode) otherNode->ref(); if (m_node) m_node->deref(); m_node = otherNode; } return *this; } DumpRenderTreeSupportQt::DumpRenderTreeSupportQt() { } DumpRenderTreeSupportQt::~DumpRenderTreeSupportQt() { } void DumpRenderTreeSupportQt::overwritePluginDirectories() { PluginDatabase* db = PluginDatabase::installedPlugins(/* populate */ false); Vector paths; String qtPath(qgetenv("QTWEBKIT_PLUGIN_PATH").data()); qtPath.split(UChar(':'), /* allowEmptyEntries */ false, paths); db->setPluginDirectories(paths); db->refresh(); } int DumpRenderTreeSupportQt::workerThreadCount() { #if ENABLE(WORKERS) return WebCore::WorkerThread::workerThreadCount(); #else return 0; #endif } void DumpRenderTreeSupportQt::setDumpRenderTreeModeEnabled(bool b) { QWebPagePrivate::drtRun = b; } void DumpRenderTreeSupportQt::setFrameFlatteningEnabled(QWebPage* page, bool enabled) { QWebPagePrivate::core(page)->settings()->setFrameFlatteningEnabled(enabled); } void DumpRenderTreeSupportQt::webPageSetGroupName(QWebPage* page, const QString& groupName) { page->handle()->page->setGroupName(groupName); } QString DumpRenderTreeSupportQt::webPageGroupName(QWebPage* page) { return page->handle()->page->groupName(); } void DumpRenderTreeSupportQt::webInspectorExecuteScript(QWebPage* page, long callId, const QString& script) { #if ENABLE(INSPECTOR) if (!page->handle()->page->inspectorController()) return; page->handle()->page->inspectorController()->evaluateForTestInFrontend(callId, script); #endif } void DumpRenderTreeSupportQt::webInspectorClose(QWebPage* page) { #if ENABLE(INSPECTOR) if (!page->handle()->page->inspectorController()) return; page->handle()->page->inspectorController()->close(); #endif } void DumpRenderTreeSupportQt::webInspectorShow(QWebPage* page) { #if ENABLE(INSPECTOR) if (!page->handle()->page->inspectorController()) return; page->handle()->page->inspectorController()->show(); #endif } void DumpRenderTreeSupportQt::setTimelineProfilingEnabled(QWebPage* page, bool enabled) { #if ENABLE(INSPECTOR) InspectorController* controller = page->handle()->page->inspectorController(); if (!controller) return; if (enabled) controller->startTimelineProfiler(); else controller->stopTimelineProfiler(); #endif } bool DumpRenderTreeSupportQt::hasDocumentElement(QWebFrame* frame) { return QWebFramePrivate::core(frame)->document()->documentElement(); } void DumpRenderTreeSupportQt::setJavaScriptProfilingEnabled(QWebFrame* frame, bool enabled) { #if ENABLE(JAVASCRIPT_DEBUGGER) && ENABLE(INSPECTOR) Frame* coreFrame = QWebFramePrivate::core(frame); InspectorController* controller = coreFrame->page()->inspectorController(); if (!controller) return; if (enabled) controller->enableProfiler(); else controller->disableProfiler(); #endif } // Pause a given CSS animation or transition on the target node at a specific time. // If the animation or transition is already paused, it will update its pause time. // This method is only intended to be used for testing the CSS animation and transition system. bool DumpRenderTreeSupportQt::pauseAnimation(QWebFrame *frame, const QString &animationName, double time, const QString &elementId) { Frame* coreFrame = QWebFramePrivate::core(frame); if (!coreFrame) return false; AnimationController* controller = coreFrame->animation(); if (!controller) return false; Document* doc = coreFrame->document(); Q_ASSERT(doc); Node* coreNode = doc->getElementById(elementId); if (!coreNode || !coreNode->renderer()) return false; return controller->pauseAnimationAtTime(coreNode->renderer(), animationName, time); } bool DumpRenderTreeSupportQt::pauseTransitionOfProperty(QWebFrame *frame, const QString &propertyName, double time, const QString &elementId) { Frame* coreFrame = QWebFramePrivate::core(frame); if (!coreFrame) return false; AnimationController* controller = coreFrame->animation(); if (!controller) return false; Document* doc = coreFrame->document(); Q_ASSERT(doc); Node* coreNode = doc->getElementById(elementId); if (!coreNode || !coreNode->renderer()) return false; return controller->pauseTransitionAtTime(coreNode->renderer(), propertyName, time); } // Pause a given SVG animation on the target node at a specific time. // This method is only intended to be used for testing the SVG animation system. bool DumpRenderTreeSupportQt::pauseSVGAnimation(QWebFrame *frame, const QString &animationId, double time, const QString &elementId) { #if !ENABLE(SVG) return false; #else Frame* coreFrame = QWebFramePrivate::core(frame); if (!coreFrame) return false; Document* doc = coreFrame->document(); Q_ASSERT(doc); if (!doc->svgExtensions()) return false; Node* coreNode = doc->getElementById(animationId); if (!coreNode || !SVGSMILElement::isSMILElement(coreNode)) return false; return doc->accessSVGExtensions()->sampleAnimationAtTime(elementId, static_cast(coreNode), time); #endif } // Returns the total number of currently running animations (includes both CSS transitions and CSS animations). int DumpRenderTreeSupportQt::numberOfActiveAnimations(QWebFrame *frame) { Frame* coreFrame = QWebFramePrivate::core(frame); if (!coreFrame) return false; AnimationController* controller = coreFrame->animation(); if (!controller) return false; return controller->numberOfActiveAnimations(); } void DumpRenderTreeSupportQt::suspendAnimations(QWebFrame *frame) { Frame* coreFrame = QWebFramePrivate::core(frame); if (!coreFrame) return; AnimationController* controller = coreFrame->animation(); if (!controller) return; controller->suspendAnimations(); } void DumpRenderTreeSupportQt::resumeAnimations(QWebFrame *frame) { Frame* coreFrame = QWebFramePrivate::core(frame); if (!coreFrame) return; AnimationController* controller = coreFrame->animation(); if (!controller) return; controller->resumeAnimations(); } void DumpRenderTreeSupportQt::clearFrameName(QWebFrame* frame) { Frame* coreFrame = QWebFramePrivate::core(frame); coreFrame->tree()->clearName(); } int DumpRenderTreeSupportQt::javaScriptObjectsCount() { #if USE(JSC) return JSDOMWindowBase::commonJSGlobalData()->heap.globalObjectCount(); #elif USE(V8) // FIXME: Find a way to do this using V8. return 1; #endif } void DumpRenderTreeSupportQt::garbageCollectorCollect() { #if USE(JSC) gcController().garbageCollectNow(); #elif USE(V8) v8::V8::LowMemoryNotification(); #endif } void DumpRenderTreeSupportQt::garbageCollectorCollectOnAlternateThread(bool waitUntilDone) { #if USE(JSC) gcController().garbageCollectOnAlternateThreadForDebugging(waitUntilDone); #elif USE(V8) // FIXME: Find a way to do this using V8. garbageCollectorCollect(); #endif } // Returns the value of counter in the element specified by \a id. QString DumpRenderTreeSupportQt::counterValueForElementById(QWebFrame* frame, const QString& id) { Frame* coreFrame = QWebFramePrivate::core(frame); if (Document* document = coreFrame->document()) { if (Element* element = document->getElementById(id)) return WebCore::counterValueForElement(element); } return QString(); } int DumpRenderTreeSupportQt::pageNumberForElementById(QWebFrame* frame, const QString& id, float width, float height) { Frame* coreFrame = QWebFramePrivate::core(frame); if (!coreFrame) return -1; Element* element = coreFrame->document()->getElementById(AtomicString(id)); if (!element) return -1; return PrintContext::pageNumberForElement(element, FloatSize(width, height)); } int DumpRenderTreeSupportQt::numberOfPages(QWebFrame* frame, float width, float height) { Frame* coreFrame = QWebFramePrivate::core(frame); if (!coreFrame) return -1; return PrintContext::numberOfPages(coreFrame, FloatSize(width, height)); } // Suspend active DOM objects in this frame. void DumpRenderTreeSupportQt::suspendActiveDOMObjects(QWebFrame* frame) { Frame* coreFrame = QWebFramePrivate::core(frame); if (coreFrame->document()) // FIXME: This function should be changed take a ReasonForSuspension parameter // https://bugs.webkit.org/show_bug.cgi?id=45732 coreFrame->document()->suspendActiveDOMObjects(ActiveDOMObject::JavaScriptDebuggerPaused); } // Resume active DOM objects in this frame. void DumpRenderTreeSupportQt::resumeActiveDOMObjects(QWebFrame* frame) { Frame* coreFrame = QWebFramePrivate::core(frame); if (coreFrame->document()) coreFrame->document()->resumeActiveDOMObjects(); } void DumpRenderTreeSupportQt::whiteListAccessFromOrigin(const QString& sourceOrigin, const QString& destinationProtocol, const QString& destinationHost, bool allowDestinationSubdomains) { SecurityOrigin::addOriginAccessWhitelistEntry(*SecurityOrigin::createFromString(sourceOrigin), destinationProtocol, destinationHost, allowDestinationSubdomains); } void DumpRenderTreeSupportQt::removeWhiteListAccessFromOrigin(const QString& sourceOrigin, const QString& destinationProtocol, const QString& destinationHost, bool allowDestinationSubdomains) { SecurityOrigin::removeOriginAccessWhitelistEntry(*SecurityOrigin::createFromString(sourceOrigin), destinationProtocol, destinationHost, allowDestinationSubdomains); } void DumpRenderTreeSupportQt::resetOriginAccessWhiteLists() { SecurityOrigin::resetOriginAccessWhitelists(); } void DumpRenderTreeSupportQt::setDomainRelaxationForbiddenForURLScheme(bool forbidden, const QString& scheme) { SecurityOrigin::setDomainRelaxationForbiddenForURLScheme(forbidden, scheme); } void DumpRenderTreeSupportQt::setCaretBrowsingEnabled(QWebPage* page, bool value) { page->handle()->page->settings()->setCaretBrowsingEnabled(value); } void DumpRenderTreeSupportQt::setMediaType(QWebFrame* frame, const QString& type) { WebCore::Frame* coreFrame = QWebFramePrivate::core(frame); WebCore::FrameView* view = coreFrame->view(); view->setMediaType(type); coreFrame->document()->styleSelectorChanged(RecalcStyleImmediately); view->layout(); } void DumpRenderTreeSupportQt::setSmartInsertDeleteEnabled(QWebPage* page, bool enabled) { page->d->smartInsertDeleteEnabled = enabled; } void DumpRenderTreeSupportQt::setSelectTrailingWhitespaceEnabled(QWebPage* page, bool enabled) { page->d->selectTrailingWhitespaceEnabled = enabled; } void DumpRenderTreeSupportQt::executeCoreCommandByName(QWebPage* page, const QString& name, const QString& value) { page->handle()->page->focusController()->focusedOrMainFrame()->editor()->command(name).execute(value); } bool DumpRenderTreeSupportQt::isCommandEnabled(QWebPage* page, const QString& name) { return page->handle()->page->focusController()->focusedOrMainFrame()->editor()->command(name).isEnabled(); } bool DumpRenderTreeSupportQt::findString(QWebPage* page, const QString& string, const QStringList& optionArray) { // 1. Parse the options from the array WebCore::FindOptions options = 0; const int optionCount = optionArray.size(); for (int i = 0; i < optionCount; ++i) { const QString& option = optionArray.at(i); if (option == QLatin1String("CaseInsensitive")) options |= WebCore::CaseInsensitive; else if (option == QLatin1String("AtWordStarts")) options |= WebCore::AtWordStarts; else if (option == QLatin1String("TreatMedialCapitalAsWordStart")) options |= WebCore::TreatMedialCapitalAsWordStart; else if (option == QLatin1String("Backwards")) options |= WebCore::Backwards; else if (option == QLatin1String("WrapAround")) options |= WebCore::WrapAround; else if (option == QLatin1String("StartInSelection")) options |= WebCore::StartInSelection; } // 2. find the string WebCore::Frame* frame = page->handle()->page->focusController()->focusedOrMainFrame(); return frame && frame->editor()->findString(string, options); } QString DumpRenderTreeSupportQt::markerTextForListItem(const QWebElement& listItem) { return WebCore::markerTextForListItem(listItem.m_element); } static QString convertToPropertyName(const QString& name) { QStringList parts = name.split(QLatin1Char('-')); QString camelCaseName; for (int j = 0; j < parts.count(); ++j) { QString part = parts.at(j); if (j) camelCaseName.append(part.replace(0, 1, part.left(1).toUpper())); else camelCaseName.append(part); } return camelCaseName; } QVariantMap DumpRenderTreeSupportQt::computedStyleIncludingVisitedInfo(const QWebElement& element) { QVariantMap res; WebCore::Element* webElement = element.m_element; if (!webElement) return res; RefPtr style = computedStyle(webElement, true); for (int i = 0; i < style->length(); i++) { QString name = style->item(i); QString value = (static_cast(style.get()))->getPropertyValue(name); res[convertToPropertyName(name)] = QVariant(value); } return res; } QVariantList DumpRenderTreeSupportQt::selectedRange(QWebPage* page) { WebCore::Frame* frame = page->handle()->page->focusController()->focusedOrMainFrame(); QVariantList selectedRange; RefPtr range = frame->selection()->toNormalizedRange().get(); Element* selectionRoot = frame->selection()->rootEditableElement(); Element* scope = selectionRoot ? selectionRoot : frame->document()->documentElement(); RefPtr testRange = Range::create(scope->document(), scope, 0, range->startContainer(), range->startOffset()); ASSERT(testRange->startContainer() == scope); int startPosition = TextIterator::rangeLength(testRange.get()); ExceptionCode ec; testRange->setEnd(range->endContainer(), range->endOffset(), ec); ASSERT(testRange->startContainer() == scope); int endPosition = TextIterator::rangeLength(testRange.get()); selectedRange << startPosition << (endPosition - startPosition); return selectedRange; } QVariantList DumpRenderTreeSupportQt::firstRectForCharacterRange(QWebPage* page, int location, int length) { WebCore::Frame* frame = page->handle()->page->focusController()->focusedOrMainFrame(); QVariantList rect; if ((location + length < location) && (location + length)) length = 0; Element* selectionRoot = frame->selection()->rootEditableElement(); Element* scope = selectionRoot ? selectionRoot : frame->document()->documentElement(); RefPtr range = TextIterator::rangeFromLocationAndLength(scope, location, length); if (!range) return QVariantList(); QRect resultRect = frame->editor()->firstRectForRange(range.get()); rect << resultRect.x() << resultRect.y() << resultRect.width() << resultRect.height(); return rect; } bool DumpRenderTreeSupportQt::elementDoesAutoCompleteForElementWithId(QWebFrame* frame, const QString& elementId) { Frame* coreFrame = QWebFramePrivate::core(frame); if (!coreFrame) return false; Document* doc = coreFrame->document(); Q_ASSERT(doc); Node* coreNode = doc->getElementById(elementId); if (!coreNode || !coreNode->renderer()) return false; HTMLInputElement* inputElement = static_cast(coreNode); return inputElement->isTextField() && !inputElement->isPasswordField() && inputElement->autoComplete(); } void DumpRenderTreeSupportQt::setEditingBehavior(QWebPage* page, const QString& editingBehavior) { WebCore::EditingBehaviorType coreEditingBehavior; if (editingBehavior == QLatin1String("win")) coreEditingBehavior = EditingWindowsBehavior; else if (editingBehavior == QLatin1String("mac")) coreEditingBehavior = EditingMacBehavior; else if (editingBehavior == QLatin1String("unix")) coreEditingBehavior = EditingUnixBehavior; else { ASSERT_NOT_REACHED(); return; } Page* corePage = QWebPagePrivate::core(page); if (!corePage) return; corePage->settings()->setEditingBehaviorType(coreEditingBehavior); } void DumpRenderTreeSupportQt::clearAllApplicationCaches() { #if ENABLE(OFFLINE_WEB_APPLICATIONS) WebCore::cacheStorage().empty(); WebCore::cacheStorage().vacuumDatabaseFile(); #endif } void DumpRenderTreeSupportQt::dumpFrameLoader(bool b) { FrameLoaderClientQt::dumpFrameLoaderCallbacks = b; } void DumpRenderTreeSupportQt::dumpUserGestureInFrameLoader(bool b) { FrameLoaderClientQt::dumpUserGestureInFrameLoaderCallbacks = b; } void DumpRenderTreeSupportQt::dumpResourceLoadCallbacks(bool b) { FrameLoaderClientQt::dumpResourceLoadCallbacks = b; } void DumpRenderTreeSupportQt::dumpResourceLoadCallbacksPath(const QString& path) { FrameLoaderClientQt::dumpResourceLoadCallbacksPath = path; } void DumpRenderTreeSupportQt::dumpResourceResponseMIMETypes(bool b) { FrameLoaderClientQt::dumpResourceResponseMIMETypes = b; } void DumpRenderTreeSupportQt::setWillSendRequestReturnsNullOnRedirect(bool b) { FrameLoaderClientQt::sendRequestReturnsNullOnRedirect = b; } void DumpRenderTreeSupportQt::setWillSendRequestReturnsNull(bool b) { FrameLoaderClientQt::sendRequestReturnsNull = b; } void DumpRenderTreeSupportQt::setWillSendRequestClearHeaders(const QStringList& headers) { FrameLoaderClientQt::sendRequestClearHeaders = headers; } void DumpRenderTreeSupportQt::setDeferMainResourceDataLoad(bool b) { FrameLoaderClientQt::deferMainResourceDataLoad = b; } void DumpRenderTreeSupportQt::setCustomPolicyDelegate(bool enabled, bool permissive) { FrameLoaderClientQt::policyDelegateEnabled = enabled; FrameLoaderClientQt::policyDelegatePermissive = permissive; } void DumpRenderTreeSupportQt::dumpHistoryCallbacks(bool b) { FrameLoaderClientQt::dumpHistoryCallbacks = b; } void DumpRenderTreeSupportQt::dumpVisitedLinksCallbacks(bool b) { ChromeClientQt::dumpVisitedLinksCallbacks = b; } void DumpRenderTreeSupportQt::dumpEditingCallbacks(bool b) { EditorClientQt::dumpEditingCallbacks = b; } void DumpRenderTreeSupportQt::dumpSetAcceptsEditing(bool b) { EditorClientQt::acceptsEditing = b; } void DumpRenderTreeSupportQt::dumpNotification(bool b) { #if ENABLE(NOTIFICATIONS) NotificationPresenterClientQt::dumpNotification = b; #endif } QString DumpRenderTreeSupportQt::viewportAsText(QWebPage* page, int deviceDPI, const QSize& deviceSize, const QSize& availableSize) { WebCore::ViewportArguments args = page->d->viewportArguments(); WebCore::ViewportAttributes conf = WebCore::computeViewportAttributes(args, /* desktop-width */ 980, /* device-width */ deviceSize.width(), /* device-height */ deviceSize.height(), /* device-dpi */ deviceDPI, availableSize); QString res; res = res.sprintf("viewport size %dx%d scale %f with limits [%f, %f] and userScalable %f\n", conf.layoutSize.width(), conf.layoutSize.height(), conf.initialScale, conf.minimumScale, conf.maximumScale, conf.userScalable); return res; } void DumpRenderTreeSupportQt::activeMockDeviceOrientationClient(bool b) { #if ENABLE(DEVICE_ORIENTATION) DeviceOrientationClientMockQt::mockIsActive = b; #endif } void DumpRenderTreeSupportQt::removeMockDeviceOrientation() { #if ENABLE(DEVICE_ORIENTATION) DeviceOrientationClientMockQt* client = DeviceOrientationClientMockQt::client(); delete client; #endif } void DumpRenderTreeSupportQt::setMockDeviceOrientation(bool canProvideAlpha, double alpha, bool canProvideBeta, double beta, bool canProvideGamma, double gamma) { #if ENABLE(DEVICE_ORIENTATION) DeviceOrientationClientMockQt::client()->setOrientation(canProvideAlpha, alpha, canProvideBeta, beta, canProvideGamma, gamma); #endif } void DumpRenderTreeSupportQt::resetGeolocationMock(QWebPage* page) { #if ENABLE(CLIENT_BASED_GEOLOCATION) Page* corePage = QWebPagePrivate::core(page); GeolocationClientMock* mockClient = toGeolocationClientMock(corePage->geolocationController()->client()); mockClient->reset(); #endif } void DumpRenderTreeSupportQt::setMockGeolocationPermission(QWebPage* page, bool allowed) { #if ENABLE(CLIENT_BASED_GEOLOCATION) Page* corePage = QWebPagePrivate::core(page); GeolocationClientMock* mockClient = toGeolocationClientMock(corePage->geolocationController()->client()); mockClient->setPermission(allowed); #endif } void DumpRenderTreeSupportQt::setMockGeolocationPosition(QWebPage* page, double latitude, double longitude, double accuracy) { #if ENABLE(CLIENT_BASED_GEOLOCATION) Page* corePage = QWebPagePrivate::core(page); GeolocationClientMock* mockClient = toGeolocationClientMock(corePage->geolocationController()->client()); mockClient->setPosition(GeolocationPosition::create(currentTime(), latitude, longitude, accuracy)); #endif } void DumpRenderTreeSupportQt::setMockGeolocationError(QWebPage* page, int errorCode, const QString& message) { #if ENABLE(CLIENT_BASED_GEOLOCATION) Page* corePage = QWebPagePrivate::core(page); GeolocationError::ErrorCode code = GeolocationError::PositionUnavailable; switch (errorCode) { case PositionError::PERMISSION_DENIED: code = GeolocationError::PermissionDenied; break; case PositionError::POSITION_UNAVAILABLE: code = GeolocationError::PositionUnavailable; break; } GeolocationClientMock* mockClient = static_cast(corePage->geolocationController()->client()); mockClient->setError(GeolocationError::create(code, message)); #endif } int DumpRenderTreeSupportQt::numberOfPendingGeolocationPermissionRequests(QWebPage* page) { #if ENABLE(CLIENT_BASED_GEOLOCATION) Page* corePage = QWebPagePrivate::core(page); GeolocationClientMock* mockClient = toGeolocationClientMock(corePage->geolocationController()->client()); return mockClient->numberOfPendingPermissionRequests(); #else return -1; #endif } bool DumpRenderTreeSupportQt::isTargetItem(const QWebHistoryItem& historyItem) { QWebHistoryItem it = historyItem; if (QWebHistoryItemPrivate::core(&it)->isTargetItem()) return true; return false; } QString DumpRenderTreeSupportQt::historyItemTarget(const QWebHistoryItem& historyItem) { QWebHistoryItem it = historyItem; return (QWebHistoryItemPrivate::core(&it)->target()); } QMap DumpRenderTreeSupportQt::getChildHistoryItems(const QWebHistoryItem& historyItem) { QWebHistoryItem it = historyItem; HistoryItem* item = QWebHistoryItemPrivate::core(&it); const WebCore::HistoryItemVector& children = item->children(); unsigned size = children.size(); QMap kids; for (unsigned i = 0; i < size; ++i) { QWebHistoryItem kid(new QWebHistoryItemPrivate(children[i].get())); kids.insert(DumpRenderTreeSupportQt::historyItemTarget(kid), kid); } return kids; } bool DumpRenderTreeSupportQt::shouldClose(QWebFrame* frame) { WebCore::Frame* coreFrame = QWebFramePrivate::core(frame); return coreFrame->loader()->shouldClose(); } void DumpRenderTreeSupportQt::clearScriptWorlds() { m_worldMap.clear(); } void DumpRenderTreeSupportQt::evaluateScriptInIsolatedWorld(QWebFrame* frame, int worldID, const QString& script) { QWebScriptWorld* scriptWorld; if (!worldID) { scriptWorld = new QWebScriptWorld(); } else if (!m_worldMap.contains(worldID)) { scriptWorld = new QWebScriptWorld(); m_worldMap.insert(worldID, scriptWorld); } else scriptWorld = m_worldMap.value(worldID); WebCore::Frame* coreFrame = QWebFramePrivate::core(frame); ScriptController* proxy = coreFrame->script(); if (!proxy) return; #if USE(JSC) proxy->executeScriptInWorld(scriptWorld->world(), script, true); #elif USE(V8) ScriptSourceCode source(script); Vector sources; sources.append(source); proxy->evaluateInIsolatedWorld(0, sources, true); #endif } bool DumpRenderTreeSupportQt::isPageBoxVisible(QWebFrame* frame, int pageIndex) { WebCore::Frame* coreFrame = QWebFramePrivate::core(frame); return coreFrame->document()->isPageBoxVisible(pageIndex); } QString DumpRenderTreeSupportQt::pageSizeAndMarginsInPixels(QWebFrame* frame, int pageIndex, int width, int height, int marginTop, int marginRight, int marginBottom, int marginLeft) { WebCore::Frame* coreFrame = QWebFramePrivate::core(frame); return PrintContext::pageSizeAndMarginsInPixels(coreFrame, pageIndex, width, height, marginTop, marginRight, marginBottom, marginLeft); } QString DumpRenderTreeSupportQt::pageProperty(QWebFrame* frame, const QString& propertyName, int pageNumber) { WebCore::Frame* coreFrame = QWebFramePrivate::core(frame); return PrintContext::pageProperty(coreFrame, propertyName.toUtf8().constData(), pageNumber); } void DumpRenderTreeSupportQt::addUserStyleSheet(QWebPage* page, const QString& sourceCode) { page->handle()->page->group().addUserStyleSheetToWorld(mainThreadNormalWorld(), sourceCode, QUrl(), 0, 0, WebCore::InjectInAllFrames); } void DumpRenderTreeSupportQt::simulateDesktopNotificationClick(const QString& title) { #if ENABLE(NOTIFICATIONS) NotificationPresenterClientQt::notificationPresenter()->notificationClicked(title); #endif } QString DumpRenderTreeSupportQt::plainText(const QVariant& range) { QMap map = range.toMap(); QVariant startContainer = map.value(QLatin1String("startContainer")); map = startContainer.toMap(); return map.value(QLatin1String("innerText")).toString(); } QVariantList DumpRenderTreeSupportQt::nodesFromRect(const QWebElement& document, int x, int y, unsigned top, unsigned right, unsigned bottom, unsigned left, bool ignoreClipping) { QVariantList res; WebCore::Element* webElement = document.m_element; if (!webElement) return res; Document* doc = webElement->document(); if (!doc) return res; RefPtr nodes = doc->nodesFromRect(x, y, top, right, bottom, left, ignoreClipping); for (int i = 0; i < nodes->length(); i++) { // QWebElement will be null if the Node is not an HTML Element if (nodes->item(i)->isHTMLElement()) res << QVariant::fromValue(QWebElement(nodes->item(i))); else res << QVariant::fromValue(QDRTNode(nodes->item(i))); } return res; } // API Candidate? QString DumpRenderTreeSupportQt::responseMimeType(QWebFrame* frame) { WebCore::Frame* coreFrame = QWebFramePrivate::core(frame); WebCore::DocumentLoader* docLoader = coreFrame->loader()->documentLoader(); return docLoader->responseMIMEType(); } void DumpRenderTreeSupportQt::clearOpener(QWebFrame* frame) { WebCore::Frame* coreFrame = QWebFramePrivate::core(frame); coreFrame->loader()->setOpener(0); } void DumpRenderTreeSupportQt::addURLToRedirect(const QString& origin, const QString& destination) { FrameLoaderClientQt::URLsToRedirect[origin] = destination; } static QStringList iterateContextMenu(QMenu* menu) { if (!menu) return QStringList(); QStringList items; QList actions = menu->actions(); for (int i = 0; i < actions.count(); ++i) { if (actions.at(i)->isSeparator()) items << QLatin1String(""); else items << actions.at(i)->text(); if (actions.at(i)->menu()) items << iterateContextMenu(actions.at(i)->menu()); } return items; } QStringList DumpRenderTreeSupportQt::contextMenu(QWebPage* page) { #ifndef QT_NO_CONTEXTMENU return iterateContextMenu(page->d->currentContextMenu); #else return QStringList(); #endif } double DumpRenderTreeSupportQt::defaultMinimumTimerInterval() { return Settings::defaultMinDOMTimerInterval(); } void DumpRenderTreeSupportQt::setMinimumTimerInterval(QWebPage* page, double interval) { Page* corePage = QWebPagePrivate::core(page); if (!corePage) return; corePage->settings()->setMinDOMTimerInterval(interval); } QUrl DumpRenderTreeSupportQt::mediaContentUrlByElementId(QWebFrame* frame, const QString& elementId) { QUrl res; #if ENABLE(VIDEO) && USE(QT_MULTIMEDIA) Frame* coreFrame = QWebFramePrivate::core(frame); if (!coreFrame) return res; Document* doc = coreFrame->document(); if (!doc) return res; Node* coreNode = doc->getElementById(elementId); if (!coreNode) return res; HTMLVideoElement* videoElement = static_cast(coreNode); PlatformMedia platformMedia = videoElement->platformMedia(); if (platformMedia.type != PlatformMedia::QtMediaPlayerType) return res; MediaPlayerPrivateQt* mediaPlayerQt = static_cast(platformMedia.media.qtMediaPlayer); if (mediaPlayerQt && mediaPlayerQt->mediaPlayer()) res = mediaPlayerQt->mediaPlayer()->media().canonicalUrl(); #endif return res; } // API Candidate? void DumpRenderTreeSupportQt::setAlternateHtml(QWebFrame* frame, const QString& html, const QUrl& baseUrl, const QUrl& failingUrl) { KURL kurl(baseUrl); WebCore::Frame* coreFrame = QWebFramePrivate::core(frame); WebCore::ResourceRequest request(kurl); const QByteArray utf8 = html.toUtf8(); WTF::RefPtr data = WebCore::SharedBuffer::create(utf8.constData(), utf8.length()); WebCore::SubstituteData substituteData(data, WTF::String("text/html"), WTF::String("utf-8"), failingUrl); coreFrame->loader()->load(request, substituteData, false); } QVariant DumpRenderTreeSupportQt::shadowRoot(const QWebElement& element) { WebCore::Element* webElement = element.m_element; if (!webElement) return QVariant(); ContainerNode* webShadowRoot = webElement->shadowRoot(); if (!webShadowRoot) return QVariant(); return QVariant::fromValue(QDRTNode(webShadowRoot)); } // Provide a backward compatibility with previously exported private symbols as of QtWebKit 4.6 release void QWEBKIT_EXPORT qt_resumeActiveDOMObjects(QWebFrame* frame) { DumpRenderTreeSupportQt::resumeActiveDOMObjects(frame); } void QWEBKIT_EXPORT qt_suspendActiveDOMObjects(QWebFrame* frame) { DumpRenderTreeSupportQt::suspendActiveDOMObjects(frame); } void QWEBKIT_EXPORT qt_drt_clearFrameName(QWebFrame* frame) { DumpRenderTreeSupportQt::clearFrameName(frame); } void QWEBKIT_EXPORT qt_drt_garbageCollector_collect() { DumpRenderTreeSupportQt::garbageCollectorCollect(); } void QWEBKIT_EXPORT qt_drt_garbageCollector_collectOnAlternateThread(bool waitUntilDone) { DumpRenderTreeSupportQt::garbageCollectorCollectOnAlternateThread(waitUntilDone); } int QWEBKIT_EXPORT qt_drt_javaScriptObjectsCount() { return DumpRenderTreeSupportQt::javaScriptObjectsCount(); } int QWEBKIT_EXPORT qt_drt_numberOfActiveAnimations(QWebFrame* frame) { return DumpRenderTreeSupportQt::numberOfActiveAnimations(frame); } void QWEBKIT_EXPORT qt_drt_overwritePluginDirectories() { DumpRenderTreeSupportQt::overwritePluginDirectories(); } bool QWEBKIT_EXPORT qt_drt_pauseAnimation(QWebFrame* frame, const QString& animationName, double time, const QString& elementId) { return DumpRenderTreeSupportQt::pauseAnimation(frame, animationName, time, elementId); } bool QWEBKIT_EXPORT qt_drt_pauseTransitionOfProperty(QWebFrame* frame, const QString& propertyName, double time, const QString &elementId) { return DumpRenderTreeSupportQt::pauseTransitionOfProperty(frame, propertyName, time, elementId); } void QWEBKIT_EXPORT qt_drt_resetOriginAccessWhiteLists() { DumpRenderTreeSupportQt::resetOriginAccessWhiteLists(); } void QWEBKIT_EXPORT qt_drt_run(bool b) { DumpRenderTreeSupportQt::setDumpRenderTreeModeEnabled(b); } void QWEBKIT_EXPORT qt_drt_setJavaScriptProfilingEnabled(QWebFrame* frame, bool enabled) { DumpRenderTreeSupportQt::setJavaScriptProfilingEnabled(frame, enabled); } void QWEBKIT_EXPORT qt_drt_whiteListAccessFromOrigin(const QString& sourceOrigin, const QString& destinationProtocol, const QString& destinationHost, bool allowDestinationSubdomains) { DumpRenderTreeSupportQt::whiteListAccessFromOrigin(sourceOrigin, destinationProtocol, destinationHost, allowDestinationSubdomains); } QString QWEBKIT_EXPORT qt_webpage_groupName(QWebPage* page) { return DumpRenderTreeSupportQt::webPageGroupName(page); } void QWEBKIT_EXPORT qt_webpage_setGroupName(QWebPage* page, const QString& groupName) { DumpRenderTreeSupportQt::webPageSetGroupName(page, groupName); } void QWEBKIT_EXPORT qt_dump_frame_loader(bool b) { DumpRenderTreeSupportQt::dumpFrameLoader(b); } void QWEBKIT_EXPORT qt_dump_resource_load_callbacks(bool b) { DumpRenderTreeSupportQt::dumpResourceLoadCallbacks(b); } void QWEBKIT_EXPORT qt_dump_editing_callbacks(bool b) { DumpRenderTreeSupportQt::dumpEditingCallbacks(b); } void QWEBKIT_EXPORT qt_dump_set_accepts_editing(bool b) { DumpRenderTreeSupportQt::dumpSetAcceptsEditing(b); }