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