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