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