/* Copyright (C) 2008,2009 Nokia Corporation and/or its subsidiary(-ies) Copyright (C) 2007 Staikos Computing Services 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 "qwebframe.h" #include "Bridge.h" #include "CallFrame.h" #include "Document.h" #include "DocumentLoader.h" #include "DragData.h" #include "Element.h" #include "FocusController.h" #include "Frame.h" #include "FrameLoaderClientQt.h" #include "FrameTree.h" #include "FrameView.h" #include "GCController.h" #include "GraphicsContext.h" #include "HTMLMetaElement.h" #include "HitTestResult.h" #include "IconDatabase.h" #include "InspectorController.h" #include "JSDOMBinding.h" #include "JSDOMWindowBase.h" #include "JSLock.h" #include "JSObject.h" #include "NodeList.h" #include "Page.h" #include "PlatformMouseEvent.h" #include "PlatformWheelEvent.h" #include "PrintContext.h" #include "PutPropertySlot.h" #include "RenderTreeAsText.h" #include "RenderView.h" #include "ResourceRequest.h" #include "ScriptController.h" #include "ScriptSourceCode.h" #include "ScriptValue.h" #include "Scrollbar.h" #include "SelectionController.h" #include "SubstituteData.h" #include "SVGSMILElement.h" #include "htmlediting.h" #include "markup.h" #include "qt_instance.h" #include "qt_runtime.h" #include "qwebelement.h" #include "qwebframe_p.h" #include "qwebpage.h" #include "qwebpage_p.h" #include "qwebsecurityorigin.h" #include "qwebsecurityorigin_p.h" #include "runtime_object.h" #include "runtime_root.h" #include "wtf/HashMap.h" #include #include #include #include #include #include #include #include using namespace WebCore; // from text/qfont.cpp QT_BEGIN_NAMESPACE extern Q_GUI_EXPORT int qt_defaultDpi(); QT_END_NAMESPACE bool QWEBKIT_EXPORT qt_drt_hasDocumentElement(QWebFrame* qframe) { return QWebFramePrivate::core(qframe)->document()->documentElement(); } void QWEBKIT_EXPORT qt_drt_setJavaScriptProfilingEnabled(QWebFrame* qframe, bool enabled) { #if ENABLE(JAVASCRIPT_DEBUGGER) Frame* frame = QWebFramePrivate::core(qframe); InspectorController* controller = frame->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 QWEBKIT_EXPORT qt_drt_pauseAnimation(QWebFrame *qframe, const QString &animationName, double time, const QString &elementId) { Frame* frame = QWebFramePrivate::core(qframe); if (!frame) return false; AnimationController* controller = frame->animation(); if (!controller) return false; Document* doc = frame->document(); Q_ASSERT(doc); Node* coreNode = doc->getElementById(elementId); if (!coreNode || !coreNode->renderer()) return false; return controller->pauseAnimationAtTime(coreNode->renderer(), animationName, time); } bool QWEBKIT_EXPORT qt_drt_pauseTransitionOfProperty(QWebFrame *qframe, const QString &propertyName, double time, const QString &elementId) { Frame* frame = QWebFramePrivate::core(qframe); if (!frame) return false; AnimationController* controller = frame->animation(); if (!controller) return false; Document* doc = frame->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 QWEBKIT_EXPORT qt_drt_pauseSVGAnimation(QWebFrame *qframe, const QString &animationId, double time, const QString &elementId) { #if !ENABLE(SVG) return false; #else Frame* frame = QWebFramePrivate::core(qframe); if (!frame) return false; Document* doc = frame->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 QWEBKIT_EXPORT qt_drt_numberOfActiveAnimations(QWebFrame *qframe) { Frame* frame = QWebFramePrivate::core(qframe); if (!frame) return false; AnimationController* controller = frame->animation(); if (!controller) return false; return controller->numberOfActiveAnimations(); } void QWEBKIT_EXPORT qt_drt_clearFrameName(QWebFrame* qFrame) { Frame* frame = QWebFramePrivate::core(qFrame); frame->tree()->clearName(); } int QWEBKIT_EXPORT qt_drt_javaScriptObjectsCount() { return JSDOMWindowBase::commonJSGlobalData()->heap.globalObjectCount(); } void QWEBKIT_EXPORT qt_drt_garbageCollector_collect() { gcController().garbageCollectNow(); } void QWEBKIT_EXPORT qt_drt_garbageCollector_collectOnAlternateThread(bool waitUntilDone) { gcController().garbageCollectOnAlternateThreadForDebugging(waitUntilDone); } // Returns the value of counter in the element specified by \a id. QString QWEBKIT_EXPORT qt_drt_counterValueForElementById(QWebFrame* qFrame, const QString& id) { Frame* frame = QWebFramePrivate::core(qFrame); if (Document* document = frame->document()) { Element* element = document->getElementById(id); return WebCore::counterValueForElement(element); } return QString(); } int QWEBKIT_EXPORT qt_drt_pageNumberForElementById(QWebFrame* qFrame, const QString& id, float width, float height) { Frame* frame = QWebFramePrivate::core(qFrame); if (!frame) return -1; Element* element = frame->document()->getElementById(AtomicString(id)); if (!element) return -1; return PrintContext::pageNumberForElement(element, FloatSize(width, height)); } // Suspend active DOM objects in this frame. void QWEBKIT_EXPORT qt_suspendActiveDOMObjects(QWebFrame* qFrame) { Frame* frame = QWebFramePrivate::core(qFrame); if (frame->document()) frame->document()->suspendActiveDOMObjects(); } // Resume active DOM objects in this frame. void QWEBKIT_EXPORT qt_resumeActiveDOMObjects(QWebFrame* qFrame) { Frame* frame = QWebFramePrivate::core(qFrame); if (frame->document()) frame->document()->resumeActiveDOMObjects(); } QWebFrameData::QWebFrameData(WebCore::Page* parentPage, WebCore::Frame* parentFrame, WebCore::HTMLFrameOwnerElement* ownerFrameElement, const WebCore::String& frameName) : name(frameName) , ownerElement(ownerFrameElement) , page(parentPage) , allowsScrolling(true) , marginWidth(0) , marginHeight(0) { frameLoaderClient = new FrameLoaderClientQt(); frame = Frame::create(page, ownerElement, frameLoaderClient); // FIXME: All of the below should probably be moved over into WebCore frame->tree()->setName(name); if (parentFrame) parentFrame->tree()->appendChild(frame); } void QWebFramePrivate::init(QWebFrame *qframe, QWebFrameData *frameData) { q = qframe; allowsScrolling = frameData->allowsScrolling; marginWidth = frameData->marginWidth; marginHeight = frameData->marginHeight; frame = frameData->frame.get(); frameLoaderClient = frameData->frameLoaderClient; frameLoaderClient->setFrame(qframe, frame); frame->init(); } WebCore::Scrollbar* QWebFramePrivate::horizontalScrollBar() const { if (!frame->view()) return 0; return frame->view()->horizontalScrollbar(); } WebCore::Scrollbar* QWebFramePrivate::verticalScrollBar() const { if (!frame->view()) return 0; return frame->view()->verticalScrollbar(); } void QWebFramePrivate::renderContentsLayerAbsoluteCoords(GraphicsContext* context, const QRegion& clip) { if (!frame->view() || !frame->contentRenderer()) return; QVector vector = clip.rects(); if (vector.isEmpty()) return; QPainter* painter = context->platformContext(); WebCore::FrameView* view = frame->view(); view->layoutIfNeededRecursive(); for (int i = 0; i < vector.size(); ++i) { const QRect& clipRect = vector.at(i); painter->save(); painter->setClipRect(clipRect, Qt::IntersectClip); context->save(); view->paintContents(context, clipRect); context->restore(); painter->restore(); } } void QWebFramePrivate::renderRelativeCoords(GraphicsContext* context, QWebFrame::RenderLayer layer, const QRegion& clip) { if (!frame->view() || !frame->contentRenderer()) return; QVector vector = clip.rects(); if (vector.isEmpty()) return; QPainter* painter = context->platformContext(); WebCore::FrameView* view = frame->view(); view->layoutIfNeededRecursive(); for (int i = 0; i < vector.size(); ++i) { const QRect& clipRect = vector.at(i); QRect intersectedRect = clipRect.intersected(view->frameRect()); painter->save(); painter->setClipRect(clipRect, Qt::IntersectClip); int x = view->x(); int y = view->y(); if (layer & QWebFrame::ContentsLayer) { context->save(); int scrollX = view->scrollX(); int scrollY = view->scrollY(); QRect rect = intersectedRect; context->translate(x, y); rect.translate(-x, -y); context->translate(-scrollX, -scrollY); rect.translate(scrollX, scrollY); context->clip(view->visibleContentRect()); view->paintContents(context, rect); context->restore(); } if (layer & QWebFrame::ScrollBarLayer && !view->scrollbarsSuppressed() && (view->horizontalScrollbar() || view->verticalScrollbar())) { context->save(); QRect rect = intersectedRect; context->translate(x, y); rect.translate(-x, -y); view->paintScrollbars(context, rect); context->restore(); } #if ENABLE(PAN_SCROLLING) if (layer & QWebFrame::PanIconLayer) view->paintPanScrollIcon(context); #endif painter->restore(); } } bool QWebFramePrivate::scrollOverflow(int dx, int dy) { if (!frame || !frame->document() || !frame->eventHandler()) return false; Node* node = frame->document()->focusedNode(); if (!node) node = frame->document()->elementFromPoint(frame->eventHandler()->currentMousePosition().x(), frame->eventHandler()->currentMousePosition().y()); if (!node) return false; RenderObject* renderer = node->renderer(); if (!renderer) return false; if (renderer->isListBox()) return false; RenderLayer* renderLayer = renderer->enclosingLayer(); if (!renderLayer) return false; bool scrolledHorizontal = false; bool scrolledVertical = false; if (dx > 0) scrolledHorizontal = renderLayer->scroll(ScrollRight, ScrollByPixel, dx); else if (dx < 0) scrolledHorizontal = renderLayer->scroll(ScrollLeft, ScrollByPixel, qAbs(dx)); if (dy > 0) scrolledVertical = renderLayer->scroll(ScrollDown, ScrollByPixel, dy); else if (dy < 0) scrolledVertical = renderLayer->scroll(ScrollUp, ScrollByPixel, qAbs(dy)); return (scrolledHorizontal || scrolledVertical); } /*! \class QWebFrame \since 4.4 \brief The QWebFrame class represents a frame in a web page. \inmodule QtWebKit QWebFrame represents a frame inside a web page. Each QWebPage object contains at least one frame, the main frame, obtained using QWebPage::mainFrame(). Additional frames will be created for HTML \c{} or \c{