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