2 Copyright (C) 2007 Trolltech ASA
3 Copyright (C) 2007 Staikos Computing Services Inc.
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.
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.
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.
20 This class provides all functionality needed for loading images, style sheets and html
21 pages from the web. It has a memory cache for these objects.
24 #include "qwebframe.h"
26 #include "qwebpage_p.h"
27 #include "qwebframe_p.h"
29 #include "DocumentLoader.h"
30 #include "FocusController.h"
31 #include "FrameLoaderClientQt.h"
33 #include "FrameTree.h"
34 #include "FrameView.h"
35 #include "IconDatabase.h"
37 #include "ResourceRequest.h"
38 #include "SelectionController.h"
39 #include "PlatformScrollBar.h"
40 #include "SubstituteData.h"
43 #include "RenderTreeAsText.h"
47 #include "RenderObject.h"
48 #include "GraphicsContext.h"
49 #include "PlatformScrollBar.h"
50 #include "PlatformMouseEvent.h"
51 #include "PlatformWheelEvent.h"
52 #include "GraphicsContext.h"
53 #include "HitTestResult.h"
56 #include "runtime_root.h"
57 #include "JSDOMWindow.h"
58 #include "qt_instance.h"
59 #include "kjs_proxy.h"
60 #include "kjs_binding.h"
61 #include "ExecState.h"
64 #include "wtf/HashMap.h"
69 #if QT_VERSION >= 0x040400
70 #include <qnetworkrequest.h>
72 #include "qwebnetworkinterface.h"
76 using namespace WebCore;
78 void QWebFramePrivate::init(QWebFrame *qframe, WebCore::Page *webcorePage, QWebFrameData *frameData)
82 frameLoaderClient = new FrameLoaderClientQt();
83 frame = new Frame(webcorePage, frameData->ownerElement, frameLoaderClient);
84 frameLoaderClient->setFrame(qframe, frame);
86 FrameView* frameView = new FrameView(frame);
87 if (!frameData->allowsScrolling)
88 frameView->setScrollbarsMode(ScrollbarAlwaysOff);
89 if (frameData->marginWidth != -1)
90 frameView->setMarginWidth(frameData->marginWidth);
91 if (frameData->marginHeight != -1)
92 frameView->setMarginHeight(frameData->marginHeight);
94 frame->setView(frameView);
98 QObject::connect(q, SIGNAL(hoveringOverLink(const QString&, const QString&, const QString&)),
99 page, SIGNAL(hoveringOverLink(const QString&, const QString&, const QString&)));
102 WebCore::PlatformScrollbar *QWebFramePrivate::horizontalScrollBar() const
106 return frame->view()->horizontalScrollBar();
109 WebCore::PlatformScrollbar *QWebFramePrivate::verticalScrollBar() const
113 return frame->view()->verticalScrollBar();
119 \brief The QWebFrame class represents a frame in a web page.
121 QWebFrame represents a frame inside a web page. Each QWebPage
122 object contains at least one frame, the mainFrame(). Additional
123 frames will be created for HTML <frame> or <iframe>
126 QWebFrame objects are created and controlled by the web page. You
127 can connect to the web pages frameCreated() signal to find out
128 about creation of new frames.
133 QWebFrame::QWebFrame(QWebPage *parent, QWebFrameData *frameData)
135 , d(new QWebFramePrivate)
138 d->init(this, parent->d->page, frameData);
140 if (!frameData->url.isEmpty()) {
141 ResourceRequest request(frameData->url, frameData->referrer);
142 d->frame->loader()->load(request, frameData->name);
146 QWebFrame::QWebFrame(QWebFrame *parent, QWebFrameData *frameData)
148 , d(new QWebFramePrivate)
150 d->page = parent->d->page;
151 d->init(this, parent->d->page->d->page, frameData);
154 QWebFrame::~QWebFrame()
156 if (d->frame && d->frame->loader() && d->frame->loader()->client())
157 static_cast<FrameLoaderClientQt*>(d->frame->loader()->client())->m_webFrame = 0;
163 Make \a object available under \a name from within the frames
164 JavaScript context. The \a object will be inserted as a child of the
165 frames window object.
167 Qt properties will be exposed as JavaScript properties and slots as
170 void QWebFrame::addToJSWindowObject(const QString &name, QObject *object)
173 JSDOMWindow *window = toJSDOMWindow(d->frame);
174 KJS::Bindings::RootObject *root = d->frame->bindingRootObject();
176 qDebug() << "Warning: couldn't get window object";
180 KJS::JSObject *runtimeObject =
181 KJS::Bindings::Instance::createRuntimeObject(KJS::Bindings::QtInstance::create(object, root));
183 window->put(window->globalExec(), KJS::Identifier((const UChar *) name.constData(), name.length()), runtimeObject);
187 returns the markup (HTML) contained in the current frame.
189 QString QWebFrame::markup() const
191 if (!d->frame->document())
193 return createMarkup(d->frame->document());
197 returns the content of this frame as plain text.
199 QString QWebFrame::innerText() const
201 if (d->frame->view() && d->frame->view()->layoutPending())
202 d->frame->view()->layout();
204 Element *documentElement = d->frame->document()->documentElement();
205 return documentElement->innerText();
209 returns a dump of the rendering tree. Mainly useful for debugging html.
211 QString QWebFrame::renderTreeDump() const
213 if (d->frame->view() && d->frame->view()->layoutPending())
214 d->frame->view()->layout();
216 return externalRepresentation(d->frame->renderer());
220 The title of the frame as defined by the HTML <title>
223 QString QWebFrame::title() const
225 if (d->frame->document())
226 return d->frame->loader()->documentLoader()->title();
227 else return QString();
231 The url of this frame.
233 QUrl QWebFrame::url() const
235 return d->frame->loader()->url();
239 The icon associated with this frame.
241 QPixmap QWebFrame::icon() const
243 String url = d->frame->loader()->url().string();
246 if (!url.isEmpty()) {
247 image = iconDatabase()->iconForPageURL(url, IntSize(16, 16));
250 if (!image || image->isNull()) {
251 image = iconDatabase()->defaultIcon(IntSize(16, 16));
258 QPixmap *icon = image->getPixmap();
266 The name of this frame as defined by the parent frame.
268 QString QWebFrame::name() const
270 return d->frame->tree()->name();
274 The web page that contains this frame.
276 QWebPage *QWebFrame::page() const
282 Load \a url into this frame.
284 void QWebFrame::load(const QUrl &url)
286 #if QT_VERSION < 0x040400
287 load(QWebNetworkRequest(url));
289 load(QNetworkRequest(url));
293 #if QT_VERSION < 0x040400
295 Load network request \a req into this frame.
297 void QWebFrame::load(const QWebNetworkRequest &req)
299 if (d->parentFrame())
300 d->page->d->insideOpenCall = true;
302 QUrl url = req.url();
303 QHttpRequestHeader httpHeader = req.httpHeader();
304 QByteArray postData = req.postData();
306 WebCore::ResourceRequest request(url);
308 QString method = httpHeader.method();
309 if (!method.isEmpty())
310 request.setHTTPMethod(method);
312 QList<QPair<QString, QString> > values = httpHeader.values();
313 for (int i = 0; i < values.size(); ++i) {
314 const QPair<QString, QString> &val = values.at(i);
315 request.addHTTPHeaderField(val.first, val.second);
318 if (!postData.isEmpty())
319 request.setHTTPBody(WebCore::FormData::create(postData.constData(), postData.size()));
321 d->frame->loader()->load(request);
323 if (d->parentFrame())
324 d->page->d->insideOpenCall = false;
330 Load network request \a req into this frame. Use the method specified in \a
331 operation. \a body is optional and is only used for POST operations.
333 void QWebFrame::load(const QNetworkRequest &req,
334 QNetworkAccessManager::Operation operation,
335 const QByteArray &body)
337 if (d->parentFrame())
338 d->page->d->insideOpenCall = true;
340 QUrl url = req.url();
342 WebCore::ResourceRequest request(url);
345 case QNetworkAccessManager::HeadOperation:
346 request.setHTTPMethod("HEAD");
348 case QNetworkAccessManager::GetOperation:
349 request.setHTTPMethod("GET");
351 case QNetworkAccessManager::PutOperation:
352 request.setHTTPMethod("PUT");
354 case QNetworkAccessManager::PostOperation:
355 request.setHTTPMethod("POST");
357 case QNetworkAccessManager::UnknownOperation:
362 QList<QByteArray> httpHeaders = req.rawHeaderList();
363 for (int i = 0; i < httpHeaders.size(); ++i) {
364 const QByteArray &headerName = httpHeaders.at(i);
365 request.addHTTPHeaderField(QString::fromLatin1(headerName), QString::fromLatin1(req.rawHeader(headerName)));
369 request.setHTTPBody(WebCore::FormData::create(body.constData(), body.size()));
371 d->frame->loader()->load(request);
373 if (d->parentFrame())
374 d->page->d->insideOpenCall = false;
379 Sets the content of this frame to \a html. \a baseUrl is optional and used to resolve relative
380 URLs in the document.
382 void QWebFrame::setHtml(const QString &html, const QUrl &baseUrl)
385 WebCore::ResourceRequest request(kurl);
386 WTF::RefPtr<WebCore::SharedBuffer> data = WebCore::SharedBuffer::create(reinterpret_cast<const uchar *>(html.unicode()), html.length() * 2);
387 WebCore::SubstituteData substituteData(data, WebCore::String("text/html"), WebCore::String("utf-16"), kurl);
388 d->frame->loader()->load(request, substituteData);
394 void QWebFrame::setHtml(const QByteArray &html, const QUrl &baseUrl)
396 setContent(html, QString(), baseUrl);
400 Sets the content of this frame to \a data assuming \a mimeType. If
401 \a mimeType is not specified it defaults to 'text/html'. \a baseUrl
402 us optional and used to resolve relative URLs in the document.
404 void QWebFrame::setContent(const QByteArray &data, const QString &mimeType, const QUrl &baseUrl)
407 WebCore::ResourceRequest request(kurl);
408 WTF::RefPtr<WebCore::SharedBuffer> buffer = WebCore::SharedBuffer::create(data.constData(), data.length());
409 QString actualMimeType = mimeType;
410 if (actualMimeType.isEmpty())
411 actualMimeType = QLatin1String("text/html");
412 WebCore::SubstituteData substituteData(buffer, WebCore::String(actualMimeType), WebCore::String(), kurl);
413 d->frame->loader()->load(request, substituteData);
418 Returns the parent frame of this frame, or 0 if the frame is the web pages
421 This is equivalent to qobject_cast<QWebFrame*>(frame->parent()).
423 QWebFrame *QWebFrame::parentFrame() const
425 return d->parentFrame();
429 Returns a list of all frames that are direct children of this frame.
431 QList<QWebFrame*> QWebFrame::childFrames() const
433 QList<QWebFrame*> rc;
435 FrameTree *tree = d->frame->tree();
436 for (Frame *child = tree->firstChild(); child; child = child->tree()->nextSibling()) {
437 FrameLoader *loader = child->loader();
438 FrameLoaderClientQt *client = static_cast<FrameLoaderClientQt*>(loader->client());
440 rc.append(client->webFrame());
448 \property QWebFrame::verticalScrollBarPolicy
450 This property defines the vertical scrollbar policy.
452 \sa Qt::ScrollBarPolicy
454 Qt::ScrollBarPolicy QWebFrame::verticalScrollBarPolicy() const
456 return d->verticalScrollBarPolicy;
459 void QWebFrame::setVerticalScrollBarPolicy(Qt::ScrollBarPolicy policy)
461 Q_ASSERT((int)ScrollbarAuto == (int)Qt::ScrollBarAsNeeded);
462 Q_ASSERT((int)ScrollbarAlwaysOff == (int)Qt::ScrollBarAlwaysOff);
463 Q_ASSERT((int)ScrollbarAlwaysOn == (int)Qt::ScrollBarAlwaysOn);
465 d->verticalScrollBarPolicy = policy;
466 if (d->frame->view())
467 d->frame->view()->setVScrollbarMode((ScrollbarMode)policy);
471 \property QWebFrame::horizontalScrollBarPolicy
473 This property defines the horizontal scrollbar policy.
475 \sa Qt::ScrollBarPolicy
477 Qt::ScrollBarPolicy QWebFrame::horizontalScrollBarPolicy() const
479 return d->horizontalScrollBarPolicy;
482 void QWebFrame::setHorizontalScrollBarPolicy(Qt::ScrollBarPolicy policy)
484 d->horizontalScrollBarPolicy = policy;
485 if (d->frame->view())
486 d->frame->view()->setHScrollbarMode((ScrollbarMode)policy);
490 Render the frame into \a painter clipping to \a clip.
492 void QWebFrame::render(QPainter *painter, const QRegion &clip)
494 if (!d->frame->view() || !d->frame->renderer())
499 GraphicsContext ctx(painter);
500 QVector<QRect> vector = clip.rects();
501 WebCore::FrameView* view = d->frame->view();
502 for (int i = 0; i < vector.size(); ++i)
503 view->paint(&ctx, vector.at(i));
507 Ensure that the content of the frame and all subframes are correctly layouted.
509 void QWebFrame::layout()
511 if (!d->frame->view())
514 d->frame->view()->layoutIfNeededRecursive();
518 returns the position of the frame relative to it's parent frame.
520 QPoint QWebFrame::pos() const
522 if (!d->frame->view())
525 return d->frame->view()->frameGeometry().topLeft();
529 return the geometry of the frame relative to it's parent frame.
531 QRect QWebFrame::geometry() const
533 if (!d->frame->view())
535 return d->frame->view()->frameGeometry();
539 Evaluate JavaScript defined by \a scriptSource using this frame as context.
541 QString QWebFrame::evaluateJavaScript(const QString& scriptSource)
543 KJSProxy *proxy = d->frame->scriptProxy();
546 KJS::JSValue *v = proxy->evaluate(String(), 0, scriptSource);
548 rc = String(v->toString(proxy->globalObject()->globalExec()));
554 WebCore::Frame* QWebFramePrivate::core(QWebFrame* webFrame)
556 return webFrame->d->frame;
559 QWebFrame* QWebFramePrivate::kit(WebCore::Frame* coreFrame)
561 return static_cast<FrameLoaderClientQt*>(coreFrame->loader()->client())->webFrame();
566 \fn void QWebFrame::cleared()
568 This signal is emitted whenever the content of the frame is cleared
569 (e.g. before starting a new load).
573 \fn void QWebFrame::loadDone(bool ok)
575 This signal is emitted when the frame is completely loaded. \a ok will indicate whether the load
576 was successful or any error occurred.
580 \fn void QWebFrame::provisionalLoad()
586 \fn void QWebFrame::titleChanged(const QString &title)
588 This signal is emitted whenever the title of the frame changes.
589 The \a title string specifies the new title.
595 \fn void QWebFrame::urlChanged(const QUrl &url)
597 This signal is emitted whenever the \a url of the frame changes.
603 \fn void QWebFrame::hoveringOverLink(const QString &link, const QString &title, const QString &textContent)
605 This signal is emitted whenever the mouse cursor is hovering over a
606 link. It can be used to display information about the link in
607 e.g. the status bar. The signal arguments consist of the \a link destination, the \a title and the
608 link text as \a textContent .
613 \fn void QWebFrame::loadStarted()
615 This signal is emitted when a new load of the frame is started.
619 \fn void QWebFrame::loadFinished()
621 This signal is emitted when a load of the frame is finished.
625 \fn void QWebFrame::initialLayoutComplete()
627 This signal is emitted when the first (initial) layout of the frame
628 has happened. This is the earliest time something can be shown on
633 \fn void QWebFrame::iconLoaded()
635 This signal is emitted when the icon ("favicon") associated with the frame has been loaded.