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.get());
86 FrameView* frameView = new FrameView(frame.get());
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.get());
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 Q_ASSERT(d->frame == 0);
161 Make \a object available under \a name from within the frames
162 JavaScript context. The \a object will be inserted as a child of the
163 frames window object.
165 Qt properties will be exposed as JavaScript properties and slots as
168 void QWebFrame::addToJSWindowObject(const QString &name, QObject *object)
171 JSDOMWindow *window = toJSDOMWindow(d->frame.get());
172 KJS::Bindings::RootObject *root = d->frame->bindingRootObject();
174 qDebug() << "Warning: couldn't get window object";
178 KJS::JSObject *runtimeObject =
179 KJS::Bindings::Instance::createRuntimeObject(KJS::Bindings::QtInstance::create(object, root));
181 window->put(window->globalExec(), KJS::Identifier((const UChar *) name.constData(), name.length()), runtimeObject);
185 returns the markup (HTML) contained in the current frame.
187 QString QWebFrame::markup() const
189 if (!d->frame->document())
191 return createMarkup(d->frame->document());
195 returns the content of this frame as plain text.
197 QString QWebFrame::innerText() const
199 if (d->frame->view() && d->frame->view()->layoutPending())
200 d->frame->view()->layout();
202 Element *documentElement = d->frame->document()->documentElement();
203 return documentElement->innerText();
207 returns a dump of the rendering tree. Mainly useful for debugging html.
209 QString QWebFrame::renderTreeDump() const
211 if (d->frame->view() && d->frame->view()->layoutPending())
212 d->frame->view()->layout();
214 return externalRepresentation(d->frame->renderer());
218 The title of the frame as defined by the HTML <title>
221 QString QWebFrame::title() const
223 if (d->frame->document())
224 return d->frame->loader()->documentLoader()->title();
225 else return QString();
229 The url of this frame.
231 QUrl QWebFrame::url() const
233 return d->frame->loader()->url();
237 The icon associated with this frame.
239 QPixmap QWebFrame::icon() const
241 String url = d->frame->loader()->url().string();
244 if (!url.isEmpty()) {
245 image = iconDatabase()->iconForPageURL(url, IntSize(16, 16));
248 if (!image || image->isNull()) {
249 image = iconDatabase()->defaultIcon(IntSize(16, 16));
256 QPixmap *icon = image->getPixmap();
264 The name of this frame as defined by the parent frame.
266 QString QWebFrame::name() const
268 return d->frame->tree()->name();
272 The web page that contains this frame.
274 QWebPage *QWebFrame::page() const
280 Load \a url into this frame.
282 void QWebFrame::load(const QUrl &url)
284 #if QT_VERSION < 0x040400
285 load(QWebNetworkRequest(url));
287 load(QNetworkRequest(url));
291 #if QT_VERSION < 0x040400
293 Load network request \a req into this frame.
295 void QWebFrame::load(const QWebNetworkRequest &req)
297 if (d->parentFrame())
298 d->page->d->insideOpenCall = true;
300 QUrl url = req.url();
301 QHttpRequestHeader httpHeader = req.httpHeader();
302 QByteArray postData = req.postData();
304 WebCore::ResourceRequest request(url);
306 QString method = httpHeader.method();
307 if (!method.isEmpty())
308 request.setHTTPMethod(method);
310 QList<QPair<QString, QString> > values = httpHeader.values();
311 for (int i = 0; i < values.size(); ++i) {
312 const QPair<QString, QString> &val = values.at(i);
313 request.addHTTPHeaderField(val.first, val.second);
316 if (!postData.isEmpty())
317 request.setHTTPBody(WebCore::FormData::create(postData.constData(), postData.size()));
319 d->frame->loader()->load(request);
321 if (d->parentFrame())
322 d->page->d->insideOpenCall = false;
328 Load network request \a req into this frame. Use the method specified in \a
329 operation. \a body is optional and is only used for POST operations.
331 void QWebFrame::load(const QNetworkRequest &req,
332 QNetworkAccessManager::Operation operation,
333 const QByteArray &body)
335 if (d->parentFrame())
336 d->page->d->insideOpenCall = true;
338 QUrl url = req.url();
340 WebCore::ResourceRequest request(url);
343 case QNetworkAccessManager::HeadOperation:
344 request.setHTTPMethod("HEAD");
346 case QNetworkAccessManager::GetOperation:
347 request.setHTTPMethod("GET");
349 case QNetworkAccessManager::PutOperation:
350 request.setHTTPMethod("PUT");
352 case QNetworkAccessManager::PostOperation:
353 request.setHTTPMethod("POST");
355 case QNetworkAccessManager::UnknownOperation:
360 QList<QByteArray> httpHeaders = req.rawHeaderList();
361 for (int i = 0; i < httpHeaders.size(); ++i) {
362 const QByteArray &headerName = httpHeaders.at(i);
363 request.addHTTPHeaderField(QString::fromLatin1(headerName), QString::fromLatin1(req.rawHeader(headerName)));
367 request.setHTTPBody(WebCore::FormData::create(body.constData(), body.size()));
369 d->frame->loader()->load(request);
371 if (d->parentFrame())
372 d->page->d->insideOpenCall = false;
377 Sets the content of this frame to \a html. \a baseUrl is optional and used to resolve relative
378 URLs in the document.
380 void QWebFrame::setHtml(const QString &html, const QUrl &baseUrl)
383 WebCore::ResourceRequest request(kurl);
384 WTF::RefPtr<WebCore::SharedBuffer> data = WebCore::SharedBuffer::create(reinterpret_cast<const uchar *>(html.unicode()), html.length() * 2);
385 WebCore::SubstituteData substituteData(data, WebCore::String("text/html"), WebCore::String("utf-16"), kurl);
386 d->frame->loader()->load(request, substituteData);
392 void QWebFrame::setHtml(const QByteArray &html, const QUrl &baseUrl)
394 setContent(html, QString(), baseUrl);
398 Sets the content of this frame to \a data assuming \a mimeType. If
399 \a mimeType is not specified it defaults to 'text/html'. \a baseUrl
400 us optional and used to resolve relative URLs in the document.
402 void QWebFrame::setContent(const QByteArray &data, const QString &mimeType, const QUrl &baseUrl)
405 WebCore::ResourceRequest request(kurl);
406 WTF::RefPtr<WebCore::SharedBuffer> buffer = WebCore::SharedBuffer::create(data.constData(), data.length());
407 QString actualMimeType = mimeType;
408 if (actualMimeType.isEmpty())
409 actualMimeType = QLatin1String("text/html");
410 WebCore::SubstituteData substituteData(buffer, WebCore::String(actualMimeType), WebCore::String(), kurl);
411 d->frame->loader()->load(request, substituteData);
416 Returns the parent frame of this frame, or 0 if the frame is the web pages
419 This is equivalent to qobject_cast<QWebFrame*>(frame->parent()).
421 QWebFrame *QWebFrame::parentFrame() const
423 return d->parentFrame();
427 Returns a list of all frames that are direct children of this frame.
429 QList<QWebFrame*> QWebFrame::childFrames() const
431 QList<QWebFrame*> rc;
433 FrameTree *tree = d->frame->tree();
434 for (Frame *child = tree->firstChild(); child; child = child->tree()->nextSibling()) {
435 FrameLoader *loader = child->loader();
436 FrameLoaderClientQt *client = static_cast<FrameLoaderClientQt*>(loader->client());
438 rc.append(client->webFrame());
446 \property QWebFrame::verticalScrollBarPolicy
448 This property defines the vertical scrollbar policy.
450 \sa Qt::ScrollBarPolicy
452 Qt::ScrollBarPolicy QWebFrame::verticalScrollBarPolicy() const
454 return d->verticalScrollBarPolicy;
457 void QWebFrame::setVerticalScrollBarPolicy(Qt::ScrollBarPolicy policy)
459 Q_ASSERT((int)ScrollbarAuto == (int)Qt::ScrollBarAsNeeded);
460 Q_ASSERT((int)ScrollbarAlwaysOff == (int)Qt::ScrollBarAlwaysOff);
461 Q_ASSERT((int)ScrollbarAlwaysOn == (int)Qt::ScrollBarAlwaysOn);
463 d->verticalScrollBarPolicy = policy;
464 if (d->frame->view())
465 d->frame->view()->setVScrollbarMode((ScrollbarMode)policy);
469 \property QWebFrame::horizontalScrollBarPolicy
471 This property defines the horizontal scrollbar policy.
473 \sa Qt::ScrollBarPolicy
475 Qt::ScrollBarPolicy QWebFrame::horizontalScrollBarPolicy() const
477 return d->horizontalScrollBarPolicy;
480 void QWebFrame::setHorizontalScrollBarPolicy(Qt::ScrollBarPolicy policy)
482 d->horizontalScrollBarPolicy = policy;
483 if (d->frame->view())
484 d->frame->view()->setHScrollbarMode((ScrollbarMode)policy);
488 Render the frame into \a painter clipping to \a clip.
490 void QWebFrame::render(QPainter *painter, const QRegion &clip)
492 if (!d->frame->view() || !d->frame->renderer())
497 GraphicsContext ctx(painter);
498 QVector<QRect> vector = clip.rects();
499 WebCore::FrameView* view = d->frame->view();
500 for (int i = 0; i < vector.size(); ++i)
501 view->paint(&ctx, vector.at(i));
505 Ensure that the content of the frame and all subframes are correctly layouted.
507 void QWebFrame::layout()
509 if (!d->frame->view())
512 d->frame->view()->layoutIfNeededRecursive();
516 returns the position of the frame relative to it's parent frame.
518 QPoint QWebFrame::pos() const
520 if (!d->frame->view())
523 return d->frame->view()->frameGeometry().topLeft();
527 return the geometry of the frame relative to it's parent frame.
529 QRect QWebFrame::geometry() const
531 if (!d->frame->view())
533 return d->frame->view()->frameGeometry();
537 Evaluate JavaScript defined by \a scriptSource using this frame as context.
539 QString QWebFrame::evaluateJavaScript(const QString& scriptSource)
541 KJSProxy *proxy = d->frame->scriptProxy();
544 KJS::JSValue *v = proxy->evaluate(String(), 0, scriptSource);
546 rc = String(v->toString(proxy->globalObject()->globalExec()));
552 WebCore::Frame* QWebFramePrivate::core(QWebFrame* webFrame)
554 return webFrame->d->frame.get();
557 QWebFrame* QWebFramePrivate::kit(WebCore::Frame* coreFrame)
559 return static_cast<FrameLoaderClientQt*>(coreFrame->loader()->client())->webFrame();
564 \fn void QWebFrame::cleared()
566 This signal is emitted whenever the content of the frame is cleared
567 (e.g. before starting a new load).
571 \fn void QWebFrame::loadDone(bool ok)
573 This signal is emitted when the frame is completely loaded. \a ok will indicate whether the load
574 was successful or any error occurred.
578 \fn void QWebFrame::provisionalLoad()
584 \fn void QWebFrame::titleChanged(const QString &title)
586 This signal is emitted whenever the title of the frame changes.
587 The \a title string specifies the new title.
593 \fn void QWebFrame::urlChanged(const QUrl &url)
595 This signal is emitted whenever the \a url of the frame changes.
601 \fn void QWebFrame::hoveringOverLink(const QString &link, const QString &title, const QString &textContent)
603 This signal is emitted whenever the mouse cursor is hovering over a
604 link. It can be used to display information about the link in
605 e.g. the status bar. The signal arguments consist of the \a link destination, the \a title and the
606 link text as \a textContent .
611 \fn void QWebFrame::loadStarted()
613 This signal is emitted when a new load of the frame is started.
617 \fn void QWebFrame::loadFinished()
619 This signal is emitted when a load of the frame is finished.
623 \fn void QWebFrame::initialLayoutComplete()
625 This signal is emitted when the first (initial) layout of the frame
626 has happened. This is the earliest time something can be shown on
631 \fn void QWebFrame::iconLoaded()
633 This signal is emitted when the icon ("favicon") associated with the frame has been loaded.