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 <title> 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