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