54e59d352be8b0edf19f9d937961b344b7e2f6eb
[WebKit-https.git] / WebKit / qt / Api / qwebframe.cpp
1 /*
2     Copyright (C) 2008 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 #include "qwebpage.h"
24 #include "qwebpage_p.h"
25 #include "qwebframe_p.h"
26 #include "qwebsecurityorigin.h"
27 #include "qwebsecurityorigin_p.h"
28
29 #include "DocumentLoader.h"
30 #include "FocusController.h"
31 #include "FrameLoaderClientQt.h"
32 #include "Frame.h"
33 #include "FrameTree.h"
34 #include "FrameView.h"
35 #include "IconDatabase.h"
36 #include "Page.h"
37 #include "PutPropertySlot.h"
38 #include "ResourceRequest.h"
39 #include "RenderView.h"
40 #include "SelectionController.h"
41 #include "Scrollbar.h"
42 #include "PrintContext.h"
43 #include "SubstituteData.h"
44
45 #include "markup.h"
46 #include "RenderTreeAsText.h"
47 #include "Element.h"
48 #include "Document.h"
49 #include "DragData.h"
50 #include "RenderView.h"
51 #include "GraphicsContext.h"
52 #include "PlatformMouseEvent.h"
53 #include "PlatformWheelEvent.h"
54 #include "GraphicsContext.h"
55 #include "HitTestResult.h"
56
57 #include "runtime.h"
58 #include "runtime_object.h"
59 #include "runtime_root.h"
60 #include "JSDOMWindow.h"
61 #include "qt_instance.h"
62 #include "ScriptController.h"
63 #include "ScriptValue.h"
64 #include "JSDOMBinding.h"
65 #include "CallFrame.h"
66 #include "JSLock.h"
67 #include "JSObject.h"
68 #include "qt_runtime.h"
69
70 #include "wtf/HashMap.h"
71
72 #include <qdebug.h>
73 #include <qevent.h>
74 #include <qfileinfo.h>
75 #include <qpainter.h>
76 #include <QMultiMap>
77 #if QT_VERSION >= 0x040400
78 #include <qnetworkrequest.h>
79 #else
80 #include "qwebnetworkinterface.h"
81 #endif
82 #include <qregion.h>
83 #include <qprinter.h>
84 #include "HTMLMetaElement.h"
85 #include "NodeList.h"
86
87 using namespace WebCore;
88
89 // from text/qfont.cpp
90 QT_BEGIN_NAMESPACE
91 extern Q_GUI_EXPORT int qt_defaultDpi();
92 QT_END_NAMESPACE
93
94 void QWebFramePrivate::init(QWebFrame *qframe, WebCore::Page *webcorePage, QWebFrameData *frameData)
95 {
96     q = qframe;
97
98     allowsScrolling = frameData->allowsScrolling;
99     marginWidth = frameData->marginWidth;
100     marginHeight = frameData->marginHeight;
101
102     frameLoaderClient = new FrameLoaderClientQt();
103     RefPtr<Frame> newFrame = Frame::create(webcorePage, frameData->ownerElement, frameLoaderClient);
104     frame = newFrame.get();
105     if (frameData->ownerElement)
106         frame->ref(); // balanced by adoptRef in FrameLoaderClientQt::createFrame
107     frameLoaderClient->setFrame(qframe, frame);
108     frame->init();
109 }
110
111 WebCore::Scrollbar* QWebFramePrivate::horizontalScrollBar() const
112 {
113     if (!frame->view())
114         return 0;
115     return frame->view()->horizontalScrollbar();
116 }
117
118 WebCore::Scrollbar* QWebFramePrivate::verticalScrollBar() const
119 {
120     if (!frame->view())
121         return 0;
122     return frame->view()->verticalScrollbar();
123 }
124
125 /*!
126     \class QWebFrame
127     \since 4.4
128     \brief The QWebFrame class represents a frame in a web page.
129
130     QWebFrame represents a frame inside a web page. Each QWebPage
131     object contains at least one frame, the main frame, obtained using
132     QWebPage::mainFrame(). Additional frames will be created for HTML
133     \c{<frame>} or \c{<iframe>} elements.
134
135     A frame can be loaded using load() or setUrl(). Alternatively, if you have
136     the HTML content readily available, you can use setHtml() instead.
137
138     The page() function returns a pointer to the web page object. See
139     \l{Elements of QWebView} for an explanation of how web
140     frames are related to a web page and web view.
141
142     The title of an HTML frame can be accessed with the title() property.
143     Additionally, a frame may also specify an icon, which can be accessed
144     using the icon() property. If the title or the icon changes, the
145     corresponding titleChanged() and iconChanged() signals will be emitted.
146     The zoomFactor() property can be used to change the overall size
147     of the content displayed in the frame.
148
149     QWebFrame objects are created and controlled by the web page. You
150     can connect to the web page's \l{QWebPage::}{frameCreated()} signal
151     to be notified when a new frame is created.
152
153     The hitTestContent() function can be used to programmatically examine the
154     contents of a frame.
155
156     A QWebFrame can be printed onto a QPrinter using the print() function.
157     This function is marked as a slot and can be conveniently connected to
158     \l{QPrintPreviewDialog}'s \l{QPrintPreviewDialog::}{paintRequested()}
159     signal.
160
161     \sa QWebPage
162 */
163
164 QWebFrame::QWebFrame(QWebPage *parent, QWebFrameData *frameData)
165     : QObject(parent)
166     , d(new QWebFramePrivate)
167 {
168     d->page = parent;
169     d->init(this, parent->d->page, frameData);
170
171     if (!frameData->url.isEmpty()) {
172         WebCore::ResourceRequest request(frameData->url, frameData->referrer);
173         d->frame->loader()->load(request, frameData->name);
174     }
175 }
176
177 QWebFrame::QWebFrame(QWebFrame *parent, QWebFrameData *frameData)
178     : QObject(parent)
179     , d(new QWebFramePrivate)
180 {
181     d->page = parent->d->page;
182     d->init(this, parent->d->page->d->page, frameData);
183 }
184
185 QWebFrame::~QWebFrame()
186 {
187     if (d->frame && d->frame->loader() && d->frame->loader()->client())
188         static_cast<FrameLoaderClientQt*>(d->frame->loader()->client())->m_webFrame = 0;
189
190     delete d;
191 }
192
193 /*!
194     Make \a object available under \a name from within the frame's JavaScript
195     context. The \a object will be inserted as a child of the frame's window
196     object.
197
198     Qt properties will be exposed as JavaScript properties and slots as
199     JavaScript methods.
200
201     If you want to ensure that your QObjects remain accessible after loading a
202     new URL, you should add them in a slot connected to the
203     javaScriptWindowObjectCleared() signal.
204 */
205 void QWebFrame::addToJavaScriptWindowObject(const QString &name, QObject *object)
206 {
207       JSC::JSLock lock(false);
208       JSDOMWindow *window = toJSDOMWindow(d->frame);
209       JSC::Bindings::RootObject *root = d->frame->script()->bindingRootObject();
210       if (!window) {
211           qDebug() << "Warning: couldn't get window object";
212           return;
213       }
214
215       JSC::ExecState* exec = window->globalExec();
216
217       JSC::JSObject *runtimeObject =
218         JSC::Bindings::Instance::createRuntimeObject(exec, JSC::Bindings::QtInstance::getQtInstance(object, root));
219
220       JSC::PutPropertySlot slot;
221       window->put(exec, JSC::Identifier(exec, (const UChar *) name.constData(), name.length()), runtimeObject, slot);
222 }
223
224 /*!
225     Returns the frame's content, converted to HTML.
226
227     \sa setHtml(), toPlainText()
228 */
229 QString QWebFrame::toHtml() const
230 {
231     if (!d->frame->document())
232         return QString();
233     return createMarkup(d->frame->document());
234 }
235
236 /*!
237     Returns the content of this frame converted to plain text.
238
239     \sa toHtml()
240 */
241 QString QWebFrame::toPlainText() const
242 {
243     if (d->frame->view() && d->frame->view()->layoutPending())
244         d->frame->view()->layout();
245
246     Element *documentElement = d->frame->document()->documentElement();
247     return documentElement->innerText();
248 }
249
250 /*!
251     Returns a dump of the rendering tree. This is mainly useful for debugging
252     html.
253 */
254 QString QWebFrame::renderTreeDump() const
255 {
256     if (d->frame->view() && d->frame->view()->layoutPending())
257         d->frame->view()->layout();
258
259     return externalRepresentation(d->frame->contentRenderer());
260 }
261
262 /*!
263     \property QWebFrame::title
264     \brief the title of the frame as defined by the HTML &lt;title&gt; element
265
266     \sa titleChanged()
267 */
268
269 QString QWebFrame::title() const
270 {
271     if (d->frame->document())
272         return d->frame->loader()->documentLoader()->title();
273     else return QString();
274 }
275
276 /*!
277     \since 4.5
278     \brief Returns the meta data in this frame as a QMultiMap
279
280     The meta data consists of the name and content attributes of the
281     of the \c{<meta>} tags in the HTML document.
282
283     For example:
284
285     \code
286     <html>
287         <head>
288             <meta name="description" content="This document is a tutorial about Qt development">
289             <meta name="keywords" content="Qt, WebKit, Programming">
290         </head>
291         ...
292     </html>
293     \endcode
294
295     Given the above HTML code the metaData() function will return a map with two entries:
296     \table
297     \header \o Key
298             \o Value
299     \row    \o "description"
300             \o "This document is a tutorial about Qt development"
301     \row    \o "keywords"
302             \o "Qt, WebKit, Programming"
303     \endtable
304
305     This function returns a multi map to support multiple meta tags with the same name attribute.
306 */
307 QMultiMap<QString, QString> QWebFrame::metaData() const
308 {
309     if(!d->frame->document())
310        return QMap<QString,QString>();
311
312     QMultiMap<QString,QString> map;
313     Document* doc = d->frame->document();
314     RefPtr<NodeList> list = doc->getElementsByTagName("meta");
315     unsigned len = list->length();
316     for (unsigned i = 0; i < len; i++) {
317         HTMLMetaElement* meta = static_cast<HTMLMetaElement*>(list->item(i));
318         map.insert(meta->name(), meta->content());
319     }
320     return map;
321 }
322
323 static inline QUrl ensureAbsoluteUrl(const QUrl &url)
324 {
325     if (!url.isRelative())
326         return url;
327
328     return QUrl::fromLocalFile(QFileInfo(url.toLocalFile()).absoluteFilePath());
329 }
330
331 /*!
332     \property QWebFrame::url
333     \brief the url of the frame currently viewed
334
335     \sa urlChanged()
336 */
337
338 void QWebFrame::setUrl(const QUrl &url)
339 {
340     d->frame->loader()->begin(ensureAbsoluteUrl(url));
341     d->frame->loader()->end();
342     load(ensureAbsoluteUrl(url));
343 }
344
345 QUrl QWebFrame::url() const
346 {
347     return d->frame->loader()->url();
348 }
349
350 /*!
351     \property QWebFrame::icon
352     \brief the icon associated with this frame
353
354     \sa iconChanged(), QWebSettings::iconForUrl()
355 */
356
357 QIcon QWebFrame::icon() const
358 {
359     return QWebSettings::iconForUrl(d->frame->loader()->url());
360 }
361
362 /*!
363   The name of this frame as defined by the parent frame.
364 */
365 QString QWebFrame::frameName() const
366 {
367     return d->frame->tree()->name();
368 }
369
370 /*!
371   The web page that contains this frame.
372 */
373 QWebPage *QWebFrame::page() const
374 {
375     return d->page;
376 }
377
378 /*!
379   Loads \a url into this frame.
380
381   \note The view remains the same until enough data has arrived to display the new \a url.
382
383   \sa setUrl(), setHtml(), setContent()
384 */
385 void QWebFrame::load(const QUrl &url)
386 {
387 #if QT_VERSION < 0x040400
388     load(QWebNetworkRequest(ensureAbsoluteUrl(url)));
389 #else
390     load(QNetworkRequest(ensureAbsoluteUrl(url)));
391 #endif
392 }
393
394 #if QT_VERSION < 0x040400
395 /*!
396   Loads a network request, \a req, into this frame.
397
398   \note The view remains the same until enough data has arrived to display the new url.
399 */
400 void QWebFrame::load(const QWebNetworkRequest &req)
401 {
402     if (d->parentFrame())
403         d->page->d->insideOpenCall = true;
404
405     QUrl url = ensureAbsoluteUrl(req.url());
406     QHttpRequestHeader httpHeader = req.httpHeader();
407     QByteArray postData = req.postData();
408
409     WebCore::ResourceRequest request(url);
410
411     QString method = httpHeader.method();
412     if (!method.isEmpty())
413         request.setHTTPMethod(method);
414
415     QList<QPair<QString, QString> > values = httpHeader.values();
416     for (int i = 0; i < values.size(); ++i) {
417         const QPair<QString, QString> &val = values.at(i);
418         request.addHTTPHeaderField(val.first, val.second);
419     }
420
421     if (!postData.isEmpty())
422         request.setHTTPBody(WebCore::FormData::create(postData.constData(), postData.size()));
423
424     d->frame->loader()->load(request);
425
426     if (d->parentFrame())
427         d->page->d->insideOpenCall = false;
428 }
429
430 #else
431
432 /*!
433   Loads a network request, \a req, into this frame, using the method specified in \a
434   operation.
435
436   \a body is optional and is only used for POST operations.
437
438   \note The view remains the same until enough data has arrived to display the new \a url.
439
440   \sa setUrl()
441 */
442 void QWebFrame::load(const QNetworkRequest &req,
443                      QNetworkAccessManager::Operation operation,
444                      const QByteArray &body)
445 {
446     if (d->parentFrame())
447         d->page->d->insideOpenCall = true;
448
449     QUrl url = ensureAbsoluteUrl(req.url());
450
451     WebCore::ResourceRequest request(url);
452
453     switch (operation) {
454         case QNetworkAccessManager::HeadOperation:
455             request.setHTTPMethod("HEAD");
456             break;
457         case QNetworkAccessManager::GetOperation:
458             request.setHTTPMethod("GET");
459             break;
460         case QNetworkAccessManager::PutOperation:
461             request.setHTTPMethod("PUT");
462             break;
463         case QNetworkAccessManager::PostOperation:
464             request.setHTTPMethod("POST");
465             break;
466         case QNetworkAccessManager::UnknownOperation:
467             // eh?
468             break;
469     }
470
471     QList<QByteArray> httpHeaders = req.rawHeaderList();
472     for (int i = 0; i < httpHeaders.size(); ++i) {
473         const QByteArray &headerName = httpHeaders.at(i);
474         request.addHTTPHeaderField(QString::fromLatin1(headerName), QString::fromLatin1(req.rawHeader(headerName)));
475     }
476
477     if (!body.isEmpty())
478         request.setHTTPBody(WebCore::FormData::create(body.constData(), body.size()));
479
480     d->frame->loader()->load(request);
481
482     if (d->parentFrame())
483         d->page->d->insideOpenCall = false;
484 }
485 #endif
486
487 /*!
488   Sets the content of this frame to \a html. \a baseUrl is optional and used to resolve relative
489   URLs in the document, such as referenced images or stylesheets.
490
491   When using this method WebKit assumes that external resources such as JavaScript programs or style
492   sheets are encoded in UTF-8 unless otherwise specified. For example, the encoding of an external
493   script can be specified through the charset attribute of the HTML script tag. It is also possible
494   for the encoding to be specified by web server.
495
496   \sa toHtml()
497 */
498 void QWebFrame::setHtml(const QString &html, const QUrl &baseUrl)
499 {
500     KURL kurl(baseUrl);
501     WebCore::ResourceRequest request(kurl);
502     const QByteArray utf8 = html.toUtf8();
503     WTF::RefPtr<WebCore::SharedBuffer> data = WebCore::SharedBuffer::create(utf8.constData(), utf8.length());
504     WebCore::SubstituteData substituteData(data, WebCore::String("text/html"), WebCore::String("utf-8"), kurl);
505     d->frame->loader()->load(request, substituteData);
506 }
507
508 /*!
509   Sets the content of this frame to the specified content \a data. If the \a mimeType argument
510   is empty it is currently assumed that the content is HTML but in future versions we may introduce
511   auto-detection.
512
513   External objects referenced in the content are located relative to \a baseUrl.
514
515   \sa toHtml()
516 */
517 void QWebFrame::setContent(const QByteArray &data, const QString &mimeType, const QUrl &baseUrl)
518 {
519     KURL kurl(baseUrl);
520     WebCore::ResourceRequest request(kurl);
521     WTF::RefPtr<WebCore::SharedBuffer> buffer = WebCore::SharedBuffer::create(data.constData(), data.length());
522     QString actualMimeType = mimeType;
523     if (actualMimeType.isEmpty())
524         actualMimeType = QLatin1String("text/html");
525     WebCore::SubstituteData substituteData(buffer, WebCore::String(actualMimeType), WebCore::String(), kurl);
526     d->frame->loader()->load(request, substituteData);
527 }
528
529
530 /*!
531   Returns the parent frame of this frame, or 0 if the frame is the web pages
532   main frame.
533
534   This is equivalent to qobject_cast<QWebFrame*>(frame->parent()).
535
536   \sa childFrames()
537 */
538 QWebFrame *QWebFrame::parentFrame() const
539 {
540     return d->parentFrame();
541 }
542
543 /*!
544   Returns a list of all frames that are direct children of this frame.
545
546   \sa parentFrame()
547 */
548 QList<QWebFrame*> QWebFrame::childFrames() const
549 {
550     QList<QWebFrame*> rc;
551     if (d->frame) {
552         FrameTree *tree = d->frame->tree();
553         for (Frame *child = tree->firstChild(); child; child = child->tree()->nextSibling()) {
554             FrameLoader *loader = child->loader();
555             FrameLoaderClientQt *client = static_cast<FrameLoaderClientQt*>(loader->client());
556             if (client)
557                 rc.append(client->webFrame());
558         }
559
560     }
561     return rc;
562 }
563
564 /*!
565     Returns the scrollbar policy for the scrollbar defined by \a orientation.
566 */
567 Qt::ScrollBarPolicy QWebFrame::scrollBarPolicy(Qt::Orientation orientation) const
568 {
569     if (orientation == Qt::Horizontal)
570         return d->horizontalScrollBarPolicy;
571     return d->verticalScrollBarPolicy;
572 }
573
574 /*!
575     Sets the scrollbar policy for the scrollbar defined by \a orientation to \a policy.
576 */
577 void QWebFrame::setScrollBarPolicy(Qt::Orientation orientation, Qt::ScrollBarPolicy policy)
578 {
579     Q_ASSERT((int)ScrollbarAuto == (int)Qt::ScrollBarAsNeeded);
580     Q_ASSERT((int)ScrollbarAlwaysOff == (int)Qt::ScrollBarAlwaysOff);
581     Q_ASSERT((int)ScrollbarAlwaysOn == (int)Qt::ScrollBarAlwaysOn);
582
583     if (orientation == Qt::Horizontal) {
584         d->horizontalScrollBarPolicy = policy;
585         if (d->frame->view())
586             d->frame->view()->setHorizontalScrollbarMode((ScrollbarMode)policy);
587     } else {
588         d->verticalScrollBarPolicy = policy;
589         if (d->frame->view())
590             d->frame->view()->setVerticalScrollbarMode((ScrollbarMode)policy);
591     }
592 }
593
594 /*!
595   Sets the current \a value for the scrollbar with orientation \a orientation.
596
597   The scrollbar forces the \a value to be within the legal range: minimum <= value <= maximum.
598
599   Changing the value also updates the thumb position.
600
601   \sa scrollBarMinimum(), scrollBarMaximum()
602 */
603 void QWebFrame::setScrollBarValue(Qt::Orientation orientation, int value)
604 {
605     Scrollbar *sb;
606     sb = (orientation == Qt::Horizontal) ? d->horizontalScrollBar() : d->verticalScrollBar();
607     if (sb) {
608         if (value < 0)
609             value = 0;
610         else if (value > scrollBarMaximum(orientation))
611             value = scrollBarMaximum(orientation);
612         sb->setValue(value);
613     }
614 }
615
616 /*!
617   Returns the current value for the scrollbar with orientation \a orientation, or 0
618   if no scrollbar is found for \a orientation.
619
620   \sa scrollBarMinimum(), scrollBarMaximum()
621 */
622 int QWebFrame::scrollBarValue(Qt::Orientation orientation) const
623 {
624     Scrollbar *sb;
625     sb = (orientation == Qt::Horizontal) ? d->horizontalScrollBar() : d->verticalScrollBar();
626     if (sb) {
627         return sb->value();
628     }
629     return 0;
630 }
631
632 /*!
633   Returns the maximum value for the scrollbar with orientation \a orientation, or 0
634   if no scrollbar is found for \a orientation.
635
636   \sa scrollBarMinimum()
637 */
638 int QWebFrame::scrollBarMaximum(Qt::Orientation orientation) const
639 {
640     Scrollbar *sb;
641     sb = (orientation == Qt::Horizontal) ? d->horizontalScrollBar() : d->verticalScrollBar();
642     if (sb)
643         return sb->maximum();
644     return 0;
645 }
646
647 /*!
648   Returns the minimum value for the scrollbar with orientation \a orientation.
649
650   The minimum value is always 0.
651
652   \sa scrollBarMaximum()
653 */
654 int QWebFrame::scrollBarMinimum(Qt::Orientation orientation) const
655 {
656     return 0;
657 }
658
659 /*!
660   \since 4.5
661   Scrolls the frame \a dx pixels to the right and \a dy pixels downward. Both
662   \a dx and \a dy may be negative.
663   
664   \sa QWebFrame::scrollOffset
665 */
666
667 void QWebFrame::scroll(int dx, int dy) const
668 {
669     if (!d->frame->view())
670         return;
671     
672     d->frame->view()->scrollBy(IntSize(dx, dy));
673 }
674
675 /*!
676   \property QWebFrame::scrollOffset
677   \brief The offset from the start this frame is currently scrolled to.
678 */
679
680 QPoint QWebFrame::scrollOffset() const
681 {
682     if (!d->frame->view())
683         return QPoint(0,0);
684
685     IntSize ofs = d->frame->view()->scrollOffset();
686     return QPoint(ofs.width(), ofs.height());
687 }
688
689 void QWebFrame::setScrollOffset(const QPoint &offset) const
690 {
691     QPoint current = scrollOffset();
692     int dx = offset.x() - current.x();
693     int dy = offset.y() - current.y();
694     scroll(dx, dy);
695 }
696
697 /*!
698   Render the frame into \a painter clipping to \a clip.
699
700   \sa print()
701 */
702 void QWebFrame::render(QPainter *painter, const QRegion &clip)
703 {
704     if (!d->frame->view() || !d->frame->contentRenderer())
705         return;
706
707     d->frame->view()->layoutIfNeededRecursive();
708
709     GraphicsContext ctx(painter);
710     QVector<QRect> vector = clip.rects();
711     WebCore::FrameView* view = d->frame->view();
712     for (int i = 0; i < vector.size(); ++i) {
713         if (i > 0) {
714             painter->save();
715             painter->setClipRect(vector.at(i), Qt::IntersectClip);
716         }
717
718         view->paint(&ctx, vector.at(i));
719
720         if (i > 0)
721             painter->restore();
722     }
723 }
724
725 /*!
726   Render the frame into \a painter.
727 */
728 void QWebFrame::render(QPainter *painter)
729 {
730     if (!d->frame->view() || !d->frame->contentRenderer())
731         return;
732
733     d->frame->view()->layoutIfNeededRecursive();
734
735     GraphicsContext ctx(painter);
736     WebCore::FrameView* view = d->frame->view();
737     view->paint(&ctx, view->frameRect());
738 }
739
740 /*!
741     \property QWebFrame::textSizeMultiplier
742     \brief the scaling factor for all text in the frame
743     \obsolete
744
745     Use setZoomFactor instead, in combination with the ZoomTextOnly attribute in
746     QWebSettings.
747
748     \note Setting this property also enables the ZoomTextOnly attribute in
749     QWebSettings.
750 */
751
752 /*!
753     Sets the value of the multiplier used to scale the text in a Web frame to
754     the \a factor specified.
755 */
756 void QWebFrame::setTextSizeMultiplier(qreal factor)
757 {
758     d->frame->setZoomFactor(factor, /*isTextOnly*/true);
759 }
760
761 /*!
762     Returns the value of the multiplier used to scale the text in a Web frame.
763 */
764 qreal QWebFrame::textSizeMultiplier() const
765 {
766     return d->frame->zoomFactor();
767 }
768
769 /*!
770     \property QWebFrame::zoomFactor
771     \since 4.5
772     \brief the zoom factor for the frame
773 */
774
775 void QWebFrame::setZoomFactor(qreal factor)
776 {
777     d->frame->setZoomFactor(factor, d->frame->isZoomFactorTextOnly());
778 }
779
780 qreal QWebFrame::zoomFactor() const
781 {
782     return d->frame->zoomFactor();
783 }
784
785 /*!
786     Returns the position of the frame relative to it's parent frame.
787 */
788 QPoint QWebFrame::pos() const
789 {
790     if (!d->frame->view())
791         return QPoint();
792
793     return d->frame->view()->frameRect().topLeft();
794 }
795
796 /*!
797     Return the geometry of the frame relative to it's parent frame.
798 */
799 QRect QWebFrame::geometry() const
800 {
801     if (!d->frame->view())
802         return QRect();
803     return d->frame->view()->frameRect();
804 }
805
806 /*!
807     \property QWebFrame::contentsSize
808     \brief the size of the contents in this frame
809 */
810 QSize QWebFrame::contentsSize() const
811 {
812     FrameView *view = d->frame->view();
813     if (!view)
814         return QSize();
815     return QSize(view->contentsWidth(), view->contentsHeight());
816 }
817
818 /*!
819     Performs a hit test on the frame contents at the given position \a pos and returns the hit test result.
820 */
821 QWebHitTestResult QWebFrame::hitTestContent(const QPoint &pos) const
822 {
823     if (!d->frame->view() || !d->frame->contentRenderer())
824         return QWebHitTestResult();
825
826     HitTestResult result = d->frame->eventHandler()->hitTestResultAtPoint(d->frame->view()->windowToContents(pos), /*allowShadowContent*/ false);
827     return QWebHitTestResult(new QWebHitTestResultPrivate(result));
828 }
829
830 /*! \reimp
831 */
832 bool QWebFrame::event(QEvent *e)
833 {
834     return QObject::event(e);
835 }
836
837 #ifndef QT_NO_PRINTER
838 /*!
839     Prints the frame to the given \a printer.
840
841     \sa render()
842 */
843 void QWebFrame::print(QPrinter *printer) const
844 {
845     const qreal zoomFactorX = printer->logicalDpiX() / qt_defaultDpi();
846     const qreal zoomFactorY = printer->logicalDpiY() / qt_defaultDpi();
847
848     PrintContext printContext(d->frame);
849     float pageHeight = 0;
850
851     QRect qprinterRect = printer->pageRect();
852
853     IntRect pageRect(0, 0,
854                      int(qprinterRect.width() / zoomFactorX),
855                      int(qprinterRect.height() / zoomFactorY));
856
857     printContext.begin(pageRect.width());
858
859     printContext.computePageRects(pageRect, /*headerHeight*/0, /*footerHeight*/0, /*userScaleFactor*/1.0, pageHeight);
860
861     int docCopies;
862     int pageCopies;
863     if (printer->collateCopies() == true){
864         docCopies = 1;
865         pageCopies = printer->numCopies();
866     } else {
867         docCopies = printer->numCopies();
868         pageCopies = 1;
869     }
870
871     int fromPage = printer->fromPage();
872     int toPage = printer->toPage();
873     bool ascending = true;
874
875     if (fromPage == 0 && toPage == 0) {
876         fromPage = 1;
877         toPage = printContext.pageCount();
878     }
879     // paranoia check
880     fromPage = qMax(1, fromPage);
881     toPage = qMin(printContext.pageCount(), toPage);
882
883     if (printer->pageOrder() == QPrinter::LastPageFirst) {
884         int tmp = fromPage;
885         fromPage = toPage;
886         toPage = tmp;
887         ascending = false;
888     }
889
890     QPainter painter(printer);
891     painter.scale(zoomFactorX, zoomFactorY);
892     GraphicsContext ctx(&painter);
893
894     for (int i = 0; i < docCopies; ++i) {
895         int page = fromPage;
896         while (true) {
897             for (int j = 0; j < pageCopies; ++j) {
898                 if (printer->printerState() == QPrinter::Aborted
899                     || printer->printerState() == QPrinter::Error) {
900                     printContext.end();
901                     return;
902                 }
903                 printContext.spoolPage(ctx, page - 1, pageRect.width());
904                 if (j < pageCopies - 1)
905                     printer->newPage();
906             }
907
908             if (page == toPage)
909                 break;
910
911             if (ascending)
912                 ++page;
913             else
914                 --page;
915
916             printer->newPage();
917         }
918
919         if ( i < docCopies - 1)
920             printer->newPage();
921     }
922
923     printContext.end();
924 }
925 #endif // QT_NO_PRINTER
926
927 /*!
928     Evaluate JavaScript defined by \a scriptSource using this frame as context.
929
930     \sa addToJavaScriptWindowObject(), javaScriptWindowObjectCleared()
931 */
932 QVariant QWebFrame::evaluateJavaScript(const QString& scriptSource)
933 {
934     ScriptController *proxy = d->frame->script();
935     QVariant rc;
936     if (proxy) {
937         JSC::JSValue* v = proxy->evaluate(String(), 1, scriptSource);
938         if (v) {
939             int distance = 0;
940             rc = JSC::Bindings::convertValueToQVariant(proxy->globalObject()->globalExec(), v, QMetaType::Void, &distance);
941         }
942     }
943     return rc;
944 }
945
946 QWebSecurityOrigin QWebFrame::securityOrigin() const
947 {
948     QWebFrame* that = const_cast<QWebFrame*>(this);
949     QWebSecurityOriginPrivate* priv = new QWebSecurityOriginPrivate(QWebFramePrivate::core(that)->document()->securityOrigin());
950     return QWebSecurityOrigin(priv);
951 }
952
953 WebCore::Frame* QWebFramePrivate::core(QWebFrame* webFrame)
954 {
955     return webFrame->d->frame;
956 }
957
958 QWebFrame* QWebFramePrivate::kit(WebCore::Frame* coreFrame)
959 {
960     return static_cast<FrameLoaderClientQt*>(coreFrame->loader()->client())->webFrame();
961 }
962
963
964 /*!
965     \fn void QWebFrame::javaScriptWindowObjectCleared()
966
967     This signal is emitted whenever the global window object of the JavaScript
968     environment is cleared, e.g., before starting a new load.
969
970     If you intend to add QObjects to a QWebFrame using
971     addToJavaScriptWindowObject(), you should add them in a slot connected
972     to this signal. This ensures that your objects remain accessible when
973     loading new URLs.
974 */
975
976 /*!
977     \fn void QWebFrame::provisionalLoad()
978     \internal
979 */
980
981 /*!
982     \fn void QWebFrame::titleChanged(const QString &title)
983
984     This signal is emitted whenever the title of the frame changes.
985     The \a title string specifies the new title.
986
987     \sa title()
988 */
989
990 /*!
991     \fn void QWebFrame::urlChanged(const QUrl &url)
992
993     This signal is emitted with the URL of the frame when the frame's title is
994     received. The new URL is specified by \a url.
995
996     \sa url()
997 */
998
999 /*!
1000     \fn void QWebFrame::initialLayoutCompleted()
1001
1002     This signal is emitted when the frame is laid out the first time.
1003     This is the first time you will see contents displayed on the frame.
1004
1005     \note A frame can be laid out multiple times.
1006 */
1007
1008 /*!
1009   \fn void QWebFrame::iconChanged()
1010
1011   This signal is emitted when the icon ("favicon") associated with the frame
1012   has been loaded.
1013
1014   \sa icon()
1015 */
1016
1017 /*!
1018   \since 4.5
1019   \fn void QWebFrame::aboutToUpdateHistory(QWebHistoryItem* item);
1020
1021   This signal is emitted shortly before the history of navigated pages
1022   is changed, for example when navigating back in the history.
1023
1024   A potential use-case for this signal is to store custom data in
1025   the QWebHistoryItem associated to the frame, using QWebHistoryItem::setUserData().
1026 */
1027
1028 /*!
1029     \class QWebHitTestResult
1030     \since 4.4
1031     \brief The QWebHitTestResult class provides information about the web
1032     page content after a hit test.
1033
1034     QWebHitTestResult is returned by QWebFrame::hitTestContent() to provide
1035     information about the content of the web page at the specified position.
1036 */
1037
1038 /*!
1039     \internal
1040 */
1041 QWebHitTestResult::QWebHitTestResult(QWebHitTestResultPrivate *priv)
1042     : d(priv)
1043 {
1044 }
1045
1046 QWebHitTestResultPrivate::QWebHitTestResultPrivate(const WebCore::HitTestResult &hitTest)
1047     : isContentEditable(false)
1048     , isContentSelected(false)
1049 {
1050     if (!hitTest.innerNode())
1051         return;
1052     pos = hitTest.point();
1053     boundingRect = hitTest.boundingBox();
1054     title = hitTest.title();
1055     linkText = hitTest.textContent();
1056     linkUrl = hitTest.absoluteLinkURL();
1057     linkTitle = hitTest.titleDisplayString();
1058     alternateText = hitTest.altDisplayString();
1059     imageUrl = hitTest.absoluteImageURL();
1060     innerNonSharedNode = hitTest.innerNonSharedNode();
1061     WebCore::Image *img = hitTest.image();
1062     if (img) {
1063         QPixmap *pix = img->nativeImageForCurrentFrame();
1064         if (pix)
1065             pixmap = *pix;
1066     }
1067     WebCore::Frame *wframe = hitTest.targetFrame();
1068     if (wframe)
1069         linkTargetFrame = QWebFramePrivate::kit(wframe);
1070
1071     isContentEditable = hitTest.isContentEditable();
1072     isContentSelected = hitTest.isSelected();
1073
1074     if (innerNonSharedNode && innerNonSharedNode->document()
1075         && innerNonSharedNode->document()->frame())
1076         frame = QWebFramePrivate::kit(innerNonSharedNode->document()->frame());
1077 }
1078
1079 /*!
1080     Constructs a null hit test result.
1081 */
1082 QWebHitTestResult::QWebHitTestResult()
1083     : d(0)
1084 {
1085 }
1086
1087 /*!
1088     Constructs a hit test result from \a other.
1089 */
1090 QWebHitTestResult::QWebHitTestResult(const QWebHitTestResult &other)
1091     : d(0)
1092 {
1093     if (other.d)
1094         d = new QWebHitTestResultPrivate(*other.d);
1095 }
1096
1097 /*!
1098     Assigns the \a other hit test result to this.
1099 */
1100 QWebHitTestResult &QWebHitTestResult::operator=(const QWebHitTestResult &other)
1101 {
1102     if (this != &other) {
1103         if (other.d) {
1104             if (!d)
1105                 d = new QWebHitTestResultPrivate;
1106             *d = *other.d;
1107         } else {
1108             delete d;
1109             d = 0;
1110         }
1111     }
1112     return *this;
1113 }
1114
1115 /*!
1116     Destructor.
1117 */
1118 QWebHitTestResult::~QWebHitTestResult()
1119 {
1120     delete d;
1121 }
1122
1123 /*!
1124     Returns true if the hit test result is null; otherwise returns false.
1125 */
1126 bool QWebHitTestResult::isNull() const
1127 {
1128     return !d;
1129 }
1130
1131 /*!
1132     Returns the position where the hit test occured.
1133 */
1134 QPoint QWebHitTestResult::pos() const
1135 {
1136     if (!d)
1137         return QPoint();
1138     return d->pos;
1139 }
1140
1141 /*!
1142     \since 4.5
1143     Returns the bounding box of the element.
1144 */
1145 QRect QWebHitTestResult::boundingRect() const
1146 {
1147     if (!d)
1148         return QRect();
1149     return d->boundingRect;
1150 }
1151
1152 /*!
1153     Returns the title of the nearest enclosing HTML element.
1154 */
1155 QString QWebHitTestResult::title() const
1156 {
1157     if (!d)
1158         return QString();
1159     return d->title;
1160 }
1161
1162 /*!
1163     Returns the text of the link.
1164 */
1165 QString QWebHitTestResult::linkText() const
1166 {
1167     if (!d)
1168         return QString();
1169     return d->linkText;
1170 }
1171
1172 /*!
1173     Returns the url to which the link points to.
1174 */
1175 QUrl QWebHitTestResult::linkUrl() const
1176 {
1177     if (!d)
1178         return QUrl();
1179     return d->linkUrl;
1180 }
1181
1182 /*!
1183     Returns the title of the link.
1184 */
1185 QUrl QWebHitTestResult::linkTitle() const
1186 {
1187     if (!d)
1188         return QUrl();
1189     return d->linkTitle;
1190 }
1191
1192 /*!
1193     Returns the frame that will load the link if it is activated.
1194 */
1195 QWebFrame *QWebHitTestResult::linkTargetFrame() const
1196 {
1197     if (!d)
1198         return 0;
1199     return d->linkTargetFrame;
1200 }
1201
1202 /*!
1203     Returns the alternate text of the element. This corresponds to the HTML alt attribute.
1204 */
1205 QString QWebHitTestResult::alternateText() const
1206 {
1207     if (!d)
1208         return QString();
1209     return d->alternateText;
1210 }
1211
1212 /*!
1213     Returns the url of the image.
1214 */
1215 QUrl QWebHitTestResult::imageUrl() const
1216 {
1217     if (!d)
1218         return QUrl();
1219     return d->imageUrl;
1220 }
1221
1222 /*!
1223     Returns a QPixmap containing the image. A null pixmap is returned if the
1224     element being tested is not an image.
1225 */
1226 QPixmap QWebHitTestResult::pixmap() const
1227 {
1228     if (!d)
1229         return QPixmap();
1230     return d->pixmap;
1231 }
1232
1233 /*!
1234     Returns true if the content is editable by the user; otherwise returns false.
1235 */
1236 bool QWebHitTestResult::isContentEditable() const
1237 {
1238     if (!d)
1239         return false;
1240     return d->isContentEditable;
1241 }
1242
1243 /*!
1244     Returns true if the content tested is part of the selection; otherwise returns false.
1245 */
1246 bool QWebHitTestResult::isContentSelected() const
1247 {
1248     if (!d)
1249         return false;
1250     return d->isContentSelected;
1251 }
1252
1253 /*!
1254     Returns the frame the hit test was executed in.
1255 */
1256 QWebFrame *QWebHitTestResult::frame() const
1257 {
1258     if (!d)
1259         return 0;
1260     return d->frame;
1261 }
1262