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