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