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 "kjs_proxy.h"
59 #include "kjs_binding.h"
60 #include "ExecState.h"
63 #include "wtf/HashMap.h"
68 #if QT_VERSION >= 0x040400
69 #include <qnetworkrequest.h>
71 #include "qwebnetworkinterface.h"
75 using namespace WebCore;
77 void QWebFramePrivate::init(QWebFrame *qframe, WebCore::Page *webcorePage, QWebFrameData *frameData)
81 frameLoaderClient = new FrameLoaderClientQt();
82 frame = new Frame(webcorePage, frameData->ownerElement, frameLoaderClient);
83 frameLoaderClient->setFrame(qframe, frame.get());
85 frameView = new FrameView(frame.get());
87 frameView->setQWebFrame(qframe);
88 if (!frameData->allowsScrolling)
89 frameView->setScrollbarsMode(ScrollbarAlwaysOff);
90 if (frameData->marginWidth != -1)
91 frameView->setMarginWidth(frameData->marginWidth);
92 if (frameData->marginHeight != -1)
93 frameView->setMarginHeight(frameData->marginHeight);
95 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
105 return frameView->horizontalScrollBar();
108 WebCore::PlatformScrollbar *QWebFramePrivate::verticalScrollBar() const
111 return frameView->verticalScrollBar();
117 \brief The QWebFrame class represents a frame in a web page.
119 QWebFrame represents a frame inside a web page. Each QWebPage
120 object contains at least one frame, the mainFrame(). Additional
121 frames will be created for HTML <frame> or <iframe>
124 QWebFrame objects are created and controlled by the web page. You
125 can connect to the web pages frameCreated() signal to find out
126 about creation of new frames.
131 QWebFrame::QWebFrame(QWebPage *parent, QWebFrameData *frameData)
133 , d(new QWebFramePrivate)
136 d->init(this, parent->d->page, frameData);
138 if (!frameData->url.isEmpty()) {
139 ResourceRequest request(frameData->url, frameData->referrer);
140 d->frame->loader()->load(request, frameData->name);
144 QWebFrame::QWebFrame(QWebFrame *parent, QWebFrameData *frameData)
146 , d(new QWebFramePrivate)
148 d->page = parent->d->page;
149 d->init(this, parent->d->page->d->page, frameData);
152 QWebFrame::~QWebFrame()
154 Q_ASSERT(d->frame == 0);
155 Q_ASSERT(d->frameView == 0);
160 Make \a object available under \a name from within the frames
161 JavaScript context. The \a object will be inserted as a child of the
162 frames window object.
164 Qt properties will be exposed as JavaScript properties and slots as
167 void QWebFrame::addToJSWindowObject(const QString &name, QObject *object)
170 JSDOMWindow *window = toJSDOMWindow(d->frame.get());
171 KJS::Bindings::RootObject *root = d->frame->bindingRootObject();
173 qDebug() << "Warning: couldn't get window object";
177 KJS::JSObject *runtimeObject =
178 KJS::Bindings::Instance::createRuntimeObject(KJS::Bindings::Instance::QtLanguage,
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->frameView->layoutPending())
200 d->frameView->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->frameView->layoutPending())
212 d->frameView->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 = new WebCore::SharedBuffer(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 = new WebCore::SharedBuffer(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 (Qt::ScrollBarPolicy) d->frameView->vScrollbarMode();
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);
462 d->frameView->setVScrollbarMode((ScrollbarMode)policy);
466 \property QWebFrame::horizontalScrollBarPolicy
468 This property defines the horizontal scrollbar policy.
470 \sa Qt::ScrollBarPolicy
472 Qt::ScrollBarPolicy QWebFrame::horizontalScrollBarPolicy() const
474 return (Qt::ScrollBarPolicy) d->frameView->hScrollbarMode();
477 void QWebFrame::setHorizontalScrollBarPolicy(Qt::ScrollBarPolicy policy)
479 d->frameView->setHScrollbarMode((ScrollbarMode)policy);
483 Render the frame into \a painter clipping to \a clip.
485 void QWebFrame::render(QPainter *painter, const QRegion &clip)
487 if (!d->frameView || !d->frame->renderer())
492 GraphicsContext ctx(painter);
493 QVector<QRect> vector = clip.rects();
494 for (int i = 0; i < vector.size(); ++i)
495 d->frameView->paint(&ctx, vector.at(i));
499 Ensure that the content of the frame and all subframes are correctly layouted.
501 void QWebFrame::layout()
506 d->frameView->layoutIfNeededRecursive();
510 returns the position of the frame relative to it's parent frame.
512 QPoint QWebFrame::pos() const
514 Q_ASSERT(d->frameView);
519 return the geometry of the frame relative to it's parent frame.
521 QRect QWebFrame::geometry() const
523 Q_ASSERT(d->frameView);
524 return d->frameView->frameGeometry();
528 Evaluate JavaScript defined by \a scriptSource using this frame as context.
530 QString QWebFrame::evaluateJavaScript(const QString& scriptSource)
532 KJSProxy *proxy = d->frame->scriptProxy();
535 KJS::JSValue *v = proxy->evaluate(String(), 0, scriptSource);
537 rc = String(v->toString(proxy->globalObject()->globalExec()));
543 WebCore::Frame* QWebFramePrivate::core(QWebFrame* webFrame)
545 return webFrame->d->frame.get();
548 QWebFrame* QWebFramePrivate::kit(WebCore::Frame* coreFrame)
550 return static_cast<FrameLoaderClientQt*>(coreFrame->loader()->client())->webFrame();
555 \fn void QWebFrame::cleared()
557 This signal is emitted whenever the content of the frame is cleared
558 (e.g. before starting a new load).
562 \fn void QWebFrame::loadDone(bool ok)
564 This signal is emitted when the frame is completely loaded. \a ok will indicate whether the load
565 was successful or any error occurred.
569 \fn void QWebFrame::provisionalLoad()
575 \fn void QWebFrame::titleChanged(const QString &title)
577 This signal is emitted whenever the title of the frame changes.
578 The \a title string specifies the new title.
584 \fn void QWebFrame::urlChanged(const QUrl &url)
586 This signal is emitted whenever the \a url of the frame changes.
592 \fn void QWebFrame::hoveringOverLink(const QString &link, const QString &title, const QString &textContent)
594 This signal is emitted whenever the mouse cursor is hovering over a
595 link. It can be used to display information about the link in
596 e.g. the status bar. The signal arguments consist of the \a link destination, the \a title and the
597 link text as \a textContent .
602 \fn void QWebFrame::loadStarted()
604 This signal is emitted when a new load of the frame is started.
608 \fn void QWebFrame::loadFinished()
610 This signal is emitted when a load of the frame is finished.
614 \fn void QWebFrame::initialLayoutComplete()
616 This signal is emitted when the first (initial) layout of the frame
617 has happened. This is the earliest time something can be shown on
622 \fn void QWebFrame::iconLoaded()
624 This signal is emitted when the icon ("favicon") associated with the frame has been loaded.