Home | History | Annotate | Download | only in Api
      1 /*
      2     Copyright (C) 2008,2009 Nokia Corporation and/or its subsidiary(-ies)
      3     Copyright (C) 2007 Staikos Computing Services Inc.
      4 
      5     This library is free software; you can redistribute it and/or
      6     modify it under the terms of the GNU Library General Public
      7     License as published by the Free Software Foundation; either
      8     version 2 of the License, or (at your option) any later version.
      9 
     10     This library is distributed in the hope that it will be useful,
     11     but WITHOUT ANY WARRANTY; without even the implied warranty of
     12     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
     13     Library General Public License for more details.
     14 
     15     You should have received a copy of the GNU Library General Public License
     16     along with this library; see the file COPYING.LIB.  If not, write to
     17     the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
     18     Boston, MA 02110-1301, USA.
     19 */
     20 
     21 #include "config.h"
     22 #include "qwebframe.h"
     23 
     24 #include "Bridge.h"
     25 #include "CallFrame.h"
     26 #include "Document.h"
     27 #include "DocumentLoader.h"
     28 #include "DragData.h"
     29 #include "Element.h"
     30 #include "FocusController.h"
     31 #include "Frame.h"
     32 #include "FrameLoaderClientQt.h"
     33 #include "FrameTree.h"
     34 #include "FrameView.h"
     35 #include "GCController.h"
     36 #include "GraphicsContext.h"
     37 #include "HTMLMetaElement.h"
     38 #include "HitTestResult.h"
     39 #include "IconDatabase.h"
     40 #include "InspectorController.h"
     41 #include "JSDOMBinding.h"
     42 #include "JSDOMWindowBase.h"
     43 #include "JSLock.h"
     44 #include "JSObject.h"
     45 #include "NodeList.h"
     46 #include "Page.h"
     47 #include "PlatformMouseEvent.h"
     48 #include "PlatformWheelEvent.h"
     49 #include "PrintContext.h"
     50 #include "PutPropertySlot.h"
     51 #include "RenderTreeAsText.h"
     52 #include "RenderView.h"
     53 #include "ResourceRequest.h"
     54 #include "ScriptController.h"
     55 #include "ScriptSourceCode.h"
     56 #include "ScriptValue.h"
     57 #include "Scrollbar.h"
     58 #include "SelectionController.h"
     59 #include "SubstituteData.h"
     60 #include "SVGSMILElement.h"
     61 #include "htmlediting.h"
     62 #include "markup.h"
     63 #include "qt_instance.h"
     64 #include "qt_runtime.h"
     65 #include "qwebelement.h"
     66 #include "qwebframe_p.h"
     67 #include "qwebpage.h"
     68 #include "qwebpage_p.h"
     69 #include "qwebsecurityorigin.h"
     70 #include "qwebsecurityorigin_p.h"
     71 #include "runtime_object.h"
     72 #include "runtime_root.h"
     73 #include "wtf/HashMap.h"
     74 #include <QMultiMap>
     75 #include <qdebug.h>
     76 #include <qevent.h>
     77 #include <qfileinfo.h>
     78 #include <qpainter.h>
     79 #include <qprinter.h>
     80 #include <qregion.h>
     81 #include <qnetworkrequest.h>
     82 
     83 using namespace WebCore;
     84 
     85 // from text/qfont.cpp
     86 QT_BEGIN_NAMESPACE
     87 extern Q_GUI_EXPORT int qt_defaultDpi();
     88 QT_END_NAMESPACE
     89 
     90 bool QWEBKIT_EXPORT qt_drt_hasDocumentElement(QWebFrame* qframe)
     91 {
     92     return QWebFramePrivate::core(qframe)->document()->documentElement();
     93 }
     94 
     95 void QWEBKIT_EXPORT qt_drt_setJavaScriptProfilingEnabled(QWebFrame* qframe, bool enabled)
     96 {
     97 #if ENABLE(JAVASCRIPT_DEBUGGER)
     98     Frame* frame = QWebFramePrivate::core(qframe);
     99     InspectorController* controller = frame->page()->inspectorController();
    100     if (!controller)
    101         return;
    102     if (enabled)
    103         controller->enableProfiler();
    104     else
    105         controller->disableProfiler();
    106 #endif
    107 }
    108 
    109 // Pause a given CSS animation or transition on the target node at a specific time.
    110 // If the animation or transition is already paused, it will update its pause time.
    111 // This method is only intended to be used for testing the CSS animation and transition system.
    112 bool QWEBKIT_EXPORT qt_drt_pauseAnimation(QWebFrame *qframe, const QString &animationName, double time, const QString &elementId)
    113 {
    114     Frame* frame = QWebFramePrivate::core(qframe);
    115     if (!frame)
    116         return false;
    117 
    118     AnimationController* controller = frame->animation();
    119     if (!controller)
    120         return false;
    121 
    122     Document* doc = frame->document();
    123     Q_ASSERT(doc);
    124 
    125     Node* coreNode = doc->getElementById(elementId);
    126     if (!coreNode || !coreNode->renderer())
    127         return false;
    128 
    129     return controller->pauseAnimationAtTime(coreNode->renderer(), animationName, time);
    130 }
    131 
    132 bool QWEBKIT_EXPORT qt_drt_pauseTransitionOfProperty(QWebFrame *qframe, const QString &propertyName, double time, const QString &elementId)
    133 {
    134     Frame* frame = QWebFramePrivate::core(qframe);
    135     if (!frame)
    136         return false;
    137 
    138     AnimationController* controller = frame->animation();
    139     if (!controller)
    140         return false;
    141 
    142     Document* doc = frame->document();
    143     Q_ASSERT(doc);
    144 
    145     Node* coreNode = doc->getElementById(elementId);
    146     if (!coreNode || !coreNode->renderer())
    147         return false;
    148 
    149     return controller->pauseTransitionAtTime(coreNode->renderer(), propertyName, time);
    150 }
    151 
    152 // Pause a given SVG animation on the target node at a specific time.
    153 // This method is only intended to be used for testing the SVG animation system.
    154 bool QWEBKIT_EXPORT qt_drt_pauseSVGAnimation(QWebFrame *qframe, const QString &animationId, double time, const QString &elementId)
    155 {
    156 #if !ENABLE(SVG)
    157     return false;
    158 #else
    159     Frame* frame = QWebFramePrivate::core(qframe);
    160     if (!frame)
    161         return false;
    162 
    163     Document* doc = frame->document();
    164     Q_ASSERT(doc);
    165 
    166     if (!doc->svgExtensions())
    167         return false;
    168 
    169     Node* coreNode = doc->getElementById(animationId);
    170     if (!coreNode || !SVGSMILElement::isSMILElement(coreNode))
    171         return false;
    172 
    173     return doc->accessSVGExtensions()->sampleAnimationAtTime(elementId, static_cast<SVGSMILElement*>(coreNode), time);
    174 #endif
    175 }
    176 
    177 // Returns the total number of currently running animations (includes both CSS transitions and CSS animations).
    178 int QWEBKIT_EXPORT qt_drt_numberOfActiveAnimations(QWebFrame *qframe)
    179 {
    180     Frame* frame = QWebFramePrivate::core(qframe);
    181     if (!frame)
    182         return false;
    183 
    184     AnimationController* controller = frame->animation();
    185     if (!controller)
    186         return false;
    187 
    188     return controller->numberOfActiveAnimations();
    189 }
    190 
    191 void QWEBKIT_EXPORT qt_drt_clearFrameName(QWebFrame* qFrame)
    192 {
    193     Frame* frame = QWebFramePrivate::core(qFrame);
    194     frame->tree()->clearName();
    195 }
    196 
    197 int QWEBKIT_EXPORT qt_drt_javaScriptObjectsCount()
    198 {
    199     return JSDOMWindowBase::commonJSGlobalData()->heap.globalObjectCount();
    200 }
    201 
    202 void QWEBKIT_EXPORT qt_drt_garbageCollector_collect()
    203 {
    204     gcController().garbageCollectNow();
    205 }
    206 
    207 void QWEBKIT_EXPORT qt_drt_garbageCollector_collectOnAlternateThread(bool waitUntilDone)
    208 {
    209     gcController().garbageCollectOnAlternateThreadForDebugging(waitUntilDone);
    210 }
    211 
    212 // Returns the value of counter in the element specified by \a id.
    213 QString QWEBKIT_EXPORT qt_drt_counterValueForElementById(QWebFrame* qFrame, const QString& id)
    214 {
    215     Frame* frame = QWebFramePrivate::core(qFrame);
    216     if (Document* document = frame->document()) {
    217         Element* element = document->getElementById(id);
    218         return WebCore::counterValueForElement(element);
    219     }
    220     return QString();
    221 }
    222 
    223 int QWEBKIT_EXPORT qt_drt_pageNumberForElementById(QWebFrame* qFrame, const QString& id, float width, float height)
    224 {
    225     Frame* frame = QWebFramePrivate::core(qFrame);
    226     if (!frame)
    227         return -1;
    228 
    229     Element* element = frame->document()->getElementById(AtomicString(id));
    230     if (!element)
    231         return -1;
    232 
    233     return PrintContext::pageNumberForElement(element, FloatSize(width, height));
    234 }
    235 
    236 // Suspend active DOM objects in this frame.
    237 void QWEBKIT_EXPORT qt_suspendActiveDOMObjects(QWebFrame* qFrame)
    238 {
    239     Frame* frame = QWebFramePrivate::core(qFrame);
    240     if (frame->document())
    241         frame->document()->suspendActiveDOMObjects();
    242 }
    243 
    244 // Resume active DOM objects in this frame.
    245 void QWEBKIT_EXPORT qt_resumeActiveDOMObjects(QWebFrame* qFrame)
    246 {
    247     Frame* frame = QWebFramePrivate::core(qFrame);
    248     if (frame->document())
    249         frame->document()->resumeActiveDOMObjects();
    250 }
    251 
    252 QWebFrameData::QWebFrameData(WebCore::Page* parentPage, WebCore::Frame* parentFrame,
    253                              WebCore::HTMLFrameOwnerElement* ownerFrameElement,
    254                              const WebCore::String& frameName)
    255     : name(frameName)
    256     , ownerElement(ownerFrameElement)
    257     , page(parentPage)
    258     , allowsScrolling(true)
    259     , marginWidth(0)
    260     , marginHeight(0)
    261 {
    262     frameLoaderClient = new FrameLoaderClientQt();
    263     frame = Frame::create(page, ownerElement, frameLoaderClient);
    264 
    265     // FIXME: All of the below should probably be moved over into WebCore
    266     frame->tree()->setName(name);
    267     if (parentFrame)
    268         parentFrame->tree()->appendChild(frame);
    269 }
    270 
    271 void QWebFramePrivate::init(QWebFrame *qframe, QWebFrameData *frameData)
    272 {
    273     q = qframe;
    274 
    275     allowsScrolling = frameData->allowsScrolling;
    276     marginWidth = frameData->marginWidth;
    277     marginHeight = frameData->marginHeight;
    278     frame = frameData->frame.get();
    279     frameLoaderClient = frameData->frameLoaderClient;
    280     frameLoaderClient->setFrame(qframe, frame);
    281 
    282     frame->init();
    283 }
    284 
    285 WebCore::Scrollbar* QWebFramePrivate::horizontalScrollBar() const
    286 {
    287     if (!frame->view())
    288         return 0;
    289     return frame->view()->horizontalScrollbar();
    290 }
    291 
    292 WebCore::Scrollbar* QWebFramePrivate::verticalScrollBar() const
    293 {
    294     if (!frame->view())
    295         return 0;
    296     return frame->view()->verticalScrollbar();
    297 }
    298 
    299 void QWebFramePrivate::renderContentsLayerAbsoluteCoords(GraphicsContext* context, const QRegion& clip)
    300 {
    301     if (!frame->view() || !frame->contentRenderer())
    302         return;
    303 
    304     QVector<QRect> vector = clip.rects();
    305     if (vector.isEmpty())
    306         return;
    307 
    308     QPainter* painter = context->platformContext();
    309 
    310     WebCore::FrameView* view = frame->view();
    311     view->layoutIfNeededRecursive();
    312 
    313     for (int i = 0; i < vector.size(); ++i) {
    314         const QRect& clipRect = vector.at(i);
    315 
    316         painter->save();
    317         painter->setClipRect(clipRect, Qt::IntersectClip);
    318 
    319         context->save();
    320         view->paintContents(context, clipRect);
    321         context->restore();
    322 
    323         painter->restore();
    324     }
    325 }
    326 
    327 void QWebFramePrivate::renderRelativeCoords(GraphicsContext* context, QWebFrame::RenderLayer layer, const QRegion& clip)
    328 {
    329     if (!frame->view() || !frame->contentRenderer())
    330         return;
    331 
    332     QVector<QRect> vector = clip.rects();
    333     if (vector.isEmpty())
    334         return;
    335 
    336     QPainter* painter = context->platformContext();
    337 
    338     WebCore::FrameView* view = frame->view();
    339     view->layoutIfNeededRecursive();
    340 
    341     for (int i = 0; i < vector.size(); ++i) {
    342         const QRect& clipRect = vector.at(i);
    343 
    344         QRect intersectedRect = clipRect.intersected(view->frameRect());
    345 
    346         painter->save();
    347         painter->setClipRect(clipRect, Qt::IntersectClip);
    348 
    349         int x = view->x();
    350         int y = view->y();
    351 
    352         if (layer & QWebFrame::ContentsLayer) {
    353             context->save();
    354 
    355             int scrollX = view->scrollX();
    356             int scrollY = view->scrollY();
    357 
    358             QRect rect = intersectedRect;
    359             context->translate(x, y);
    360             rect.translate(-x, -y);
    361             context->translate(-scrollX, -scrollY);
    362             rect.translate(scrollX, scrollY);
    363             context->clip(view->visibleContentRect());
    364 
    365             view->paintContents(context, rect);
    366 
    367             context->restore();
    368         }
    369 
    370         if (layer & QWebFrame::ScrollBarLayer
    371             && !view->scrollbarsSuppressed()
    372             && (view->horizontalScrollbar() || view->verticalScrollbar())) {
    373             context->save();
    374 
    375             QRect rect = intersectedRect;
    376             context->translate(x, y);
    377             rect.translate(-x, -y);
    378 
    379             view->paintScrollbars(context, rect);
    380 
    381             context->restore();
    382         }
    383 
    384 #if ENABLE(PAN_SCROLLING)
    385         if (layer & QWebFrame::PanIconLayer)
    386             view->paintPanScrollIcon(context);
    387 #endif
    388 
    389         painter->restore();
    390     }
    391 }
    392 
    393 bool QWebFramePrivate::scrollOverflow(int dx, int dy)
    394 {
    395     if (!frame || !frame->document() || !frame->eventHandler())
    396         return false;
    397 
    398     Node* node = frame->document()->focusedNode();
    399     if (!node)
    400         node = frame->document()->elementFromPoint(frame->eventHandler()->currentMousePosition().x(),
    401                                                    frame->eventHandler()->currentMousePosition().y());
    402     if (!node)
    403         return false;
    404 
    405     RenderObject* renderer = node->renderer();
    406     if (!renderer)
    407         return false;
    408 
    409     if (renderer->isListBox())
    410         return false;
    411 
    412     RenderLayer* renderLayer = renderer->enclosingLayer();
    413     if (!renderLayer)
    414         return false;
    415 
    416     bool scrolledHorizontal = false;
    417     bool scrolledVertical = false;
    418 
    419     if (dx > 0)
    420         scrolledHorizontal = renderLayer->scroll(ScrollRight, ScrollByPixel, dx);
    421     else if (dx < 0)
    422         scrolledHorizontal = renderLayer->scroll(ScrollLeft, ScrollByPixel, qAbs(dx));
    423 
    424     if (dy > 0)
    425         scrolledVertical = renderLayer->scroll(ScrollDown, ScrollByPixel, dy);
    426     else if (dy < 0)
    427         scrolledVertical = renderLayer->scroll(ScrollUp, ScrollByPixel, qAbs(dy));
    428 
    429     return (scrolledHorizontal || scrolledVertical);
    430 }
    431 
    432 /*!
    433     \class QWebFrame
    434     \since 4.4
    435     \brief The QWebFrame class represents a frame in a web page.
    436 
    437     \inmodule QtWebKit
    438 
    439     QWebFrame represents a frame inside a web page. Each QWebPage
    440     object contains at least one frame, the main frame, obtained using
    441     QWebPage::mainFrame(). Additional frames will be created for HTML
    442     \c{<frame>} or \c{<iframe>} elements.
    443 
    444     A frame can be loaded using load() or setUrl(). Alternatively, if you have
    445     the HTML content readily available, you can use setHtml() instead.
    446 
    447     The page() function returns a pointer to the web page object. See
    448     \l{QWebView}{Elements of QWebView} for an explanation of how web
    449     frames are related to a web page and web view.
    450 
    451     The QWebFrame class also offers methods to retrieve both the URL currently
    452     loaded by the frame (see url()) as well as the URL originally requested
    453     to be loaded (see requestedUrl()). These methods make possible the retrieval
    454     of the URL before and after a DNS resolution or a redirection occurs during
    455     the load process. The requestedUrl() also matches to the URL added to the
    456     frame history (\l{QWebHistory}) if load is successful.
    457 
    458     The title of an HTML frame can be accessed with the title() property.
    459     Additionally, a frame may also specify an icon, which can be accessed
    460     using the icon() property. If the title or the icon changes, the
    461     corresponding titleChanged() and iconChanged() signals will be emitted.
    462     The zoomFactor() property can be used to change the overall size
    463     of the content displayed in the frame.
    464 
    465     QWebFrame objects are created and controlled by the web page. You
    466     can connect to the web page's \l{QWebPage::}{frameCreated()} signal
    467     to be notified when a new frame is created.
    468 
    469     The hitTestContent() function can be used to programmatically examine the
    470     contents of a frame.
    471 
    472     A QWebFrame can be printed onto a QPrinter using the print() function.
    473     This function is marked as a slot and can be conveniently connected to
    474     \l{QPrintPreviewDialog}'s \l{QPrintPreviewDialog::}{paintRequested()}
    475     signal.
    476 
    477     \sa QWebPage
    478 */
    479 
    480 /*!
    481     \enum QWebFrame::RenderLayer
    482 
    483     This enum describes the layers available for rendering using \l{QWebFrame::}{render()}.
    484     The layers can be OR-ed together from the following list:
    485 
    486     \value ContentsLayer The web content of the frame
    487     \value ScrollBarLayer The scrollbars of the frame
    488     \value PanIconLayer The icon used when panning the frame
    489 
    490     \value AllLayers Includes all the above layers
    491 */
    492 
    493 QWebFrame::QWebFrame(QWebPage *parent, QWebFrameData *frameData)
    494     : QObject(parent)
    495     , d(new QWebFramePrivate)
    496 {
    497     d->page = parent;
    498     d->init(this, frameData);
    499 
    500     if (!frameData->url.isEmpty()) {
    501         WebCore::ResourceRequest request(frameData->url, frameData->referrer);
    502         d->frame->loader()->load(request, frameData->name, false);
    503     }
    504 }
    505 
    506 QWebFrame::QWebFrame(QWebFrame *parent, QWebFrameData *frameData)
    507     : QObject(parent)
    508     , d(new QWebFramePrivate)
    509 {
    510     d->page = parent->d->page;
    511     d->init(this, frameData);
    512 }
    513 
    514 QWebFrame::~QWebFrame()
    515 {
    516     if (d->frame && d->frame->loader() && d->frame->loader()->client())
    517         static_cast<FrameLoaderClientQt*>(d->frame->loader()->client())->m_webFrame = 0;
    518 
    519     delete d;
    520 }
    521 
    522 /*!
    523     Make \a object available under \a name from within the frame's JavaScript
    524     context. The \a object will be inserted as a child of the frame's window
    525     object.
    526 
    527     Qt properties will be exposed as JavaScript properties and slots as
    528     JavaScript methods.
    529 
    530     If you want to ensure that your QObjects remain accessible after loading a
    531     new URL, you should add them in a slot connected to the
    532     javaScriptWindowObjectCleared() signal.
    533 
    534     If Javascript is not enabled for this page, then this method does nothing.
    535 
    536     The \a object will never be explicitly deleted by QtWebKit.
    537 */
    538 void QWebFrame::addToJavaScriptWindowObject(const QString &name, QObject *object)
    539 {
    540     addToJavaScriptWindowObject(name, object, QScriptEngine::QtOwnership);
    541 }
    542 
    543 /*!
    544     \fn void QWebFrame::addToJavaScriptWindowObject(const QString &name, QObject *object, QScriptEngine::ValueOwnership own)
    545     \overload
    546 
    547     Make \a object available under \a name from within the frame's JavaScript
    548     context. The \a object will be inserted as a child of the frame's window
    549     object.
    550 
    551     Qt properties will be exposed as JavaScript properties and slots as
    552     JavaScript methods.
    553 
    554     If you want to ensure that your QObjects remain accessible after loading a
    555     new URL, you should add them in a slot connected to the
    556     javaScriptWindowObjectCleared() signal.
    557 
    558     If Javascript is not enabled for this page, then this method does nothing.
    559 
    560     The ownership of \a object is specified using \a own.
    561 */
    562 void QWebFrame::addToJavaScriptWindowObject(const QString &name, QObject *object, QScriptEngine::ValueOwnership ownership)
    563 {
    564     if (!page()->settings()->testAttribute(QWebSettings::JavascriptEnabled))
    565         return;
    566 
    567     JSC::JSLock lock(JSC::SilenceAssertionsOnly);
    568     JSDOMWindow* window = toJSDOMWindow(d->frame, mainThreadNormalWorld());
    569     JSC::Bindings::RootObject* root = d->frame->script()->bindingRootObject();
    570     if (!window) {
    571         qDebug() << "Warning: couldn't get window object";
    572         return;
    573     }
    574 
    575     JSC::ExecState* exec = window->globalExec();
    576 
    577     JSC::JSObject* runtimeObject =
    578             JSC::Bindings::QtInstance::getQtInstance(object, root, ownership)->createRuntimeObject(exec);
    579 
    580     JSC::PutPropertySlot slot;
    581     window->put(exec, JSC::Identifier(exec, (const UChar *) name.constData(), name.length()), runtimeObject, slot);
    582 }
    583 
    584 /*!
    585     Returns the frame's content as HTML, enclosed in HTML and BODY tags.
    586 
    587     \sa setHtml(), toPlainText()
    588 */
    589 QString QWebFrame::toHtml() const
    590 {
    591     if (!d->frame->document())
    592         return QString();
    593     return createMarkup(d->frame->document());
    594 }
    595 
    596 /*!
    597     Returns the content of this frame converted to plain text, completely
    598     stripped of all HTML formatting.
    599 
    600     \sa toHtml()
    601 */
    602 QString QWebFrame::toPlainText() const
    603 {
    604     if (d->frame->view() && d->frame->view()->layoutPending())
    605         d->frame->view()->layout();
    606 
    607     Element *documentElement = d->frame->document()->documentElement();
    608     if (documentElement)
    609         return documentElement->innerText();
    610     return QString();
    611 }
    612 
    613 /*!
    614     Returns a dump of the rendering tree. This is mainly useful for debugging
    615     html.
    616 */
    617 QString QWebFrame::renderTreeDump() const
    618 {
    619     if (d->frame->view() && d->frame->view()->layoutPending())
    620         d->frame->view()->layout();
    621 
    622     return externalRepresentation(d->frame);
    623 }
    624 
    625 /*!
    626     \property QWebFrame::title
    627     \brief the title of the frame as defined by the HTML &lt;title&gt; element
    628 
    629     \sa titleChanged()
    630 */
    631 
    632 QString QWebFrame::title() const
    633 {
    634     if (d->frame->document())
    635         return d->frame->loader()->documentLoader()->title();
    636     return QString();
    637 }
    638 
    639 /*!
    640     \since 4.5
    641     \brief Returns the meta data in this frame as a QMultiMap
    642 
    643     The meta data consists of the name and content attributes of the
    644     of the \c{<meta>} tags in the HTML document.
    645 
    646     For example:
    647 
    648     \code
    649     <html>
    650         <head>
    651             <meta name="description" content="This document is a tutorial about Qt development">
    652             <meta name="keywords" content="Qt, WebKit, Programming">
    653         </head>
    654         ...
    655     </html>
    656     \endcode
    657 
    658     Given the above HTML code the metaData() function will return a map with two entries:
    659     \table
    660     \header \o Key
    661             \o Value
    662     \row    \o "description"
    663             \o "This document is a tutorial about Qt development"
    664     \row    \o "keywords"
    665             \o "Qt, WebKit, Programming"
    666     \endtable
    667 
    668     This function returns a multi map to support multiple meta tags with the same attribute name.
    669 */
    670 QMultiMap<QString, QString> QWebFrame::metaData() const
    671 {
    672     if (!d->frame->document())
    673        return QMap<QString, QString>();
    674 
    675     QMultiMap<QString, QString> map;
    676     Document* doc = d->frame->document();
    677     RefPtr<NodeList> list = doc->getElementsByTagName("meta");
    678     unsigned len = list->length();
    679     for (unsigned i = 0; i < len; i++) {
    680         HTMLMetaElement* meta = static_cast<HTMLMetaElement*>(list->item(i));
    681         map.insert(meta->name(), meta->content());
    682     }
    683     return map;
    684 }
    685 
    686 static inline QUrl ensureAbsoluteUrl(const QUrl &url)
    687 {
    688     if (!url.isRelative())
    689         return url;
    690 
    691     return QUrl::fromLocalFile(QFileInfo(url.toLocalFile()).absoluteFilePath());
    692 }
    693 
    694 /*!
    695     \property QWebFrame::url
    696     \brief the url of the frame currently viewed
    697 
    698     \sa urlChanged()
    699 */
    700 
    701 void QWebFrame::setUrl(const QUrl &url)
    702 {
    703     d->frame->loader()->begin(ensureAbsoluteUrl(url));
    704     d->frame->loader()->end();
    705     load(ensureAbsoluteUrl(url));
    706 }
    707 
    708 QUrl QWebFrame::url() const
    709 {
    710     return d->frame->loader()->url();
    711 }
    712 
    713 /*!
    714     \since 4.6
    715     \property QWebFrame::requestedUrl
    716 
    717     The URL requested to loaded by the frame currently viewed. The URL may differ from
    718     the one returned by url() if a DNS resolution or a redirection occurs.
    719 
    720     \sa url(), setUrl()
    721 */
    722 QUrl QWebFrame::requestedUrl() const
    723 {
    724     // There are some possible edge cases to be handled here,
    725     // apart from checking if activeDocumentLoader is valid:
    726     //
    727     // * Method can be called while processing an unsucessful load.
    728     //   In this case, frameLoaderClient will hold the current error
    729     //   (m_loadError), and we will make use of it to recover the 'failingURL'.
    730     // * If the 'failingURL' holds a null'ed string though, we fallback
    731     //   to 'outgoingReferrer' (it yet is safer than originalRequest).
    732     FrameLoader* loader = d->frame->loader();
    733     FrameLoaderClientQt* loaderClient = d->frameLoaderClient;
    734 
    735     if (!loader->activeDocumentLoader()
    736         || !loaderClient->m_loadError.isNull()) {
    737         if (!loaderClient->m_loadError.failingURL().isNull())
    738             return QUrl(loaderClient->m_loadError.failingURL());
    739         else if (!loader->outgoingReferrer().isEmpty())
    740             return QUrl(loader->outgoingReferrer());
    741     }
    742 
    743     return loader->originalRequest().url();
    744 }
    745 /*!
    746     \since 4.6
    747     \property QWebFrame::baseUrl
    748     \brief the base URL of the frame, can be used to resolve relative URLs
    749     \since 4.6
    750 */
    751 
    752 QUrl QWebFrame::baseUrl() const
    753 {
    754     return d->frame->loader()->baseURL();
    755 }
    756 
    757 /*!
    758     \property QWebFrame::icon
    759     \brief the icon associated with this frame
    760 
    761     \sa iconChanged(), QWebSettings::iconForUrl()
    762 */
    763 
    764 QIcon QWebFrame::icon() const
    765 {
    766     return QWebSettings::iconForUrl(d->frame->loader()->url());
    767 }
    768 
    769 /*!
    770   The name of this frame as defined by the parent frame.
    771 */
    772 QString QWebFrame::frameName() const
    773 {
    774     return d->frame->tree()->name();
    775 }
    776 
    777 /*!
    778   The web page that contains this frame.
    779 */
    780 QWebPage *QWebFrame::page() const
    781 {
    782     return d->page;
    783 }
    784 
    785 /*!
    786   Loads \a url into this frame.
    787 
    788   \note The view remains the same until enough data has arrived to display the new \a url.
    789 
    790   \sa setUrl(), setHtml(), setContent()
    791 */
    792 void QWebFrame::load(const QUrl &url)
    793 {
    794     load(QNetworkRequest(ensureAbsoluteUrl(url)));
    795 }
    796 
    797 /*!
    798   Loads a network request, \a req, into this frame, using the method specified in \a
    799   operation.
    800 
    801   \a body is optional and is only used for POST operations.
    802 
    803   \note The view remains the same until enough data has arrived to display the new \a url.
    804 
    805   \sa setUrl()
    806 */
    807 void QWebFrame::load(const QNetworkRequest &req,
    808                      QNetworkAccessManager::Operation operation,
    809                      const QByteArray &body)
    810 {
    811     if (d->parentFrame())
    812         d->page->d->insideOpenCall = true;
    813 
    814     QUrl url = ensureAbsoluteUrl(req.url());
    815 
    816     WebCore::ResourceRequest request(url);
    817 
    818     switch (operation) {
    819         case QNetworkAccessManager::HeadOperation:
    820             request.setHTTPMethod("HEAD");
    821             break;
    822         case QNetworkAccessManager::GetOperation:
    823             request.setHTTPMethod("GET");
    824             break;
    825         case QNetworkAccessManager::PutOperation:
    826             request.setHTTPMethod("PUT");
    827             break;
    828         case QNetworkAccessManager::PostOperation:
    829             request.setHTTPMethod("POST");
    830             break;
    831 #if QT_VERSION >= 0x040600
    832         case QNetworkAccessManager::DeleteOperation:
    833             request.setHTTPMethod("DELETE");
    834             break;
    835 #endif
    836         case QNetworkAccessManager::UnknownOperation:
    837             // eh?
    838             break;
    839     }
    840 
    841     QList<QByteArray> httpHeaders = req.rawHeaderList();
    842     for (int i = 0; i < httpHeaders.size(); ++i) {
    843         const QByteArray &headerName = httpHeaders.at(i);
    844         request.addHTTPHeaderField(QString::fromLatin1(headerName), QString::fromLatin1(req.rawHeader(headerName)));
    845     }
    846 
    847     if (!body.isEmpty())
    848         request.setHTTPBody(WebCore::FormData::create(body.constData(), body.size()));
    849 
    850     d->frame->loader()->load(request, false);
    851 
    852     if (d->parentFrame())
    853         d->page->d->insideOpenCall = false;
    854 }
    855 
    856 /*!
    857   Sets the content of this frame to \a html. \a baseUrl is optional and used to resolve relative
    858   URLs in the document, such as referenced images or stylesheets.
    859 
    860   The \a html is loaded immediately; external objects are loaded asynchronously.
    861 
    862   When using this method WebKit assumes that external resources such as JavaScript programs or style
    863   sheets are encoded in UTF-8 unless otherwise specified. For example, the encoding of an external
    864   script can be specified through the charset attribute of the HTML script tag. It is also possible
    865   for the encoding to be specified by web server.
    866 
    867   \note This method will not affect session or global history for the frame.
    868 
    869   \sa toHtml(), setContent()
    870 */
    871 void QWebFrame::setHtml(const QString &html, const QUrl &baseUrl)
    872 {
    873     KURL kurl(baseUrl);
    874     WebCore::ResourceRequest request(kurl);
    875     const QByteArray utf8 = html.toUtf8();
    876     WTF::RefPtr<WebCore::SharedBuffer> data = WebCore::SharedBuffer::create(utf8.constData(), utf8.length());
    877     WebCore::SubstituteData substituteData(data, WebCore::String("text/html"), WebCore::String("utf-8"), KURL());
    878     d->frame->loader()->load(request, substituteData, false);
    879 }
    880 
    881 /*!
    882   Sets the content of this frame to the specified content \a data. If the \a mimeType argument
    883   is empty it is currently assumed that the content is HTML but in future versions we may introduce
    884   auto-detection.
    885 
    886   External objects referenced in the content are located relative to \a baseUrl.
    887 
    888   The \a data is loaded immediately; external objects are loaded asynchronously.
    889 
    890   \note This method will not affect session or global history for the frame.
    891 
    892   \sa toHtml(), setHtml()
    893 */
    894 void QWebFrame::setContent(const QByteArray &data, const QString &mimeType, const QUrl &baseUrl)
    895 {
    896     KURL kurl(baseUrl);
    897     WebCore::ResourceRequest request(kurl);
    898     WTF::RefPtr<WebCore::SharedBuffer> buffer = WebCore::SharedBuffer::create(data.constData(), data.length());
    899     QString actualMimeType = mimeType;
    900     if (actualMimeType.isEmpty())
    901         actualMimeType = QLatin1String("text/html");
    902     WebCore::SubstituteData substituteData(buffer, WebCore::String(actualMimeType), WebCore::String(), KURL());
    903     d->frame->loader()->load(request, substituteData, false);
    904 }
    905 
    906 /*!
    907   Returns the parent frame of this frame, or 0 if the frame is the web pages
    908   main frame.
    909 
    910   This is equivalent to qobject_cast<QWebFrame*>(frame->parent()).
    911 
    912   \sa childFrames()
    913 */
    914 QWebFrame *QWebFrame::parentFrame() const
    915 {
    916     return d->parentFrame();
    917 }
    918 
    919 /*!
    920   Returns a list of all frames that are direct children of this frame.
    921 
    922   \sa parentFrame()
    923 */
    924 QList<QWebFrame*> QWebFrame::childFrames() const
    925 {
    926     QList<QWebFrame*> rc;
    927     if (d->frame) {
    928         FrameTree *tree = d->frame->tree();
    929         for (Frame *child = tree->firstChild(); child; child = child->tree()->nextSibling()) {
    930             FrameLoader *loader = child->loader();
    931             FrameLoaderClientQt *client = static_cast<FrameLoaderClientQt*>(loader->client());
    932             if (client)
    933                 rc.append(client->webFrame());
    934         }
    935 
    936     }
    937     return rc;
    938 }
    939 
    940 /*!
    941     Returns the scrollbar policy for the scrollbar defined by \a orientation.
    942 */
    943 Qt::ScrollBarPolicy QWebFrame::scrollBarPolicy(Qt::Orientation orientation) const
    944 {
    945     if (orientation == Qt::Horizontal)
    946         return d->horizontalScrollBarPolicy;
    947     return d->verticalScrollBarPolicy;
    948 }
    949 
    950 /*!
    951     Sets the scrollbar policy for the scrollbar defined by \a orientation to \a policy.
    952 */
    953 void QWebFrame::setScrollBarPolicy(Qt::Orientation orientation, Qt::ScrollBarPolicy policy)
    954 {
    955     Q_ASSERT((int)ScrollbarAuto == (int)Qt::ScrollBarAsNeeded);
    956     Q_ASSERT((int)ScrollbarAlwaysOff == (int)Qt::ScrollBarAlwaysOff);
    957     Q_ASSERT((int)ScrollbarAlwaysOn == (int)Qt::ScrollBarAlwaysOn);
    958 
    959     if (orientation == Qt::Horizontal) {
    960         d->horizontalScrollBarPolicy = policy;
    961         if (d->frame->view()) {
    962             d->frame->view()->setHorizontalScrollbarMode((ScrollbarMode)policy);
    963             d->frame->view()->updateCanHaveScrollbars();
    964         }
    965     } else {
    966         d->verticalScrollBarPolicy = policy;
    967         if (d->frame->view()) {
    968             d->frame->view()->setVerticalScrollbarMode((ScrollbarMode)policy);
    969             d->frame->view()->updateCanHaveScrollbars();
    970         }
    971     }
    972 }
    973 
    974 /*!
    975   Sets the current \a value for the scrollbar with orientation \a orientation.
    976 
    977   The scrollbar forces the \a value to be within the legal range: minimum <= value <= maximum.
    978 
    979   Changing the value also updates the thumb position.
    980 
    981   \sa scrollBarMinimum(), scrollBarMaximum()
    982 */
    983 void QWebFrame::setScrollBarValue(Qt::Orientation orientation, int value)
    984 {
    985     Scrollbar *sb;
    986     sb = (orientation == Qt::Horizontal) ? d->horizontalScrollBar() : d->verticalScrollBar();
    987     if (sb) {
    988         if (value < 0)
    989             value = 0;
    990         else if (value > scrollBarMaximum(orientation))
    991             value = scrollBarMaximum(orientation);
    992         sb->setValue(value);
    993     }
    994 }
    995 
    996 /*!
    997   Returns the current value for the scrollbar with orientation \a orientation, or 0
    998   if no scrollbar is found for \a orientation.
    999 
   1000   \sa scrollBarMinimum(), scrollBarMaximum()
   1001 */
   1002 int QWebFrame::scrollBarValue(Qt::Orientation orientation) const
   1003 {
   1004     Scrollbar *sb;
   1005     sb = (orientation == Qt::Horizontal) ? d->horizontalScrollBar() : d->verticalScrollBar();
   1006     if (sb)
   1007         return sb->value();
   1008     return 0;
   1009 }
   1010 
   1011 /*!
   1012   Returns the maximum value for the scrollbar with orientation \a orientation, or 0
   1013   if no scrollbar is found for \a orientation.
   1014 
   1015   \sa scrollBarMinimum()
   1016 */
   1017 int QWebFrame::scrollBarMaximum(Qt::Orientation orientation) const
   1018 {
   1019     Scrollbar *sb;
   1020     sb = (orientation == Qt::Horizontal) ? d->horizontalScrollBar() : d->verticalScrollBar();
   1021     if (sb)
   1022         return sb->maximum();
   1023     return 0;
   1024 }
   1025 
   1026 /*!
   1027   Returns the minimum value for the scrollbar with orientation \a orientation.
   1028 
   1029   The minimum value is always 0.
   1030 
   1031   \sa scrollBarMaximum()
   1032 */
   1033 int QWebFrame::scrollBarMinimum(Qt::Orientation orientation) const
   1034 {
   1035     Q_UNUSED(orientation)
   1036     return 0;
   1037 }
   1038 
   1039 /*!
   1040   \since 4.6
   1041   Returns the geometry for the scrollbar with orientation \a orientation.
   1042 
   1043   If the scrollbar does not exist an empty rect is returned.
   1044 */
   1045 QRect QWebFrame::scrollBarGeometry(Qt::Orientation orientation) const
   1046 {
   1047     Scrollbar *sb;
   1048     sb = (orientation == Qt::Horizontal) ? d->horizontalScrollBar() : d->verticalScrollBar();
   1049     if (sb)
   1050         return sb->frameRect();
   1051     return QRect();
   1052 }
   1053 
   1054 /*!
   1055   \since 4.5
   1056   Scrolls the frame \a dx pixels to the right and \a dy pixels downward. Both
   1057   \a dx and \a dy may be negative.
   1058 
   1059   \sa QWebFrame::scrollPosition
   1060 */
   1061 
   1062 void QWebFrame::scroll(int dx, int dy)
   1063 {
   1064     if (!d->frame->view())
   1065         return;
   1066 
   1067     d->frame->view()->scrollBy(IntSize(dx, dy));
   1068 }
   1069 
   1070 /*!
   1071   \since 4.7
   1072   Scrolls nested frames starting at this frame, \a dx pixels to the right
   1073   and \a dy pixels downward. Both \a dx and \a dy may be negative. First attempts
   1074   to scroll elements with CSS overflow followed by this frame. If this
   1075   frame doesn't scroll, attempts to scroll the parent
   1076 
   1077   \sa QWebFrame::scroll
   1078 */
   1079 bool QWebFrame::scrollRecursively(int dx, int dy)
   1080 {
   1081     bool scrolledHorizontal = false;
   1082     bool scrolledVertical = false;
   1083     bool scrolledOverflow = d->scrollOverflow(dx, dy);
   1084 
   1085     if (!scrolledOverflow) {
   1086         Frame* frame = d->frame;
   1087         if (!frame || !frame->view())
   1088             return false;
   1089 
   1090         do {
   1091             IntSize scrollOffset = frame->view()->scrollOffset();
   1092             IntPoint maxScrollOffset = frame->view()->maximumScrollPosition();
   1093 
   1094             if (dx > 0) // scroll right
   1095                 scrolledHorizontal = scrollOffset.width() < maxScrollOffset.x();
   1096             else if (dx < 0) // scroll left
   1097                 scrolledHorizontal = scrollOffset.width() > 0;
   1098 
   1099             if (dy > 0) // scroll down
   1100                 scrolledVertical = scrollOffset.height() < maxScrollOffset.y();
   1101             else if (dy < 0) //scroll up
   1102                 scrolledVertical = scrollOffset.height() > 0;
   1103 
   1104             if (scrolledHorizontal || scrolledVertical) {
   1105                 frame->view()->scrollBy(IntSize(dx, dy));
   1106                 return true;
   1107             }
   1108             frame = frame->tree()->parent();
   1109         } while (frame && frame->view());
   1110     }
   1111     return (scrolledHorizontal || scrolledVertical || scrolledOverflow);
   1112 }
   1113 
   1114 bool QWEBKIT_EXPORT qtwebkit_webframe_scrollRecursively(QWebFrame* qFrame, int dx, int dy)
   1115 {
   1116     return qFrame->scrollRecursively(dx, dy);
   1117 }
   1118 
   1119 /*!
   1120   \property QWebFrame::scrollPosition
   1121   \since 4.5
   1122   \brief the position the frame is currently scrolled to.
   1123 */
   1124 
   1125 QPoint QWebFrame::scrollPosition() const
   1126 {
   1127     if (!d->frame->view())
   1128         return QPoint(0, 0);
   1129 
   1130     IntSize ofs = d->frame->view()->scrollOffset();
   1131     return QPoint(ofs.width(), ofs.height());
   1132 }
   1133 
   1134 void QWebFrame::setScrollPosition(const QPoint &pos)
   1135 {
   1136     QPoint current = scrollPosition();
   1137     int dx = pos.x() - current.x();
   1138     int dy = pos.y() - current.y();
   1139     scroll(dx, dy);
   1140 }
   1141 
   1142 /*!
   1143   \since 4.6
   1144   Render the \a layer of the frame using \a painter clipping to \a clip.
   1145 
   1146   \sa print()
   1147 */
   1148 
   1149 void QWebFrame::render(QPainter* painter, RenderLayer layer, const QRegion& clip)
   1150 {
   1151     GraphicsContext context(painter);
   1152     if (context.paintingDisabled() && !context.updatingControlTints())
   1153         return;
   1154 
   1155     if (!clip.isEmpty())
   1156         d->renderRelativeCoords(&context, layer, clip);
   1157     else if (d->frame->view())
   1158         d->renderRelativeCoords(&context, layer, QRegion(d->frame->view()->frameRect()));
   1159 }
   1160 
   1161 /*!
   1162   Render the frame into \a painter clipping to \a clip.
   1163 */
   1164 void QWebFrame::render(QPainter* painter, const QRegion& clip)
   1165 {
   1166     GraphicsContext context(painter);
   1167     if (context.paintingDisabled() && !context.updatingControlTints())
   1168         return;
   1169 
   1170     d->renderRelativeCoords(&context, AllLayers, clip);
   1171 }
   1172 
   1173 /*!
   1174   Render the frame into \a painter.
   1175 */
   1176 void QWebFrame::render(QPainter* painter)
   1177 {
   1178     if (!d->frame->view())
   1179         return;
   1180 
   1181     GraphicsContext context(painter);
   1182     if (context.paintingDisabled() && !context.updatingControlTints())
   1183         return;
   1184 
   1185     d->renderRelativeCoords(&context, AllLayers, QRegion(d->frame->view()->frameRect()));
   1186 }
   1187 
   1188 /*!
   1189     \property QWebFrame::textSizeMultiplier
   1190     \brief the scaling factor for all text in the frame
   1191     \obsolete
   1192 
   1193     Use setZoomFactor instead, in combination with the ZoomTextOnly attribute in
   1194     QWebSettings.
   1195 
   1196     \note Setting this property also enables the ZoomTextOnly attribute in
   1197     QWebSettings.
   1198 */
   1199 
   1200 /*!
   1201     Sets the value of the multiplier used to scale the text in a Web frame to
   1202     the \a factor specified.
   1203 */
   1204 void QWebFrame::setTextSizeMultiplier(qreal factor)
   1205 {
   1206     d->frame->setZoomFactor(factor, /*isTextOnly*/true);
   1207 }
   1208 
   1209 /*!
   1210     Returns the value of the multiplier used to scale the text in a Web frame.
   1211 */
   1212 qreal QWebFrame::textSizeMultiplier() const
   1213 {
   1214     return d->frame->zoomFactor();
   1215 }
   1216 
   1217 /*!
   1218     \property QWebFrame::zoomFactor
   1219     \since 4.5
   1220     \brief the zoom factor for the frame
   1221 */
   1222 
   1223 void QWebFrame::setZoomFactor(qreal factor)
   1224 {
   1225     d->frame->setZoomFactor(factor, d->frame->isZoomFactorTextOnly());
   1226 }
   1227 
   1228 qreal QWebFrame::zoomFactor() const
   1229 {
   1230     return d->frame->zoomFactor();
   1231 }
   1232 
   1233 /*!
   1234     \property QWebFrame::focus
   1235     \since 4.6
   1236 
   1237     Returns true if this frame has keyboard input focus; otherwise, returns false.
   1238 */
   1239 bool QWebFrame::hasFocus() const
   1240 {
   1241     WebCore::Frame* ff = d->frame->page()->focusController()->focusedFrame();
   1242     return ff && QWebFramePrivate::kit(ff) == this;
   1243 }
   1244 
   1245 /*!
   1246     \since 4.6
   1247 
   1248     Gives keyboard input focus to this frame.
   1249 */
   1250 void QWebFrame::setFocus()
   1251 {
   1252     QWebFramePrivate::core(this)->page()->focusController()->setFocusedFrame(QWebFramePrivate::core(this));
   1253 }
   1254 
   1255 /*!
   1256     Returns the position of the frame relative to it's parent frame.
   1257 */
   1258 QPoint QWebFrame::pos() const
   1259 {
   1260     if (!d->frame->view())
   1261         return QPoint();
   1262 
   1263     return d->frame->view()->frameRect().topLeft();
   1264 }
   1265 
   1266 /*!
   1267     Return the geometry of the frame relative to it's parent frame.
   1268 */
   1269 QRect QWebFrame::geometry() const
   1270 {
   1271     if (!d->frame->view())
   1272         return QRect();
   1273     return d->frame->view()->frameRect();
   1274 }
   1275 
   1276 /*!
   1277     \property QWebFrame::contentsSize
   1278     \brief the size of the contents in this frame
   1279 
   1280     \sa contentsSizeChanged()
   1281 */
   1282 QSize QWebFrame::contentsSize() const
   1283 {
   1284     FrameView *view = d->frame->view();
   1285     if (!view)
   1286         return QSize();
   1287     return QSize(view->contentsWidth(), view->contentsHeight());
   1288 }
   1289 
   1290 /*!
   1291     \since 4.6
   1292 
   1293     Returns the document element of this frame.
   1294 
   1295     The document element provides access to the entire structured
   1296     content of the frame.
   1297 */
   1298 QWebElement QWebFrame::documentElement() const
   1299 {
   1300     WebCore::Document *doc = d->frame->document();
   1301     if (!doc)
   1302         return QWebElement();
   1303     return QWebElement(doc->documentElement());
   1304 }
   1305 
   1306 /*!
   1307     \since 4.6
   1308     Returns a new list of elements matching the given CSS selector \a selectorQuery.
   1309     If there are no matching elements, an empty list is returned.
   1310 
   1311     \l{http://www.w3.org/TR/REC-CSS2/selector.html#q1}{Standard CSS2 selector} syntax is
   1312     used for the query.
   1313 
   1314     \sa QWebElement::findAll()
   1315 */
   1316 QWebElementCollection QWebFrame::findAllElements(const QString &selectorQuery) const
   1317 {
   1318     return documentElement().findAll(selectorQuery);
   1319 }
   1320 
   1321 /*!
   1322     \since 4.6
   1323     Returns the first element in the frame's document that matches the
   1324     given CSS selector \a selectorQuery. If there is no matching element, a
   1325     null element is returned.
   1326 
   1327     \l{http://www.w3.org/TR/REC-CSS2/selector.html#q1}{Standard CSS2 selector} syntax is
   1328     used for the query.
   1329 
   1330     \sa QWebElement::findFirst()
   1331 */
   1332 QWebElement QWebFrame::findFirstElement(const QString &selectorQuery) const
   1333 {
   1334     return documentElement().findFirst(selectorQuery);
   1335 }
   1336 
   1337 /*!
   1338     Performs a hit test on the frame contents at the given position \a pos and returns the hit test result.
   1339 */
   1340 QWebHitTestResult QWebFrame::hitTestContent(const QPoint &pos) const
   1341 {
   1342     if (!d->frame->view() || !d->frame->contentRenderer())
   1343         return QWebHitTestResult();
   1344 
   1345     HitTestResult result = d->frame->eventHandler()->hitTestResultAtPoint(d->frame->view()->windowToContents(pos), /*allowShadowContent*/ false, /*ignoreClipping*/ true);
   1346 
   1347     if (result.scrollbar())
   1348         return QWebHitTestResult();
   1349 
   1350     return QWebHitTestResult(new QWebHitTestResultPrivate(result));
   1351 }
   1352 
   1353 /*! \reimp
   1354 */
   1355 bool QWebFrame::event(QEvent *e)
   1356 {
   1357     return QObject::event(e);
   1358 }
   1359 
   1360 #ifndef QT_NO_PRINTER
   1361 /*!
   1362     Prints the frame to the given \a printer.
   1363 
   1364     \sa render()
   1365 */
   1366 void QWebFrame::print(QPrinter *printer) const
   1367 {
   1368     QPainter painter;
   1369     if (!painter.begin(printer))
   1370         return;
   1371 
   1372     const qreal zoomFactorX = printer->logicalDpiX() / qt_defaultDpi();
   1373     const qreal zoomFactorY = printer->logicalDpiY() / qt_defaultDpi();
   1374 
   1375     PrintContext printContext(d->frame);
   1376     float pageHeight = 0;
   1377 
   1378     QRect qprinterRect = printer->pageRect();
   1379 
   1380     IntRect pageRect(0, 0,
   1381                      int(qprinterRect.width() / zoomFactorX),
   1382                      int(qprinterRect.height() / zoomFactorY));
   1383 
   1384     printContext.begin(pageRect.width());
   1385 
   1386     printContext.computePageRects(pageRect, /* headerHeight */ 0, /* footerHeight */ 0, /* userScaleFactor */ 1.0, pageHeight);
   1387 
   1388     int docCopies;
   1389     int pageCopies;
   1390     if (printer->collateCopies()) {
   1391         docCopies = 1;
   1392         pageCopies = printer->numCopies();
   1393     } else {
   1394         docCopies = printer->numCopies();
   1395         pageCopies = 1;
   1396     }
   1397 
   1398     int fromPage = printer->fromPage();
   1399     int toPage = printer->toPage();
   1400     bool ascending = true;
   1401 
   1402     if (fromPage == 0 && toPage == 0) {
   1403         fromPage = 1;
   1404         toPage = printContext.pageCount();
   1405     }
   1406     // paranoia check
   1407     fromPage = qMax(1, fromPage);
   1408     toPage = qMin(printContext.pageCount(), toPage);
   1409     if (toPage < fromPage) {
   1410         // if the user entered a page range outside the actual number
   1411         // of printable pages, just return
   1412         return;
   1413     }
   1414 
   1415     if (printer->pageOrder() == QPrinter::LastPageFirst) {
   1416         int tmp = fromPage;
   1417         fromPage = toPage;
   1418         toPage = tmp;
   1419         ascending = false;
   1420     }
   1421 
   1422     painter.scale(zoomFactorX, zoomFactorY);
   1423     GraphicsContext ctx(&painter);
   1424 
   1425     for (int i = 0; i < docCopies; ++i) {
   1426         int page = fromPage;
   1427         while (true) {
   1428             for (int j = 0; j < pageCopies; ++j) {
   1429                 if (printer->printerState() == QPrinter::Aborted
   1430                     || printer->printerState() == QPrinter::Error) {
   1431                     printContext.end();
   1432                     return;
   1433                 }
   1434                 printContext.spoolPage(ctx, page - 1, pageRect.width());
   1435                 if (j < pageCopies - 1)
   1436                     printer->newPage();
   1437             }
   1438 
   1439             if (page == toPage)
   1440                 break;
   1441 
   1442             if (ascending)
   1443                 ++page;
   1444             else
   1445                 --page;
   1446 
   1447             printer->newPage();
   1448         }
   1449 
   1450         if ( i < docCopies - 1)
   1451             printer->newPage();
   1452     }
   1453 
   1454     printContext.end();
   1455 }
   1456 #endif // QT_NO_PRINTER
   1457 
   1458 /*!
   1459     Evaluates the JavaScript defined by \a scriptSource using this frame as context
   1460     and returns the result of the last executed statement.
   1461 
   1462     \sa addToJavaScriptWindowObject(), javaScriptWindowObjectCleared()
   1463 */
   1464 QVariant QWebFrame::evaluateJavaScript(const QString& scriptSource)
   1465 {
   1466     ScriptController *proxy = d->frame->script();
   1467     QVariant rc;
   1468     if (proxy) {
   1469         JSC::JSValue v = d->frame->script()->executeScript(ScriptSourceCode(scriptSource)).jsValue();
   1470         int distance = 0;
   1471         rc = JSC::Bindings::convertValueToQVariant(proxy->globalObject(mainThreadNormalWorld())->globalExec(), v, QMetaType::Void, &distance);
   1472     }
   1473     return rc;
   1474 }
   1475 
   1476 /*!
   1477     \since 4.5
   1478 
   1479     Returns the frame's security origin.
   1480 */
   1481 QWebSecurityOrigin QWebFrame::securityOrigin() const
   1482 {
   1483     QWebFrame* that = const_cast<QWebFrame*>(this);
   1484     QWebSecurityOriginPrivate* priv = new QWebSecurityOriginPrivate(QWebFramePrivate::core(that)->document()->securityOrigin());
   1485     return QWebSecurityOrigin(priv);
   1486 }
   1487 
   1488 WebCore::Frame* QWebFramePrivate::core(QWebFrame* webFrame)
   1489 {
   1490     return webFrame->d->frame;
   1491 }
   1492 
   1493 QWebFrame* QWebFramePrivate::kit(WebCore::Frame* coreFrame)
   1494 {
   1495     return static_cast<FrameLoaderClientQt*>(coreFrame->loader()->client())->webFrame();
   1496 }
   1497 
   1498 
   1499 /*!
   1500     \fn void QWebFrame::javaScriptWindowObjectCleared()
   1501 
   1502     This signal is emitted whenever the global window object of the JavaScript
   1503     environment is cleared, e.g., before starting a new load.
   1504 
   1505     If you intend to add QObjects to a QWebFrame using
   1506     addToJavaScriptWindowObject(), you should add them in a slot connected
   1507     to this signal. This ensures that your objects remain accessible when
   1508     loading new URLs.
   1509 */
   1510 
   1511 /*!
   1512     \fn void QWebFrame::provisionalLoad()
   1513     \internal
   1514 */
   1515 
   1516 /*!
   1517     \fn void QWebFrame::titleChanged(const QString &title)
   1518 
   1519     This signal is emitted whenever the title of the frame changes.
   1520     The \a title string specifies the new title.
   1521 
   1522     \sa title()
   1523 */
   1524 
   1525 /*!
   1526     \fn void QWebFrame::urlChanged(const QUrl &url)
   1527 
   1528     This signal is emitted with the URL of the frame when the frame's title is
   1529     received. The new URL is specified by \a url.
   1530 
   1531     \sa url()
   1532 */
   1533 
   1534 /*!
   1535     \fn void QWebFrame::initialLayoutCompleted()
   1536 
   1537     This signal is emitted when the frame is laid out the first time.
   1538     This is the first time you will see contents displayed on the frame.
   1539 
   1540     \note A frame can be laid out multiple times.
   1541 */
   1542 
   1543 /*!
   1544   \fn void QWebFrame::iconChanged()
   1545 
   1546   This signal is emitted when the icon ("favicon") associated with the frame
   1547   has been loaded.
   1548 
   1549   \sa icon()
   1550 */
   1551 
   1552 /*!
   1553   \fn void QWebFrame::contentsSizeChanged(const QSize &size)
   1554   \since 4.6
   1555 
   1556   This signal is emitted when the frame's contents size changes
   1557   to \a size.
   1558 
   1559   \sa contentsSize()
   1560 */
   1561 
   1562 /*!
   1563     \fn void QWebFrame::loadStarted()
   1564     \since 4.6
   1565 
   1566     This signal is emitted when a new load of this frame is started.
   1567 
   1568     \sa loadFinished()
   1569 */
   1570 
   1571 /*!
   1572     \fn void QWebFrame::loadFinished(bool ok)
   1573     \since 4.6
   1574 
   1575     This signal is emitted when a load of this frame is finished.
   1576     \a ok will indicate whether the load was successful or any error occurred.
   1577 
   1578     \sa loadStarted()
   1579 */
   1580 
   1581 /*!
   1582     \class QWebHitTestResult
   1583     \since 4.4
   1584     \brief The QWebHitTestResult class provides information about the web
   1585     page content after a hit test.
   1586 
   1587     \inmodule QtWebKit
   1588 
   1589     QWebHitTestResult is returned by QWebFrame::hitTestContent() to provide
   1590     information about the content of the web page at the specified position.
   1591 */
   1592 
   1593 /*!
   1594     \internal
   1595 */
   1596 QWebHitTestResult::QWebHitTestResult(QWebHitTestResultPrivate *priv)
   1597     : d(priv)
   1598 {
   1599 }
   1600 
   1601 QWebHitTestResultPrivate::QWebHitTestResultPrivate(const WebCore::HitTestResult &hitTest)
   1602     : isContentEditable(false)
   1603     , isContentSelected(false)
   1604     , isScrollBar(false)
   1605 {
   1606     if (!hitTest.innerNode())
   1607         return;
   1608     pos = hitTest.point();
   1609     WebCore::TextDirection dir;
   1610     title = hitTest.title(dir);
   1611     linkText = hitTest.textContent();
   1612     linkUrl = hitTest.absoluteLinkURL();
   1613     linkTitle = hitTest.titleDisplayString();
   1614     alternateText = hitTest.altDisplayString();
   1615     imageUrl = hitTest.absoluteImageURL();
   1616     innerNode = hitTest.innerNode();
   1617     innerNonSharedNode = hitTest.innerNonSharedNode();
   1618     boundingRect = innerNonSharedNode ? innerNonSharedNode->renderer()->absoluteBoundingBoxRect(true) : IntRect();
   1619     WebCore::Image *img = hitTest.image();
   1620     if (img) {
   1621         QPixmap *pix = img->nativeImageForCurrentFrame();
   1622         if (pix)
   1623             pixmap = *pix;
   1624     }
   1625     WebCore::Frame *wframe = hitTest.targetFrame();
   1626     if (wframe)
   1627         linkTargetFrame = QWebFramePrivate::kit(wframe);
   1628     linkElement = QWebElement(hitTest.URLElement());
   1629 
   1630     isContentEditable = hitTest.isContentEditable();
   1631     isContentSelected = hitTest.isSelected();
   1632     isScrollBar = hitTest.scrollbar();
   1633 
   1634     if (innerNonSharedNode && innerNonSharedNode->document()
   1635         && innerNonSharedNode->document()->frame())
   1636         frame = QWebFramePrivate::kit(innerNonSharedNode->document()->frame());
   1637 
   1638     enclosingBlock = QWebElement(WebCore::enclosingBlock(innerNode.get()));
   1639 }
   1640 
   1641 /*!
   1642     Constructs a null hit test result.
   1643 */
   1644 QWebHitTestResult::QWebHitTestResult()
   1645     : d(0)
   1646 {
   1647 }
   1648 
   1649 /*!
   1650     Constructs a hit test result from \a other.
   1651 */
   1652 QWebHitTestResult::QWebHitTestResult(const QWebHitTestResult &other)
   1653     : d(0)
   1654 {
   1655     if (other.d)
   1656         d = new QWebHitTestResultPrivate(*other.d);
   1657 }
   1658 
   1659 /*!
   1660     Assigns the \a other hit test result to this.
   1661 */
   1662 QWebHitTestResult &QWebHitTestResult::operator=(const QWebHitTestResult &other)
   1663 {
   1664     if (this != &other) {
   1665         if (other.d) {
   1666             if (!d)
   1667                 d = new QWebHitTestResultPrivate;
   1668             *d = *other.d;
   1669         } else {
   1670             delete d;
   1671             d = 0;
   1672         }
   1673     }
   1674     return *this;
   1675 }
   1676 
   1677 /*!
   1678     Destructor.
   1679 */
   1680 QWebHitTestResult::~QWebHitTestResult()
   1681 {
   1682     delete d;
   1683 }
   1684 
   1685 /*!
   1686     Returns true if the hit test result is null; otherwise returns false.
   1687 */
   1688 bool QWebHitTestResult::isNull() const
   1689 {
   1690     return !d;
   1691 }
   1692 
   1693 /*!
   1694     Returns the position where the hit test occured.
   1695 */
   1696 QPoint QWebHitTestResult::pos() const
   1697 {
   1698     if (!d)
   1699         return QPoint();
   1700     return d->pos;
   1701 }
   1702 
   1703 /*!
   1704     \since 4.5
   1705     Returns the bounding rect of the element.
   1706 */
   1707 QRect QWebHitTestResult::boundingRect() const
   1708 {
   1709     if (!d)
   1710         return QRect();
   1711     return d->boundingRect;
   1712 }
   1713 
   1714 /*!
   1715     \since 4.6
   1716     Returns the block element that encloses the element hit.
   1717 
   1718     A block element is an element that is rendered using the
   1719     CSS "block" style. This includes for example text
   1720     paragraphs.
   1721 */
   1722 QWebElement QWebHitTestResult::enclosingBlockElement() const
   1723 {
   1724     if (!d)
   1725         return QWebElement();
   1726     return d->enclosingBlock;
   1727 }
   1728 
   1729 /*!
   1730     Returns the title of the nearest enclosing HTML element.
   1731 */
   1732 QString QWebHitTestResult::title() const
   1733 {
   1734     if (!d)
   1735         return QString();
   1736     return d->title;
   1737 }
   1738 
   1739 /*!
   1740     Returns the text of the link.
   1741 */
   1742 QString QWebHitTestResult::linkText() const
   1743 {
   1744     if (!d)
   1745         return QString();
   1746     return d->linkText;
   1747 }
   1748 
   1749 /*!
   1750     Returns the url to which the link points to.
   1751 */
   1752 QUrl QWebHitTestResult::linkUrl() const
   1753 {
   1754     if (!d)
   1755         return QUrl();
   1756     return d->linkUrl;
   1757 }
   1758 
   1759 /*!
   1760     Returns the title of the link.
   1761 */
   1762 QUrl QWebHitTestResult::linkTitle() const
   1763 {
   1764     if (!d)
   1765         return QUrl();
   1766     return d->linkTitle;
   1767 }
   1768 
   1769 /*!
   1770   \since 4.6
   1771   Returns the element that represents the link.
   1772 
   1773   \sa linkTargetFrame()
   1774 */
   1775 QWebElement QWebHitTestResult::linkElement() const
   1776 {
   1777     if (!d)
   1778         return QWebElement();
   1779     return d->linkElement;
   1780 }
   1781 
   1782 /*!
   1783     Returns the frame that will load the link if it is activated.
   1784 
   1785     \sa linkElement()
   1786 */
   1787 QWebFrame *QWebHitTestResult::linkTargetFrame() const
   1788 {
   1789     if (!d)
   1790         return 0;
   1791     return d->linkTargetFrame;
   1792 }
   1793 
   1794 /*!
   1795     Returns the alternate text of the element. This corresponds to the HTML alt attribute.
   1796 */
   1797 QString QWebHitTestResult::alternateText() const
   1798 {
   1799     if (!d)
   1800         return QString();
   1801     return d->alternateText;
   1802 }
   1803 
   1804 /*!
   1805     Returns the url of the image.
   1806 */
   1807 QUrl QWebHitTestResult::imageUrl() const
   1808 {
   1809     if (!d)
   1810         return QUrl();
   1811     return d->imageUrl;
   1812 }
   1813 
   1814 /*!
   1815     Returns a QPixmap containing the image. A null pixmap is returned if the
   1816     element being tested is not an image.
   1817 */
   1818 QPixmap QWebHitTestResult::pixmap() const
   1819 {
   1820     if (!d)
   1821         return QPixmap();
   1822     return d->pixmap;
   1823 }
   1824 
   1825 /*!
   1826     Returns true if the content is editable by the user; otherwise returns false.
   1827 */
   1828 bool QWebHitTestResult::isContentEditable() const
   1829 {
   1830     if (!d)
   1831         return false;
   1832     return d->isContentEditable;
   1833 }
   1834 
   1835 /*!
   1836     Returns true if the content tested is part of the selection; otherwise returns false.
   1837 */
   1838 bool QWebHitTestResult::isContentSelected() const
   1839 {
   1840     if (!d)
   1841         return false;
   1842     return d->isContentSelected;
   1843 }
   1844 
   1845 /*!
   1846     \since 4.6
   1847     Returns the underlying DOM element as QWebElement.
   1848 */
   1849 QWebElement QWebHitTestResult::element() const
   1850 {
   1851     if (!d || !d->innerNonSharedNode || !d->innerNonSharedNode->isElementNode())
   1852         return QWebElement();
   1853 
   1854     return QWebElement(static_cast<WebCore::Element*>(d->innerNonSharedNode.get()));
   1855 }
   1856 
   1857 /*!
   1858     Returns the frame the hit test was executed in.
   1859 */
   1860 QWebFrame *QWebHitTestResult::frame() const
   1861 {
   1862     if (!d)
   1863         return 0;
   1864     return d->frame;
   1865 }
   1866