diff options
Diffstat (limited to 'WebKit/qt/Api')
28 files changed, 6980 insertions, 0 deletions
diff --git a/WebKit/qt/Api/headers.pri b/WebKit/qt/Api/headers.pri new file mode 100644 index 0000000..1e70072 --- /dev/null +++ b/WebKit/qt/Api/headers.pri @@ -0,0 +1,11 @@ +WEBKIT_API_HEADERS = $$PWD/qcookiejar.h \ + $$PWD/qwebframe.h \ + $$PWD/qwebkitglobal.h \ + $$PWD/qwebnetworkinterface.h \ + $$PWD/qwebobjectplugin.h \ + $$PWD/qwebobjectpluginconnector.h \ + $$PWD/qwebpage.h \ + $$PWD/qwebview.h \ + $$PWD/qwebpagehistory.h \ + $$PWD/qwebsettings.h \ + $$PWD/qwebhistoryinterface.h diff --git a/WebKit/qt/Api/qcookiejar.cpp b/WebKit/qt/Api/qcookiejar.cpp new file mode 100644 index 0000000..a6cbdab --- /dev/null +++ b/WebKit/qt/Api/qcookiejar.cpp @@ -0,0 +1,105 @@ +/* + Copyright (C) 2007 Staikos Computing Services Inc. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + + +#include "qcookiejar.h" +#include <QCoreApplication> +uint qHash(const QUrl&); +#include <QHash> +#include <QPointer> + +class QCookieJarPrivate { + public: + QCookieJarPrivate() { + enabled = true; + } + bool enabled; + QHash<QUrl, QString> jar; +}; + + +uint qHash(const QUrl& url) { + return qHash(url.toString()); +} + + +QCookieJar::QCookieJar() +: QObject(), d(new QCookieJarPrivate) +{ +} + + +QCookieJar::~QCookieJar() +{ + delete d; +} + + +void QCookieJar::setCookies(const QUrl& url, const QUrl& policyUrl, const QString& value) +{ + Q_UNUSED(policyUrl) + d->jar.insert(url, value); +} + + +QString QCookieJar::cookies(const QUrl& url) +{ + return d->jar.value(url); +} + + +bool QCookieJar::isEnabled() const +{ + return d->enabled; +} + + +void QCookieJar::setEnabled(bool enabled) +{ + d->enabled = enabled; +} + + +static QPointer<QCookieJar> gJar; +static bool gRoutineAdded = false; + +static void gCleanupJar() +{ + delete gJar; +} + + +void QCookieJar::setCookieJar(QCookieJar *jar) +{ + if (!gRoutineAdded) { + qAddPostRoutine(gCleanupJar); + gRoutineAdded = true; + } + delete gJar; + gJar = jar; +} + + +QCookieJar *QCookieJar::cookieJar() +{ + if (!gJar) { + setCookieJar(new QCookieJar); + } + return gJar; +} diff --git a/WebKit/qt/Api/qcookiejar.h b/WebKit/qt/Api/qcookiejar.h new file mode 100644 index 0000000..0ca00bd --- /dev/null +++ b/WebKit/qt/Api/qcookiejar.h @@ -0,0 +1,55 @@ +/* + Copyright (C) 2007 Staikos Computing Services Inc. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifndef QCOOKIEJAR_H +#define QCOOKIEJAR_H + +#include <QtCore/qobject.h> +#include <QtCore/qurl.h> +#include "qwebkitglobal.h" + +class QCookieJarPrivate; + +class QWEBKIT_EXPORT QCookieJar : public QObject +{ + Q_OBJECT + + Q_PROPERTY(bool enabled READ isEnabled WRITE setEnabled) +public: + QCookieJar(); + ~QCookieJar(); + + virtual void setCookies(const QUrl& url, const QUrl& policyUrl, const QString& value); + virtual QString cookies(const QUrl& url); + + bool isEnabled() const; + + static void setCookieJar(QCookieJar *jar); + static QCookieJar *cookieJar(); + +public slots: + virtual void setEnabled(bool enabled); + +private: + friend class QCookieJarPrivate; + QCookieJarPrivate *d; +}; + + +#endif diff --git a/WebKit/qt/Api/qtwebkit.prf b/WebKit/qt/Api/qtwebkit.prf new file mode 100644 index 0000000..37417c6 --- /dev/null +++ b/WebKit/qt/Api/qtwebkit.prf @@ -0,0 +1,4 @@ + +qtAddLibrary(QtWebKit) + +QT += network diff --git a/WebKit/qt/Api/qwebframe.cpp b/WebKit/qt/Api/qwebframe.cpp new file mode 100644 index 0000000..155731c --- /dev/null +++ b/WebKit/qt/Api/qwebframe.cpp @@ -0,0 +1,625 @@ +/* + Copyright (C) 2007 Trolltech ASA + Copyright (C) 2007 Staikos Computing Services Inc. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. + + This class provides all functionality needed for loading images, style sheets and html + pages from the web. It has a memory cache for these objects. +*/ +#include "config.h" +#include "qwebframe.h" +#include "qwebpage.h" +#include "qwebpage_p.h" +#include "qwebframe_p.h" + +#include "DocumentLoader.h" +#include "FocusController.h" +#include "FrameLoaderClientQt.h" +#include "Frame.h" +#include "FrameTree.h" +#include "FrameView.h" +#include "IconDatabase.h" +#include "Page.h" +#include "ResourceRequest.h" +#include "SelectionController.h" +#include "PlatformScrollBar.h" +#include "SubstituteData.h" + +#include "markup.h" +#include "RenderTreeAsText.h" +#include "Element.h" +#include "Document.h" +#include "DragData.h" +#include "RenderObject.h" +#include "GraphicsContext.h" +#include "PlatformScrollBar.h" +#include "PlatformMouseEvent.h" +#include "PlatformWheelEvent.h" +#include "GraphicsContext.h" +#include "HitTestResult.h" + +#include "bindings/runtime.h" +#include "bindings/runtime_root.h" +#include "kjs_proxy.h" +#include "kjs_window.h" +#include "kjs_binding.h" +#include "ExecState.h" +#include "object.h" + +#include "wtf/HashMap.h" + +#include <qdebug.h> +#include <qevent.h> +#include <qpainter.h> +#if QT_VERSION >= 0x040400 +#include <qnetworkrequest.h> +#else +#include "qwebnetworkinterface.h" +#endif +#include <qregion.h> + +using namespace WebCore; + +void QWebFramePrivate::init(QWebFrame *qframe, WebCore::Page *webcorePage, QWebFrameData *frameData) +{ + q = qframe; + + frameLoaderClient = new FrameLoaderClientQt(); + frame = new Frame(webcorePage, frameData->ownerElement, frameLoaderClient); + frameLoaderClient->setFrame(qframe, frame.get()); + + frameView = new FrameView(frame.get()); + frameView->deref(); + frameView->setQWebFrame(qframe); + if (!frameData->allowsScrolling) + frameView->setScrollbarsMode(ScrollbarAlwaysOff); + if (frameData->marginWidth != -1) + frameView->setMarginWidth(frameData->marginWidth); + if (frameData->marginHeight != -1) + frameView->setMarginHeight(frameData->marginHeight); + + frame->setView(frameView.get()); + frame->init(); + + QObject::connect(q, SIGNAL(hoveringOverLink(const QString&, const QString&, const QString&)), + page, SIGNAL(hoveringOverLink(const QString&, const QString&, const QString&))); +} + +WebCore::PlatformScrollbar *QWebFramePrivate::horizontalScrollBar() const +{ + Q_ASSERT(frameView); + return frameView->horizontalScrollBar(); +} + +WebCore::PlatformScrollbar *QWebFramePrivate::verticalScrollBar() const +{ + Q_ASSERT(frameView); + return frameView->verticalScrollBar(); +} + +/*! + \class QWebFrame + \since 4.4 + \brief The QWebFrame class represents a frame in a web page. + + QWebFrame represents a frame inside a web page. Each QWebPage + object contains at least one frame, the mainFrame(). Additional + frames will be created for HTML <frame> or <iframe> + elements. + + QWebFrame objects are created and controlled by the web page. You + can connect to the web pages frameCreated() signal to find out + about creation of new frames. + + \sa QWebPage +*/ + +QWebFrame::QWebFrame(QWebPage *parent, QWebFrameData *frameData) + : QObject(parent) + , d(new QWebFramePrivate) +{ + d->page = parent; + d->init(this, parent->d->page, frameData); + + if (!frameData->url.isEmpty()) { + ResourceRequest request(frameData->url, frameData->referrer); + d->frame->loader()->load(request, frameData->name); + } +} + +QWebFrame::QWebFrame(QWebFrame *parent, QWebFrameData *frameData) + : QObject(parent) + , d(new QWebFramePrivate) +{ + d->page = parent->d->page; + d->init(this, parent->d->page->d->page, frameData); +} + +QWebFrame::~QWebFrame() +{ + Q_ASSERT(d->frame == 0); + Q_ASSERT(d->frameView == 0); + delete d; +} + +/*! + Make \a object available under \a name from within the frames + JavaScript context. The \a object will be inserted as a child of the + frames window object. + + Qt properties will be exposed as JavaScript properties and slots as + JavaScript methods. +*/ +void QWebFrame::addToJSWindowObject(const QString &name, QObject *object) +{ + KJS::JSLock lock; + KJS::Window *window = KJS::Window::retrieveWindow(d->frame.get()); + KJS::Bindings::RootObject *root = d->frame->bindingRootObject(); + if (!window) { + qDebug() << "Warning: couldn't get window object"; + return; + } + + KJS::JSObject *runtimeObject = + KJS::Bindings::Instance::createRuntimeObject(KJS::Bindings::Instance::QtLanguage, + object, root); + + window->put(window->globalExec(), KJS::Identifier((const KJS::UChar *) name.constData(), name.length()), runtimeObject); +} + +/*! + returns the markup (HTML) contained in the current frame. +*/ +QString QWebFrame::markup() const +{ + if (!d->frame->document()) + return QString(); + return createMarkup(d->frame->document()); +} + +/*! + returns the content of this frame as plain text. +*/ +QString QWebFrame::innerText() const +{ + if (d->frameView->layoutPending()) + d->frameView->layout(); + + Element *documentElement = d->frame->document()->documentElement(); + return documentElement->innerText(); +} + +/*! + returns a dump of the rendering tree. Mainly useful for debugging html. +*/ +QString QWebFrame::renderTreeDump() const +{ + if (d->frameView->layoutPending()) + d->frameView->layout(); + + return externalRepresentation(d->frame->renderer()); +} + +/*! + The title of the frame as defined by the HTML <title> + element. +*/ +QString QWebFrame::title() const +{ + if (d->frame->document()) + return d->frame->loader()->documentLoader()->title(); + else return QString(); +} + +/*! + The url of this frame. +*/ +QUrl QWebFrame::url() const +{ + return d->frame->loader()->url(); +} + +/*! + The icon associated with this frame. +*/ +QPixmap QWebFrame::icon() const +{ + String url = d->frame->loader()->url().string(); + + Image* image = 0; + if (!url.isEmpty()) { + image = iconDatabase()->iconForPageURL(url, IntSize(16, 16)); + } + + if (!image || image->isNull()) { + image = iconDatabase()->defaultIcon(IntSize(16, 16)); + } + + if (!image) { + return QPixmap(); + } + + QPixmap *icon = image->getPixmap(); + if (!icon) { + return QPixmap(); + } + return *icon; +} + +/*! + The name of this frame as defined by the parent frame. +*/ +QString QWebFrame::name() const +{ + return d->frame->tree()->name(); +} + +/*! + The web page that contains this frame. +*/ +QWebPage *QWebFrame::page() const +{ + return d->page; +} + +/*! + Load \a url into this frame. +*/ +void QWebFrame::load(const QUrl &url) +{ +#if QT_VERSION < 0x040400 + load(QWebNetworkRequest(url)); +#else + load(QNetworkRequest(url)); +#endif +} + +#if QT_VERSION < 0x040400 +/*! + Load network request \a req into this frame. +*/ +void QWebFrame::load(const QWebNetworkRequest &req) +{ + if (d->parentFrame()) + d->page->d->insideOpenCall = true; + + QUrl url = req.url(); + QHttpRequestHeader httpHeader = req.httpHeader(); + QByteArray postData = req.postData(); + + WebCore::ResourceRequest request(url); + + QString method = httpHeader.method(); + if (!method.isEmpty()) + request.setHTTPMethod(method); + + QList<QPair<QString, QString> > values = httpHeader.values(); + for (int i = 0; i < values.size(); ++i) { + const QPair<QString, QString> &val = values.at(i); + request.addHTTPHeaderField(val.first, val.second); + } + + if (!postData.isEmpty()) + request.setHTTPBody(WebCore::FormData::create(postData.constData(), postData.size())); + + d->frame->loader()->load(request); + + if (d->parentFrame()) + d->page->d->insideOpenCall = false; +} + +#else + +/*! + Load network request \a req into this frame. Use the method specified in \a + operation. \a body is optional and is only used for POST operations. +*/ +void QWebFrame::load(const QNetworkRequest &req, + QNetworkAccessManager::Operation operation, + const QByteArray &body) +{ + if (d->parentFrame()) + d->page->d->insideOpenCall = true; + + QUrl url = req.url(); + + WebCore::ResourceRequest request(url); + + switch (operation) { + case QNetworkAccessManager::HeadOperation: + request.setHTTPMethod("HEAD"); + break; + case QNetworkAccessManager::GetOperation: + request.setHTTPMethod("GET"); + break; + case QNetworkAccessManager::PutOperation: + request.setHTTPMethod("PUT"); + break; + case QNetworkAccessManager::PostOperation: + request.setHTTPMethod("POST"); + break; + case QNetworkAccessManager::UnknownOperation: + // eh? + break; + } + + QList<QByteArray> httpHeaders = req.rawHeaderList(); + for (int i = 0; i < httpHeaders.size(); ++i) { + const QByteArray &headerName = httpHeaders.at(i); + request.addHTTPHeaderField(QString::fromLatin1(headerName), QString::fromLatin1(req.rawHeader(headerName))); + } + + if (!body.isEmpty()) + request.setHTTPBody(WebCore::FormData::create(body.constData(), body.size())); + + d->frame->loader()->load(request); + + if (d->parentFrame()) + d->page->d->insideOpenCall = false; +} +#endif + +/*! + Sets the content of this frame to \a html. \a baseUrl is optional and used to resolve relative + URLs in the document. +*/ +void QWebFrame::setHtml(const QString &html, const QUrl &baseUrl) +{ + KURL kurl(baseUrl); + WebCore::ResourceRequest request(kurl); + WTF::RefPtr<WebCore::SharedBuffer> data = new WebCore::SharedBuffer(reinterpret_cast<const uchar *>(html.unicode()), html.length() * 2); + WebCore::SubstituteData substituteData(data, WebCore::String("text/html"), WebCore::String("utf-16"), kurl); + d->frame->loader()->load(request, substituteData); +} + +/*! + \overload +*/ +void QWebFrame::setHtml(const QByteArray &html, const QUrl &baseUrl) +{ + setContent(html, QString(), baseUrl); +} + +/*! + Sets the content of this frame to \a data assuming \a mimeType. If + \a mimeType is not specified it defaults to 'text/html'. \a baseUrl + us optional and used to resolve relative URLs in the document. +*/ +void QWebFrame::setContent(const QByteArray &data, const QString &mimeType, const QUrl &baseUrl) +{ + KURL kurl(baseUrl); + WebCore::ResourceRequest request(kurl); + WTF::RefPtr<WebCore::SharedBuffer> buffer = new WebCore::SharedBuffer(data.constData(), data.length()); + QString actualMimeType = mimeType; + if (actualMimeType.isEmpty()) + actualMimeType = QLatin1String("text/html"); + WebCore::SubstituteData substituteData(buffer, WebCore::String(actualMimeType), WebCore::String(), kurl); + d->frame->loader()->load(request, substituteData); +} + + +/*! + Returns the parent frame of this frame, or 0 if the frame is the web pages + main frame. + + This is equivalent to qobject_cast<QWebFrame*>(frame->parent()). +*/ +QWebFrame *QWebFrame::parentFrame() const +{ + return d->parentFrame(); +} + +/*! + Returns a list of all frames that are direct children of this frame. +*/ +QList<QWebFrame*> QWebFrame::childFrames() const +{ + QList<QWebFrame*> rc; + if (d->frame) { + FrameTree *tree = d->frame->tree(); + for (Frame *child = tree->firstChild(); child; child = child->tree()->nextSibling()) { + FrameLoader *loader = child->loader(); + FrameLoaderClientQt *client = static_cast<FrameLoaderClientQt*>(loader->client()); + if (client) + rc.append(client->webFrame()); + } + + } + return rc; +} + +/*! + \property QWebFrame::verticalScrollBarPolicy + + This property defines the vertical scrollbar policy. + + \sa Qt::ScrollBarPolicy +*/ +Qt::ScrollBarPolicy QWebFrame::verticalScrollBarPolicy() const +{ + return (Qt::ScrollBarPolicy) d->frameView->vScrollbarMode(); +} + +void QWebFrame::setVerticalScrollBarPolicy(Qt::ScrollBarPolicy policy) +{ + Q_ASSERT((int)ScrollbarAuto == (int)Qt::ScrollBarAsNeeded); + Q_ASSERT((int)ScrollbarAlwaysOff == (int)Qt::ScrollBarAlwaysOff); + Q_ASSERT((int)ScrollbarAlwaysOn == (int)Qt::ScrollBarAlwaysOn); + d->frameView->setVScrollbarMode((ScrollbarMode)policy); +} + +/*! + \property QWebFrame::horizontalScrollBarPolicy + + This property defines the horizontal scrollbar policy. + + \sa Qt::ScrollBarPolicy +*/ +Qt::ScrollBarPolicy QWebFrame::horizontalScrollBarPolicy() const +{ + return (Qt::ScrollBarPolicy) d->frameView->hScrollbarMode(); +} + +void QWebFrame::setHorizontalScrollBarPolicy(Qt::ScrollBarPolicy policy) +{ + d->frameView->setHScrollbarMode((ScrollbarMode)policy); +} + +/*! + Render the frame into \a painter clipping to \a clip. +*/ +void QWebFrame::render(QPainter *painter, const QRegion &clip) +{ + if (!d->frameView || !d->frame->renderer()) + return; + + layout(); + + GraphicsContext ctx(painter); + QVector<QRect> vector = clip.rects(); + for (int i = 0; i < vector.size(); ++i) + d->frameView->paint(&ctx, vector.at(i)); +} + +/*! + Ensure that the content of the frame and all subframes are correctly layouted. +*/ +void QWebFrame::layout() +{ + if (!d->frameView) + return; + + d->frameView->layoutIfNeededRecursive(); +} + +/*! + returns the position of the frame relative to it's parent frame. +*/ +QPoint QWebFrame::pos() const +{ + Q_ASSERT(d->frameView); + return d->pos(); +} + +/*! + return the geometry of the frame relative to it's parent frame. +*/ +QRect QWebFrame::geometry() const +{ + Q_ASSERT(d->frameView); + return d->frameView->frameGeometry(); +} + +/*! + Evaluate JavaScript defined by \a scriptSource using this frame as context. +*/ +QString QWebFrame::evaluateJavaScript(const QString& scriptSource) +{ + KJSProxy *proxy = d->frame->scriptProxy(); + QString rc; + if (proxy) { + KJS::JSValue *v = proxy->evaluate(String(), 0, scriptSource); + if (v) { + rc = String(v->toString(proxy->globalObject()->globalExec())); + } + } + return rc; +} + +WebCore::Frame* QWebFramePrivate::core(QWebFrame* webFrame) +{ + return webFrame->d->frame.get(); +} + +QWebFrame* QWebFramePrivate::kit(WebCore::Frame* coreFrame) +{ + return static_cast<FrameLoaderClientQt*>(coreFrame->loader()->client())->webFrame(); +} + + +/*! + \fn void QWebFrame::cleared() + + This signal is emitted whenever the content of the frame is cleared + (e.g. before starting a new load). +*/ + +/*! + \fn void QWebFrame::loadDone(bool ok) + + This signal is emitted when the frame is completely loaded. \a ok will indicate whether the load + was successful or any error occurred. +*/ + +/*! + \fn void QWebFrame::provisionalLoad() + + \internal +*/ + +/*! + \fn void QWebFrame::titleChanged(const QString &title) + + This signal is emitted whenever the title of the frame changes. + The \a title string specifies the new title. + + \sa title() +*/ + +/*! + \fn void QWebFrame::urlChanged(const QUrl &url) + + This signal is emitted whenever the \a url of the frame changes. + + \sa url() +*/ + +/*! + \fn void QWebFrame::hoveringOverLink(const QString &link, const QString &title, const QString &textContent) + + This signal is emitted whenever the mouse cursor is hovering over a + link. It can be used to display information about the link in + e.g. the status bar. The signal arguments consist of the \a link destination, the \a title and the + link text as \a textContent . +*/ + + +/*! + \fn void QWebFrame::loadStarted() + + This signal is emitted when a new load of the frame is started. +*/ + +/*! + \fn void QWebFrame::loadFinished() + + This signal is emitted when a load of the frame is finished. +*/ + +/*! + \fn void QWebFrame::initialLayoutComplete() + + This signal is emitted when the first (initial) layout of the frame + has happened. This is the earliest time something can be shown on + the screen. +*/ + +/*! + \fn void QWebFrame::iconLoaded() + + This signal is emitted when the icon ("favicon") associated with the frame has been loaded. +*/ diff --git a/WebKit/qt/Api/qwebframe.h b/WebKit/qt/Api/qwebframe.h new file mode 100644 index 0000000..a1cdb25 --- /dev/null +++ b/WebKit/qt/Api/qwebframe.h @@ -0,0 +1,138 @@ +/* + Copyright (C) 2007 Trolltech ASA + Copyright (C) 2007 Staikos Computing Services Inc. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. + + This class provides all functionality needed for loading images, style sheets and html + pages from the web. It has a memory cache for these objects. +*/ + +#ifndef QWEBFRAME_H +#define QWEBFRAME_H + +#include <QtCore/qobject.h> +#include <QtCore/qurl.h> +#if QT_VERSION >= 0x040400 +#include <QtNetwork/qnetworkaccessmanager.h> +#endif +#include "qwebkitglobal.h" + +class QRect; +class QPoint; +class QPainter; +class QPixmap; +class QMouseEvent; +class QWheelEvent; +class QWebNetworkRequest; +class QNetworkRequest; + +class QWebFramePrivate; +class QWebPage; +class QRegion; + +namespace WebCore { + class WidgetPrivate; + class FrameLoaderClientQt; + class ChromeClientQt; +} +class QWebFrameData; + +class QWEBKIT_EXPORT QWebFrame : public QObject +{ + Q_OBJECT + Q_PROPERTY(Qt::ScrollBarPolicy verticalScrollBarPolicy READ verticalScrollBarPolicy WRITE setVerticalScrollBarPolicy) + Q_PROPERTY(Qt::ScrollBarPolicy horizontalScrollBarPolicy READ horizontalScrollBarPolicy WRITE setHorizontalScrollBarPolicy) +private: + QWebFrame(QWebPage *parent, QWebFrameData *frameData); + QWebFrame(QWebFrame *parent, QWebFrameData *frameData); + ~QWebFrame(); + +public: + QWebPage *page() const; + + void load(const QUrl &url); +#if QT_VERSION < 0x040400 + void load(const QWebNetworkRequest &request); +#else + void load(const QNetworkRequest &request, + QNetworkAccessManager::Operation operation = QNetworkAccessManager::GetOperation, + const QByteArray &body = QByteArray()); +#endif + void setHtml(const QString &html, const QUrl &baseUrl = QUrl()); + void setHtml(const QByteArray &html, const QUrl &baseUrl = QUrl()); + void setContent(const QByteArray &data, const QString &mimeType = QString(), const QUrl &baseUrl = QUrl()); + + void addToJSWindowObject(const QString &name, QObject *object); + QString markup() const; + QString innerText() const; + QString renderTreeDump() const; + + QString title() const; + QUrl url() const; + QPixmap icon() const; + + QString name() const; + + QWebFrame *parentFrame() const; + QList<QWebFrame*> childFrames() const; + + Qt::ScrollBarPolicy verticalScrollBarPolicy() const; + void setVerticalScrollBarPolicy(Qt::ScrollBarPolicy); + Qt::ScrollBarPolicy horizontalScrollBarPolicy() const; + void setHorizontalScrollBarPolicy(Qt::ScrollBarPolicy); + + void render(QPainter *painter, const QRegion &clip); + void layout(); + + QPoint pos() const; + QRect geometry() const; + +public Q_SLOTS: + QString evaluateJavaScript(const QString& scriptSource); + +Q_SIGNALS: + void cleared(); + void loadDone(bool ok); + void provisionalLoad(); + void titleChanged(const QString &title); + void hoveringOverLink(const QString &link, const QString &title, const QString &textContent); + void urlChanged(const QUrl &url); + + void loadStarted(); + void loadFinished(); + + /** + * Signal is emitted when the mainframe()'s initial layout is completed. + */ + void initialLayoutComplete(); + + /** + * Signal is emitted when an icon ("favicon") is loaded from the site. + */ + void iconLoaded(); + +private: + friend class QWebPage; + friend class QWebPagePrivate; + friend class QWebFramePrivate; + friend class WebCore::WidgetPrivate; + friend class WebCore::FrameLoaderClientQt; + friend class WebCore::ChromeClientQt; + QWebFramePrivate *d; +}; + +#endif diff --git a/WebKit/qt/Api/qwebframe_p.h b/WebKit/qt/Api/qwebframe_p.h new file mode 100644 index 0000000..136cf78 --- /dev/null +++ b/WebKit/qt/Api/qwebframe_p.h @@ -0,0 +1,90 @@ +/* + Copyright (C) 2007 Trolltech ASA + Copyright (C) 2007 Staikos Computing Services Inc. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. + + This class provides all functionality needed for loading images, style sheets and html + pages from the web. It has a memory cache for these objects. +*/ +#ifndef QWEBFRAME_P_H +#define QWEBFRAME_P_H + +#include "qwebframe.h" +#include "qwebpage_p.h" + +#include "EventHandler.h" +#include "FrameView.h" +#include "KURL.h" +#include "PlatformString.h" +#include "wtf/RefPtr.h" + +namespace WebCore +{ + class FrameLoaderClientQt; + class Frame; + class FrameView; + class HTMLFrameOwnerElement; + class PlatformScrollbar; +} +class QWebPage; + + +class QWebFrameData +{ +public: + WebCore::KURL url; + WebCore::String name; + WebCore::HTMLFrameOwnerElement* ownerElement; + + WebCore::String referrer; + bool allowsScrolling; + int marginWidth; + int marginHeight; +}; + +class QWebFramePrivate +{ +public: + QWebFramePrivate() + : q(0) + , frameLoaderClient(0) + , frame(0) + , frameView(0) + , page(0) + {} + void init(QWebFrame *qframe, WebCore::Page *page, + QWebFrameData *frameData); + + inline QWebFrame *parentFrame() { return qobject_cast<QWebFrame*>(q->parent()); } + + WebCore::PlatformScrollbar *horizontalScrollBar() const; + WebCore::PlatformScrollbar *verticalScrollBar() const; + + inline QPoint pos() const + { return frameView->frameGeometry().topLeft(); } + + static WebCore::Frame* core(QWebFrame*); + static QWebFrame* kit(WebCore::Frame*); + + QWebFrame *q; + WebCore::FrameLoaderClientQt *frameLoaderClient; + WTF::RefPtr<WebCore::Frame> frame; + WTF::RefPtr<WebCore::FrameView> frameView; + QWebPage *page; +}; + +#endif diff --git a/WebKit/qt/Api/qwebhistory.cpp b/WebKit/qt/Api/qwebhistory.cpp new file mode 100644 index 0000000..10127a4 --- /dev/null +++ b/WebKit/qt/Api/qwebhistory.cpp @@ -0,0 +1,281 @@ +/* + Copyright (C) 2007 Trolltech ASA + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. + + This class provides all functionality needed for loading images, style sheets and html + pages from the web. It has a memory cache for these objects. +*/ +#include "qwebhistory.h" +#include "qwebhistory_p.h" + +#include "PlatformString.h" +#include "Image.h" + +#include <QSharedData> + +/*! + \class QWebHistoryItem + \since 4.4 + \brief The QWebHistoryItem class represents one item in the history of a QWebPage + + QWebHistoryItem represents on entry in the history stack of a web page. + + \sa QWebPage::history() QWebHistory + + QWebHistoryItem objects are value based and explicitly shared. +*/ + +/*! + Constructs a history item from \a other. +*/ +QWebHistoryItem::QWebHistoryItem(const QWebHistoryItem &other) + : d(other.d) +{ +} + +/*! + Assigns the \a other history item to this. +*/ +QWebHistoryItem &QWebHistoryItem::operator=(const QWebHistoryItem &other) +{ + d = other.d; + return *this; +} + +/*! + Destructs a history item. +*/ +QWebHistoryItem::~QWebHistoryItem() +{ +} + +/*! + The original url associated with the history item. +*/ +QUrl QWebHistoryItem::originalUrl() const +{ + return QUrl(d->item->originalURL().string()); +} + + +/*! + The current url associated with the history item. +*/ +QUrl QWebHistoryItem::currentUrl() const +{ + return QUrl(d->item->url().string()); +} + + +/*! + The title of the page associated with the history item. +*/ +QString QWebHistoryItem::title() const +{ + return d->item->title(); +} + + +/*! + The time when the apge associated with the item was last visited. +*/ +QDateTime QWebHistoryItem::lastVisited() const +{ + //FIXME : this will be wrong unless we correctly set lastVisitedTime ourselves + return QDateTime::fromTime_t((uint)d->item->lastVisitedTime()); +} + + +/*! + The icon associated with the history item. +*/ +QPixmap QWebHistoryItem::icon() const +{ + return *d->item->icon()->getPixmap(); +} + +/*! + \internal +*/ +QWebHistoryItem::QWebHistoryItem(QWebHistoryItemPrivate *priv) +{ + d = priv; +} + +/*! + \class QWebHistory + \since 4.4 + \brief The QWebHistory class represents the history of a QWebPage + + Each QWebPage contains a history of visited pages that can be accessed by QWebPage::history(). + QWebHistory represents this history and makes it possible to navigate it. +*/ + + +QWebHistory::QWebHistory() + : d(0) +{ +} + +QWebHistory::~QWebHistory() +{ + delete d; +} + +/*! + Clears the history. +*/ +void QWebHistory::clear() +{ + RefPtr<WebCore::HistoryItem> current = d->lst->currentItem(); + int capacity = d->lst->capacity(); + d->lst->setCapacity(0); + d->lst->setCapacity(capacity); + d->lst->addItem(current.get()); + d->lst->goToItem(current.get()); +} + +/*! + returns a list of all items currently in the history. +*/ +QList<QWebHistoryItem> QWebHistory::items() const +{ + const WebCore::HistoryItemVector &items = d->lst->entries(); + + QList<QWebHistoryItem> ret; + for (int i = 0; i < items.size(); ++i) { + QWebHistoryItemPrivate *priv = new QWebHistoryItemPrivate(items[i].get()); + ret.append(QWebHistoryItem(priv)); + } + return ret; +} + +/*! + Returns the list of items that are in the backwards history. + At most \a maxItems entries are returned. +*/ +QList<QWebHistoryItem> QWebHistory::backItems(int maxItems) const +{ + WebCore::HistoryItemVector items(maxItems); + d->lst->backListWithLimit(maxItems, items); + + QList<QWebHistoryItem> ret; + for (int i = 0; i < items.size(); ++i) { + QWebHistoryItemPrivate *priv = new QWebHistoryItemPrivate(items[i].get()); + ret.append(QWebHistoryItem(priv)); + } + return ret; +} + +/*! + Returns the list of items that are in the forward history. + At most \a maxItems entries are returned. +*/ +QList<QWebHistoryItem> QWebHistory::forwardItems(int maxItems) const +{ + WebCore::HistoryItemVector items(maxItems); + d->lst->forwardListWithLimit(maxItems, items); + + QList<QWebHistoryItem> ret; + for (int i = 0; i < items.size(); ++i) { + QWebHistoryItemPrivate *priv = new QWebHistoryItemPrivate(items[i].get()); + ret.append(QWebHistoryItem(priv)); + } + return ret; +} + +/*! + returns true if we have an item to go back to. +*/ +bool QWebHistory::canGoBack() const +{ + return d->lst->backListCount() > 0; +} + +/*! + returns true if we have an item to go forward to. +*/ +bool QWebHistory::canGoForward() const +{ + return d->lst->forwardListCount() > 0; +} + +/*! + goes back one history item. +*/ +void QWebHistory::goBack() +{ + d->lst->goBack(); +} + +/*! + goes forward one history item. +*/ +void QWebHistory::goForward() +{ + d->lst->goBack(); +} + +/*! + goes to item \a item in the history. +*/ +void QWebHistory::goToItem(const QWebHistoryItem &item) +{ + d->lst->goToItem(item.d->item); +} + +/*! + returns the item before the current item. +*/ +QWebHistoryItem QWebHistory::backItem() const +{ + WebCore::HistoryItem *i = d->lst->backItem(); + QWebHistoryItemPrivate *priv = new QWebHistoryItemPrivate(i); + return QWebHistoryItem(priv); +} + +/*! + returns the current item. +*/ +QWebHistoryItem QWebHistory::currentItem() const +{ + WebCore::HistoryItem *i = d->lst->currentItem(); + QWebHistoryItemPrivate *priv = new QWebHistoryItemPrivate(i); + return QWebHistoryItem(priv); +} + +/*! + returns the item after the current item. +*/ +QWebHistoryItem QWebHistory::forwardItem() const +{ + WebCore::HistoryItem *i = d->lst->forwardItem(); + QWebHistoryItemPrivate *priv = new QWebHistoryItemPrivate(i); + return QWebHistoryItem(priv); +} + +/*! + returns the item at index \a i. +*/ +QWebHistoryItem QWebHistory::itemAtIndex(int i) const +{ + WebCore::HistoryItem *item = d->lst->itemAtIndex(i); + + QWebHistoryItemPrivate *priv = new QWebHistoryItemPrivate(item); + return QWebHistoryItem(priv); +} + diff --git a/WebKit/qt/Api/qwebhistory.h b/WebKit/qt/Api/qwebhistory.h new file mode 100644 index 0000000..6c8a4f4 --- /dev/null +++ b/WebKit/qt/Api/qwebhistory.h @@ -0,0 +1,92 @@ +/* + Copyright (C) 2007 Trolltech ASA + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. + + This class provides all functionality needed for loading images, style sheets and html + pages from the web. It has a memory cache for these objects. +*/ +#ifndef QWEBHISTORY_H +#define QWEBHISTORY_H + +#include <QtCore/qurl.h> +#include <QtCore/qstring.h> +#include <QtGui/qicon.h> +#include <QtCore/qdatetime.h> +#include <QtCore/qshareddata.h> + +#include "qwebkitglobal.h" + +class QWebPage; + +class QWebHistoryItemPrivate; +class QWEBKIT_EXPORT QWebHistoryItem +{ +public: + QWebHistoryItem(const QWebHistoryItem &other); + QWebHistoryItem &operator=(const QWebHistoryItem &other); + ~QWebHistoryItem(); + + QUrl originalUrl() const; + QUrl currentUrl() const; + + QString title() const; + QDateTime lastVisited() const; + + QPixmap icon() const; + +private: + QWebHistoryItem(QWebHistoryItemPrivate *priv); + friend class QWebHistory; + friend class QWebPage; + QExplicitlySharedDataPointer<QWebHistoryItemPrivate> d; +}; + +class QWebHistoryPrivate; +class QWEBKIT_EXPORT QWebHistory +{ +public: + void clear(); + + QList<QWebHistoryItem> items() const; + QList<QWebHistoryItem> backItems(int maxItems) const; + QList<QWebHistoryItem> forwardItems(int maxItems) const; + + bool canGoBack() const; + bool canGoForward() const; + + void goBack(); + void goForward(); + void goToItem(const QWebHistoryItem &item); + + QWebHistoryItem backItem() const; + QWebHistoryItem currentItem() const; + QWebHistoryItem forwardItem() const; + QWebHistoryItem itemAtIndex(int i) const; + +private: + QWebHistory(); + ~QWebHistory(); + + friend class QWebPage; + friend class QWebPagePrivate; + + Q_DISABLE_COPY(QWebHistory) + + QWebHistoryPrivate *d; +}; + +#endif diff --git a/WebKit/qt/Api/qwebhistory_p.h b/WebKit/qt/Api/qwebhistory_p.h new file mode 100644 index 0000000..5b56667 --- /dev/null +++ b/WebKit/qt/Api/qwebhistory_p.h @@ -0,0 +1,39 @@ +#ifndef QWEBHISTORY_P_H +#define QWEBHISTORY_P_H + +#include "BackForwardList.h" +#include "HistoryItem.h" + +class QWebHistoryItemPrivate : public QSharedData +{ +public: + QWebHistoryItemPrivate(WebCore::HistoryItem *i) + { + i->ref(); + item = i; + } + ~QWebHistoryItemPrivate() + { + item->deref(); + } + + WebCore::HistoryItem *item; +}; + +class QWebHistoryPrivate : public QSharedData +{ +public: + QWebHistoryPrivate(WebCore::BackForwardList *l) + { + l->ref(); + lst = l; + } + ~QWebHistoryPrivate() + { + lst->deref(); + } + WebCore::BackForwardList *lst; +}; + + +#endif diff --git a/WebKit/qt/Api/qwebhistoryinterface.cpp b/WebKit/qt/Api/qwebhistoryinterface.cpp new file mode 100644 index 0000000..8890350 --- /dev/null +++ b/WebKit/qt/Api/qwebhistoryinterface.cpp @@ -0,0 +1,110 @@ +/* + Copyright (C) 2007 Staikos Computing Services Inc. <info@staikos.net> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. + + This class provides all functionality needed for tracking global history. +*/ + +#include "qwebhistoryinterface.h" + +#include <QCoreApplication> + +#include "PlatformString.h" +#include <wtf/Platform.h> + +// FIXME: It's not correct to just implement a WebCore function in WebKit! +// This needs to be fixed to match other platforms. + +namespace WebCore { + +bool historyContains(const UChar* characters, unsigned length) +{ + if (!QWebHistoryInterface::defaultInterface()) + return false; + + return QWebHistoryInterface::defaultInterface()->historyContains(QString(reinterpret_cast<const QChar*>(characters), length)); +} + +} // namespace WebCore + +static QWebHistoryInterface *default_interface; + +static bool gRoutineAdded; + +static void gCleanupInterface() +{ + delete default_interface; + default_interface = 0; +} + +/*! + Sets a new default interface that will be used by all of WebKit + for managing history. +*/ +void QWebHistoryInterface::setDefaultInterface(QWebHistoryInterface *defaultInterface) +{ + if (default_interface == defaultInterface) + return; + if (default_interface) + delete default_interface; + default_interface = defaultInterface; + if (!gRoutineAdded) { + qAddPostRoutine(gCleanupInterface); + gRoutineAdded = true; + } +} + +/*! + Returns the default interface that will be used by WebKit. If no + default interface has been set, QtWebkit will not track history. +*/ +QWebHistoryInterface *QWebHistoryInterface::defaultInterface() +{ + return default_interface; +} + +/*! + \class QWebHistoryInterface + \since 4.4 + \brief The QWebHistoryInterface class provides an interface to implement link history. + + The QWebHistoryInterface is an interface that can be used to + implement link history. It contains two pure virtual methods that + are called by the WebKit engine. addHistoryEntry() is used to add + pages that have been visited to the interface, while + historyContains() is used to query whether this page has been + visited by the user. +*/ +QWebHistoryInterface::QWebHistoryInterface(QObject *parent) : QObject(parent) +{ +} + +QWebHistoryInterface::~QWebHistoryInterface() +{ +} + +/*! + \fn bool QWebHistoryInterface::historyContains(const QString &url) const + + Called by the WebKit engine to query whether a certain url has been visited by the user already. +*/ + +/*! + \fn void QWebHistoryInterface::addHistoryEntry(const QString &url) const + + Called by WebKit to add another url to the list of visited pages. +*/ diff --git a/WebKit/qt/Api/qwebhistoryinterface.h b/WebKit/qt/Api/qwebhistoryinterface.h new file mode 100644 index 0000000..87dc88c --- /dev/null +++ b/WebKit/qt/Api/qwebhistoryinterface.h @@ -0,0 +1,43 @@ +/* + Copyright (C) 2007 Staikos Computing Services, Inc. <info@staikos.net> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. + + This class provides all functionality needed for tracking global history. +*/ + +#ifndef QWEBHISTORYINTERFACE_H +#define QWEBHISTORYINTERFACE_H + +#include <QtCore/qobject.h> + +#include "qwebkitglobal.h" + +class QWEBKIT_EXPORT QWebHistoryInterface : public QObject +{ + Q_OBJECT +public: + QWebHistoryInterface(QObject *parent = 0); + ~QWebHistoryInterface(); + + static void setDefaultInterface(QWebHistoryInterface *defaultInterface); + static QWebHistoryInterface *defaultInterface(); + + virtual bool historyContains(const QString &url) const = 0; + virtual void addHistoryEntry(const QString &url) = 0; +}; + +#endif diff --git a/WebKit/qt/Api/qwebkitglobal.h b/WebKit/qt/Api/qwebkitglobal.h new file mode 100644 index 0000000..25fe0f9 --- /dev/null +++ b/WebKit/qt/Api/qwebkitglobal.h @@ -0,0 +1,39 @@ +/* + Copyright (C) 2007 Trolltech ASA + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. + + This class provides all functionality needed for loading images, style sheets and html + pages from the web. It has a memory cache for these objects. +*/ +#ifndef QWEBKITGLOBAL_H +#define QWEBKITGLOBAL_H + +#include <qglobal.h> + +#if defined(Q_OS_WIN) +# if defined(BUILD_WEBKIT) +# define QWEBKIT_EXPORT Q_DECL_EXPORT +# else +# define QWEBKIT_EXPORT Q_DECL_IMPORT +# endif +#endif + +#if !defined(QWEBKIT_EXPORT) +#define QWEBKIT_EXPORT Q_DECL_EXPORT +#endif + +#endif // QWEBKITGLOBAL_H diff --git a/WebKit/qt/Api/qwebnetworkinterface.cpp b/WebKit/qt/Api/qwebnetworkinterface.cpp new file mode 100644 index 0000000..fd0c694 --- /dev/null +++ b/WebKit/qt/Api/qwebnetworkinterface.cpp @@ -0,0 +1,1265 @@ +/* + Copyright (C) 2006 Enrico Ros <enrico.ros@m31engineering.it> + Copyright (C) 2007 Trolltech ASA + Copyright (C) 2007 Staikos Computing Services Inc. <info@staikos.net> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. + + This class provides all functionality needed for loading images, style sheets and html + pages from the web. It has a memory cache for these objects. +*/ +#include <qglobal.h> +#if QT_VERSION < 0x040400 +#include "qwebframe.h" +#include "qwebnetworkinterface.h" +#include "qwebnetworkinterface_p.h" +#include "qwebobjectpluginconnector.h" +#include "qwebpage.h" +#include "qcookiejar.h" +#include <qdebug.h> +#include <qfile.h> +#include <qnetworkproxy.h> +#include <qurl.h> +#include <QAuthenticator> +#include <QCoreApplication> +#include <QSslError> + +#include "ResourceHandle.h" +#include "ResourceHandleClient.h" +#include "ResourceHandleInternal.h" +#include "MIMETypeRegistry.h" +#include "CookieJar.h" + +#if 0 +#define DEBUG qDebug +#else +#define DEBUG if (1) {} else qDebug +#endif + +static QWebNetworkInterface *s_default_interface = 0; +static QWebNetworkManager *s_manager = 0; + +using namespace WebCore; + +uint qHash(const HostInfo &info) +{ + return qHash(info.host) + info.port; +} + +static bool operator==(const HostInfo &i1, const HostInfo &i2) +{ + return i1.port == i2.port && i1.host == i2.host; +} + +enum ParserState { + State_Begin, + State_FirstChar, + State_SecondChar +}; + +/* + * Decode URLs without doing any charset conversion. + * + * Most simple approach to do it without any lookahead. + */ +static QByteArray decodePercentEncoding(const QByteArray& input) +{ + int actualLength = 0; + QByteArray tmpVal; + QByteArray output; + ParserState state = State_Begin; + + output.resize(input.length()); + tmpVal.resize(2); + + for (int i = 0; i < input.length(); ++i) + if (state == State_Begin) { + if (input.at(i) == '%') { + state = State_FirstChar; + } else { + output[actualLength++] = input[i]; + } + } else if (state == State_FirstChar) { + state = State_SecondChar; + tmpVal[0] = input[i]; + } else if (state == State_SecondChar) { + state = State_Begin; + tmpVal[1] = input[i]; + output[actualLength++] = tmpVal.toShort(0, 16); + } + + output.resize(actualLength); + return output; +} + +void QWebNetworkRequestPrivate::init(const WebCore::ResourceRequest &resourceRequest) +{ + KURL url = resourceRequest.url(); + QUrl qurl = QString(url.string()); + init(resourceRequest.httpMethod(), qurl, &resourceRequest); +} + +void QWebNetworkRequestPrivate::init(const QString &method, const QUrl &url, const WebCore::ResourceRequest *resourceRequest) +{ + httpHeader = QHttpRequestHeader(method, url.toString(QUrl::RemoveScheme|QUrl::RemoveAuthority)); + httpHeader.setValue(QLatin1String("Connection"), QLatin1String("Keep-Alive")); + setURL(url); + + if (resourceRequest) { + httpHeader.setValue(QLatin1String("User-Agent"), resourceRequest->httpUserAgent()); + const QString scheme = url.scheme().toLower(); + if (scheme == QLatin1String("http") || scheme == QLatin1String("https")) { + QString cookies = QCookieJar::cookieJar()->cookies(resourceRequest->url()); + if (!cookies.isEmpty()) + httpHeader.setValue(QLatin1String("Cookie"), cookies); + } + + + const HTTPHeaderMap& loaderHeaders = resourceRequest->httpHeaderFields(); + HTTPHeaderMap::const_iterator end = loaderHeaders.end(); + for (HTTPHeaderMap::const_iterator it = loaderHeaders.begin(); it != end; ++it) + httpHeader.setValue(it->first, it->second); + + // handle and perform a 'POST' request + if (method == "POST") { + Vector<char> data; + resourceRequest->httpBody()->flatten(data); + postData = QByteArray(data.data(), data.size()); + httpHeader.setValue(QLatin1String("content-length"), QString::number(postData.size())); + } + } +} + +void QWebNetworkRequestPrivate::setURL(const QUrl &u) +{ + url = u; + int port = url.port(); + const QString scheme = u.scheme(); + if (port > 0 && (port != 80 || scheme != "http") && (port != 443 || scheme != "https")) + httpHeader.setValue(QLatin1String("Host"), url.host() + QLatin1Char(':') + QString::number(port)); + else + httpHeader.setValue(QLatin1String("Host"), url.host()); +} + +/*! + \class QWebNetworkRequest + + The QWebNetworkRequest class represents a request for data from the network with all the + necessary information needed for retrieval. This includes the url, extra HTTP header fields + as well as data for a HTTP POST request. +*/ + +QWebNetworkRequest::QWebNetworkRequest() + : d(new QWebNetworkRequestPrivate) +{ +} + +QWebNetworkRequest::QWebNetworkRequest(const QUrl &url, Method method, const QByteArray &postData) + : d(new QWebNetworkRequestPrivate) +{ + d->init(method == Get ? "GET" : "POST", url); + d->postData = postData; +} + +QWebNetworkRequest::QWebNetworkRequest(const QWebNetworkRequest &other) + : d(new QWebNetworkRequestPrivate(*other.d)) +{ +} + +QWebNetworkRequest &QWebNetworkRequest::operator=(const QWebNetworkRequest &other) +{ + *d = *other.d; + return *this; +} + +/*! + \internal +*/ +QWebNetworkRequest::QWebNetworkRequest(const QWebNetworkRequestPrivate &priv) + : d(new QWebNetworkRequestPrivate(priv)) +{ +} + +/*! + \internal +*/ +QWebNetworkRequest::QWebNetworkRequest(const WebCore::ResourceRequest &request) + : d(new QWebNetworkRequestPrivate) +{ + d->init(request); +} + +QWebNetworkRequest::~QWebNetworkRequest() +{ + delete d; +} + +/*! + The requested URL +*/ +QUrl QWebNetworkRequest::url() const +{ + return d->url; +} + +/*! + Sets the URL to request. + + Note that setting the URL also sets the "Host" field in the HTTP header. +*/ +void QWebNetworkRequest::setUrl(const QUrl &url) +{ + d->setURL(url); +} + +/*! + The http request header information. +*/ +QHttpRequestHeader QWebNetworkRequest::httpHeader() const +{ + return d->httpHeader; +} + +void QWebNetworkRequest::setHttpHeader(const QHttpRequestHeader &header) const +{ + d->httpHeader = header; +} + +QString QWebNetworkRequest::httpHeaderField(const QString &key) const +{ + return d->httpHeader.value(key); +} + +void QWebNetworkRequest::setHttpHeaderField(const QString &key, const QString &value) +{ + d->httpHeader.setValue(key, value); +} + +/*! + Post data sent with HTTP POST requests. +*/ +QByteArray QWebNetworkRequest::postData() const +{ + return d->postData; +} + +void QWebNetworkRequest::setPostData(const QByteArray &data) +{ + d->postData = data; +} + +/*! + \class QWebNetworkJob + + The QWebNetworkJob class represents a network job, that needs to be + processed by the QWebNetworkInterface. + + This class is only required when implementing a new network layer (or + support for a special protocol) using QWebNetworkInterface. + + QWebNetworkJob objects are created and owned by the QtWebKit library. + Most of it's properties are read-only. + + The job is reference counted. This can be used to ensure that the job doesn't + get deleted while it's still stored in some data structure. +*/ + +/*! + \internal +*/ +QWebNetworkJob::QWebNetworkJob() + : d(new QWebNetworkJobPrivate) +{ +} + +/*! + \internal +*/ +QWebNetworkJob::~QWebNetworkJob() +{ + delete d; + d = 0; +} + +/*! + The requested URL +*/ +QUrl QWebNetworkJob::url() const +{ + return d->request.url; +} + +/*! + Post data associated with the job +*/ +QByteArray QWebNetworkJob::postData() const +{ + return d->request.postData; +} + +/*! + The HTTP request header that should be used to download the job. +*/ +QHttpRequestHeader QWebNetworkJob::httpHeader() const +{ + return d->request.httpHeader; +} + +/*! + The complete network request that should be used to download the job. +*/ +QWebNetworkRequest QWebNetworkJob::request() const +{ + return QWebNetworkRequest(d->request); +} + +/*! + The HTTP response header received from the network. +*/ +QHttpResponseHeader QWebNetworkJob::response() const +{ + return d->response; +} + +/*! + The last error of the Job. +*/ +QString QWebNetworkJob::errorString() const +{ + return d->errorString; +} + +/*! + Sets the HTTP reponse header. The response header has to be called before + emitting QWebNetworkInterface::started. +*/ +void QWebNetworkJob::setResponse(const QHttpResponseHeader &response) +{ + d->response = response; +} + +void QWebNetworkJob::setErrorString(const QString& errorString) +{ + d->errorString = errorString; +} + +/*! + returns true if the job has been cancelled by the WebKit framework +*/ +bool QWebNetworkJob::cancelled() const +{ + return !d->resourceHandle && !d->connector; +} + +/*! + reference the job. +*/ +void QWebNetworkJob::ref() +{ + ++d->ref; +} + +/*! + derefence the job. + + If the reference count drops to 0 this method also deletes the job. + + Returns false if the reference count has dropped to 0. +*/ +bool QWebNetworkJob::deref() +{ + if (!--d->ref) { + delete this; + return false; + } + return true; +} + +/*! + Returns the network interface that is associated with this job. +*/ +QWebNetworkInterface *QWebNetworkJob::networkInterface() const +{ + return d->interface; +} + +/*! + Returns the network interface that is associated with this job. +*/ +QWebFrame *QWebNetworkJob::frame() const +{ + if (d->resourceHandle) { + ResourceHandleInternal *rhi = d->resourceHandle->getInternal(); + if (rhi) { + return rhi->m_frame; + } + } + return 0; +} + +QWebNetworkJob::JobStatus QWebNetworkJob::status() const +{ + return d->jobStatus; +} + +void QWebNetworkJob::setStatus(const JobStatus& status) +{ + d->jobStatus = status; +} + +/*! + \class QWebNetworkManager + \internal +*/ +QWebNetworkManager::QWebNetworkManager() + : QObject(0) + , m_scheduledWork(false) +{ + connect(this, SIGNAL(scheduleWork()), SLOT(doWork()), Qt::QueuedConnection); +} + +QWebNetworkManager *QWebNetworkManager::self() +{ + // ensure everything's constructed and connected + QWebNetworkInterface::defaultInterface(); + + return s_manager; +} + +bool QWebNetworkManager::add(ResourceHandle *handle, QWebNetworkInterface *interface, JobMode jobMode) +{ + if (!interface) + interface = s_default_interface; + + ASSERT(interface); + + QWebNetworkJob *job = new QWebNetworkJob(); + handle->getInternal()->m_job = job; + job->d->resourceHandle = handle; + job->d->interface = interface; + job->d->connector = 0; + + job->d->request.init(handle->request()); + + const QString method = handle->getInternal()->m_request.httpMethod(); + if (method != "POST" && method != "GET" && method != "HEAD") { + qWarning("REQUEST: [%s]\n", qPrintable(job->d->request.httpHeader.toString())); + return false; + } + + DEBUG() << "QWebNetworkManager::add:" << job->d->request.httpHeader.toString(); + + if (jobMode == SynchronousJob) { + Q_ASSERT(!m_synchronousJobs.contains(job)); + m_synchronousJobs[job] = 1; + } + + interface->addJob(job); + + return true; +} + +void QWebNetworkManager::cancel(ResourceHandle *handle) +{ + QWebNetworkJob *job = handle->getInternal()->m_job; + if (!job) + return; + DEBUG() << "QWebNetworkManager::cancel:" << job->d->request.httpHeader.toString(); + job->d->resourceHandle = 0; + job->d->connector = 0; + job->d->interface->cancelJob(job); + handle->getInternal()->m_job = 0; +} + +void QWebNetworkManager::started(QWebNetworkJob *job) +{ + Q_ASSERT(job->d); + Q_ASSERT(job->status() == QWebNetworkJob::JobCreated || + job->status() == QWebNetworkJob::JobRecreated); + + job->setStatus(QWebNetworkJob::JobStarted); + ResourceHandleClient* client = 0; + if (job->d->resourceHandle) { + client = job->d->resourceHandle->client(); + if (!client) + return; + } else if (!job->d->connector) { + return; + } + + DEBUG() << "ResourceHandleManager::receivedResponse:"; + DEBUG() << job->d->response.toString(); + + QStringList cookies = job->d->response.allValues("Set-Cookie"); + KURL url(job->url()); + foreach (QString c, cookies) { + QCookieJar::cookieJar()->setCookies(url, url, c); + } + QString contentType = job->d->response.value("Content-Type"); + QString encoding; + int idx = contentType.indexOf(QLatin1Char(';')); + if (idx > 0) { + QString remainder = contentType.mid(idx + 1).toLower(); + contentType = contentType.left(idx).trimmed(); + + idx = remainder.indexOf("charset"); + if (idx >= 0) { + idx = remainder.indexOf(QLatin1Char('='), idx); + if (idx >= 0) + encoding = remainder.mid(idx + 1).trimmed(); + } + } + if (contentType.isEmpty()) { + // let's try to guess from the extension + QString extension = job->d->request.url.path(); + int index = extension.lastIndexOf(QLatin1Char('.')); + if (index > 0) { + extension = extension.mid(index + 1); + contentType = MIMETypeRegistry::getMIMETypeForExtension(extension); + } + } +// qDebug() << "Content-Type=" << contentType; +// qDebug() << "Encoding=" << encoding; + + + ResourceResponse response(url, contentType, + 0 /* FIXME */, + encoding, + String() /* FIXME */); + + int statusCode = job->d->response.statusCode(); + if (job->url().scheme() != QLatin1String("file")) + response.setHTTPStatusCode(statusCode); + else if (statusCode == 404) + response.setHTTPStatusCode(statusCode); + + /* Fill in the other fields */ + + if (statusCode >= 300 && statusCode < 400) { + // we're on a redirect page! if the 'Location:' field is valid, we redirect + QString location = job->d->response.value("location"); + DEBUG() << "Redirection"; + if (!location.isEmpty()) { + QUrl newUrl = job->d->request.url.resolved(location); + if (job->d->resourceHandle) { + ResourceRequest newRequest = job->d->resourceHandle->request(); + newRequest.setURL(KURL(newUrl)); + if (client) + client->willSendRequest(job->d->resourceHandle, newRequest, response); + } + + job->d->request.httpHeader.setRequest(job->d->request.httpHeader.method(), + newUrl.toString(QUrl::RemoveScheme|QUrl::RemoveAuthority)); + job->d->request.setURL(newUrl); + job->d->redirected = true; + return; + } + } + + if (client) + client->didReceiveResponse(job->d->resourceHandle, response); + if (job->d->connector) + emit job->d->connector->started(job); + +} + +void QWebNetworkManager::data(QWebNetworkJob *job, const QByteArray &data) +{ + Q_ASSERT(job->status() == QWebNetworkJob::JobStarted || + job->status() == QWebNetworkJob::JobReceivingData); + + job->setStatus(QWebNetworkJob::JobReceivingData); + ResourceHandleClient* client = 0; + if (job->d->resourceHandle) { + client = job->d->resourceHandle->client(); + if (!client) + return; + } else if (!job->d->connector) { + return; + } + + if (job->d->redirected) + return; // don't emit the "Document has moved here" type of HTML + + DEBUG() << "receivedData" << job->d->request.url.path(); + if (client) + client->didReceiveData(job->d->resourceHandle, data.constData(), data.length(), data.length() /*FixMe*/); + if (job->d->connector) + emit job->d->connector->data(job, data); + +} + +void QWebNetworkManager::finished(QWebNetworkJob *job, int errorCode) +{ + Q_ASSERT(errorCode == 1 || + job->status() == QWebNetworkJob::JobStarted || + job->status() == QWebNetworkJob::JobReceivingData); + + if (m_synchronousJobs.contains(job)) + m_synchronousJobs.remove(job); + + job->setStatus(QWebNetworkJob::JobFinished); + ResourceHandleClient* client = 0; + if (job->d->resourceHandle) { + client = job->d->resourceHandle->client(); + if (!client) + return; + } else if (!job->d->connector) { + job->deref(); + return; + } + + DEBUG() << "receivedFinished" << errorCode << job->url(); + + if (job->d->redirected) { + job->d->redirected = false; + job->setStatus(QWebNetworkJob::JobRecreated); + job->d->interface->addJob(job); + return; + } + + if (job->d->resourceHandle) + job->d->resourceHandle->getInternal()->m_job = 0; + + if (client) { + if (errorCode) { + //FIXME: error setting error was removed from ResourceHandle + client->didFail(job->d->resourceHandle, + ResourceError(job->d->request.url.host(), job->d->response.statusCode(), + job->d->request.url.toString(), job->d->errorString)); + } else { + client->didFinishLoading(job->d->resourceHandle); + } + } + + if (job->d->connector) + emit job->d->connector->finished(job, errorCode); + + DEBUG() << "receivedFinished done" << job->d->request.url; + + job->deref(); +} + +void QWebNetworkManager::addHttpJob(QWebNetworkJob *job) +{ + HostInfo hostInfo(job->url()); + WebCoreHttp *httpConnection = m_hostMapping.value(hostInfo); + if (!httpConnection) { + // #### fix custom ports + DEBUG() << " new connection to" << hostInfo.host << hostInfo.port; + httpConnection = new WebCoreHttp(this, hostInfo); + QObject::connect(httpConnection, SIGNAL(connectionClosed(const WebCore::HostInfo&)), + this, SLOT(httpConnectionClosed(const WebCore::HostInfo&))); + + m_hostMapping[hostInfo] = httpConnection; + } + httpConnection->request(job); +} + +void QWebNetworkManager::cancelHttpJob(QWebNetworkJob *job) +{ + WebCoreHttp *httpConnection = m_hostMapping.value(job->url()); + if (httpConnection) + httpConnection->cancel(job); +} + +void QWebNetworkManager::httpConnectionClosed(const WebCore::HostInfo &info) +{ + WebCoreHttp *connection = m_hostMapping.take(info); + connection->deleteLater(); +} + +void QWebNetworkInterfacePrivate::sendFileData(QWebNetworkJob* job, int statusCode, const QByteArray &data) +{ + int error = statusCode >= 400 ? 1 : 0; + if (!job->cancelled()) { + QHttpResponseHeader response; + response.setStatusLine(statusCode); + response.setContentLength(data.length()); + job->setResponse(response); + q->started(job); + if (!data.isEmpty()) + q->data(job, data); + } + q->finished(job, error); +} + +void QWebNetworkInterfacePrivate::parseDataUrl(QWebNetworkJob* job) +{ + QByteArray data = job->url().toString().toLatin1(); + //qDebug() << "handling data url:" << data; + + ASSERT(data.startsWith("data:")); + + // Here's the syntax of data URLs: + // dataurl := "data:" [ mediatype ] [ ";base64" ] "," data + // mediatype := [ type "/" subtype ] *( ";" parameter ) + // data := *urlchar + // parameter := attribute "=" value + QByteArray header; + bool base64 = false; + + int index = data.indexOf(','); + if (index != -1) { + header = data.mid(5, index - 5).toLower(); + //qDebug() << "header=" << header; + data = data.mid(index+1); + //qDebug() << "data=" << data; + + if (header.endsWith(";base64")) { + //qDebug() << "base64"; + base64 = true; + header = header.left(header.length() - 7); + //qDebug() << "mime=" << header; + } + } else { + data = QByteArray(); + } + + if (base64) { + data = QByteArray::fromBase64(data); + } else { + data = decodePercentEncoding(data); + } + + if (header.isEmpty()) + header = "text/plain;charset=US-ASCII"; + int statusCode = 200; + QHttpResponseHeader response; + response.setContentType(header); + response.setContentLength(data.size()); + job->setResponse(response); + + int error = statusCode >= 400 ? 1 : 0; + q->started(job); + if (!data.isEmpty()) + q->data(job, data); + q->finished(job, error); +} + +void QWebNetworkManager::queueStart(QWebNetworkJob* job) +{ + Q_ASSERT(job->d); + + QMutexLocker locker(&m_queueMutex); + job->ref(); + m_pendingWork.append(new JobWork(job)); + doScheduleWork(); +} + +void QWebNetworkManager::queueData(QWebNetworkJob* job, const QByteArray& data) +{ + ASSERT(job->d); + + QMutexLocker locker(&m_queueMutex); + job->ref(); + m_pendingWork.append(new JobWork(job, data)); + doScheduleWork(); +} + +void QWebNetworkManager::queueFinished(QWebNetworkJob* job, int errorCode) +{ + Q_ASSERT(job->d); + + QMutexLocker locker(&m_queueMutex); + job->ref(); + m_pendingWork.append(new JobWork(job, errorCode)); + doScheduleWork(); +} + +void QWebNetworkManager::doScheduleWork() +{ + if (!m_scheduledWork) { + m_scheduledWork = true; + emit scheduleWork(); + } +} + + +/* + * We will work on a copy of m_pendingWork. While dispatching m_pendingWork + * new work will be added that will be handled at a later doWork call. doWork + * will be called we set m_scheduledWork to false early in this method. + */ +void QWebNetworkManager::doWork() +{ + m_queueMutex.lock(); + m_scheduledWork = false; + bool hasSyncJobs = m_synchronousJobs.size(); + const QHash<QWebNetworkJob*, int> syncJobs = m_synchronousJobs; + m_queueMutex.unlock(); + + foreach (JobWork* work, m_pendingWork) { + if (hasSyncJobs && !syncJobs.contains(work->job)) + continue; + + if (work->workType == JobWork::JobStarted) + started(work->job); + else if (work->workType == JobWork::JobData) { + // This job was not yet started + if (static_cast<int>(work->job->status()) < QWebNetworkJob::JobStarted) + continue; + + data(work->job, work->data); + } else if (work->workType == JobWork::JobFinished) { + // This job was not yet started... we have no idea if data comes by... + // and it won't start in case of errors + if (static_cast<int>(work->job->status()) < QWebNetworkJob::JobStarted && work->errorCode != 1) + continue; + + finished(work->job, work->errorCode); + } + + m_queueMutex.lock(); + m_pendingWork.removeAll(work); + m_queueMutex.unlock(); + + work->job->deref(); + delete work; + } + + m_queueMutex.lock(); + if (hasSyncJobs && m_synchronousJobs.size() == 0) + doScheduleWork(); + m_queueMutex.unlock(); +} + +/*! + \class QWebNetworkInterface + + The QWebNetworkInterface class provides an abstraction layer for + WebKit's network interface. It allows to completely replace or + extend the builtin network layer. + + QWebNetworkInterface contains two virtual methods, addJob and + cancelJob that have to be reimplemented when implementing your own + networking layer. + + QWebNetworkInterface can by default handle the http, https, file and + data URI protocols. + +*/ + +static bool gRoutineAdded = false; + +static void gCleanupInterface() +{ + delete s_default_interface; + s_default_interface = 0; +} + +/*! + Sets a new default interface that will be used by all of WebKit + for downloading data from the internet. +*/ +void QWebNetworkInterface::setDefaultInterface(QWebNetworkInterface *defaultInterface) +{ + if (s_default_interface == defaultInterface) + return; + if (s_default_interface) + delete s_default_interface; + s_default_interface = defaultInterface; + if (!gRoutineAdded) { + qAddPostRoutine(gCleanupInterface); + gRoutineAdded = true; + } +} + +/*! + Returns the default interface that will be used by WebKit. If no + default interface has been set, QtWebkit will create an instance of + QWebNetworkInterface to do the work. +*/ +QWebNetworkInterface *QWebNetworkInterface::defaultInterface() +{ + if (!s_default_interface) { + setDefaultInterface(new QWebNetworkInterface); + } + return s_default_interface; +} + + +/*! + Constructs a QWebNetworkInterface object. +*/ +QWebNetworkInterface::QWebNetworkInterface(QObject *parent) + : QObject(parent) +{ + d = new QWebNetworkInterfacePrivate; + d->q = this; + + if (!s_manager) + s_manager = new QWebNetworkManager; +} + +/*! + Destructs the QWebNetworkInterface object. +*/ +QWebNetworkInterface::~QWebNetworkInterface() +{ + delete d; +} + +/*! + This virtual method gets called whenever QtWebkit needs to add a + new job to download. + + The QWebNetworkInterface should process this job, by first emitting + the started signal, then emitting data repeatedly as new data for + the Job is available, and finally ending the job with emitting a + finished signal. + + After the finished signal has been emitted, the QWebNetworkInterface + is not allowed to access the job anymore. +*/ +void QWebNetworkInterface::addJob(QWebNetworkJob *job) +{ + QString protocol = job->url().scheme(); + if (protocol == QLatin1String("http") || protocol == QLatin1String("https")) { + QWebNetworkManager::self()->addHttpJob(job); + return; + } + + // "file", "data" and all unhandled stuff go through here + //DEBUG() << "fileRequest"; + DEBUG() << "FileLoader::request" << job->url(); + + if (job->cancelled()) { + d->sendFileData(job, 400, QByteArray()); + return; + } + + QUrl url = job->url(); + if (protocol == QLatin1String("data")) { + d->parseDataUrl(job); + return; + } + + int statusCode = 200; + QByteArray data; + QString path = url.path(); + if (protocol == QLatin1String("qrc")) { + protocol = "file"; + path.prepend(QLatin1Char(':')); + } + + if (!(protocol.isEmpty() || protocol == QLatin1String("file"))) { + statusCode = 404; + } else { + // we simply ignore post data here. + QFile f(path); + DEBUG() << "opening" << QString(url.path()); + + if (f.open(QIODevice::ReadOnly)) { + QHttpResponseHeader response; + response.setStatusLine(200); + job->setResponse(response); + data = f.readAll(); + } else { + statusCode = 404; + } + } + + if (statusCode == 404) { + QHttpResponseHeader response; + response.setStatusLine(404); + job->setResponse(response); + } + + d->sendFileData(job, statusCode, data); +} + +/*! + This virtual method gets called whenever QtWebkit needs to cancel a + new job. + + The QWebNetworkInterface acknowledge the canceling of the job, by + emitting the finished signal with an error code of 1. After emitting + the finished signal, the interface should not access the job + anymore. +*/ +void QWebNetworkInterface::cancelJob(QWebNetworkJob *job) +{ + QString protocol = job->url().scheme(); + if (protocol == QLatin1String("http") || protocol == QLatin1String("https")) + QWebNetworkManager::self()->cancelHttpJob(job); +} + +void QWebNetworkInterface::started(QWebNetworkJob* job) +{ + Q_ASSERT(s_manager); + s_manager->queueStart(job); +} + +void QWebNetworkInterface::data(QWebNetworkJob* job, const QByteArray& data) +{ + Q_ASSERT(s_manager); + s_manager->queueData(job, data); +} + +void QWebNetworkInterface::finished(QWebNetworkJob* job, int errorCode) +{ + Q_ASSERT(s_manager); + s_manager->queueFinished(job, errorCode); +} + +///////////////////////////////////////////////////////////////////////////// +WebCoreHttp::WebCoreHttp(QObject* parent, const HostInfo &hi) + : QObject(parent), info(hi), + m_inCancel(false) +{ + for (int i = 0; i < 2; ++i) { + connection[i].http = new QHttp(info.host, (hi.protocol == QLatin1String("https")) ? QHttp::ConnectionModeHttps : QHttp::ConnectionModeHttp, info.port); + connect(connection[i].http, SIGNAL(responseHeaderReceived(const QHttpResponseHeader&)), + this, SLOT(onResponseHeaderReceived(const QHttpResponseHeader&))); + connect(connection[i].http, SIGNAL(readyRead(const QHttpResponseHeader&)), + this, SLOT(onReadyRead())); + connect(connection[i].http, SIGNAL(requestFinished(int, bool)), + this, SLOT(onRequestFinished(int, bool))); + connect(connection[i].http, SIGNAL(done(bool)), + this, SLOT(onDone(bool))); + connect(connection[i].http, SIGNAL(stateChanged(int)), + this, SLOT(onStateChanged(int))); + connect(connection[i].http, SIGNAL(authenticationRequired(const QString&, quint16, QAuthenticator*)), + this, SLOT(onAuthenticationRequired(const QString&, quint16, QAuthenticator*))); + connect(connection[i].http, SIGNAL(proxyAuthenticationRequired(const QNetworkProxy&, QAuthenticator*)), + this, SLOT(onProxyAuthenticationRequired(const QNetworkProxy&, QAuthenticator*))); + connect(connection[i].http, SIGNAL(sslErrors(const QList<QSslError>&)), + this, SLOT(onSslErrors(const QList<QSslError>&))); + } +} + +WebCoreHttp::~WebCoreHttp() +{ + connection[0].http->deleteLater(); + connection[1].http->deleteLater(); +} + +void WebCoreHttp::request(QWebNetworkJob *job) +{ + m_pendingRequests.append(job); + scheduleNextRequest(); +} + +void WebCoreHttp::scheduleNextRequest() +{ + int c = 0; + for (; c < 2; ++c) { + if (!connection[c].current) + break; + } + if (c >= 2) + return; + + QWebNetworkJob *job = 0; + while (!job && !m_pendingRequests.isEmpty()) { + job = m_pendingRequests.takeFirst(); + if (job->cancelled()) { + job->networkInterface()->finished(job, 1); + job = 0; + } + } + if (!job) + return; + + QHttp *http = connection[c].http; + + connection[c].current = job; + connection[c].id = -1; +#ifndef QT_NO_NETWORKPROXY + int proxyId = http->setProxy(job->frame()->page()->networkProxy()); +#endif + + QByteArray postData = job->postData(); + if (!postData.isEmpty()) + connection[c].id = http->request(job->httpHeader(), postData); + else + connection[c].id = http->request(job->httpHeader()); + + DEBUG() << "WebCoreHttp::scheduleNextRequest: using connection" << c; + DEBUG() << job->httpHeader().toString(); +// DEBUG() << job->request.toString(); +} + +int WebCoreHttp::getConnection() +{ + QObject *o = sender(); + int c; + if (o == connection[0].http) { + c = 0; + } else { + Q_ASSERT(o == connection[1].http); + c = 1; + } + Q_ASSERT(connection[c].current); + return c; +} + +void WebCoreHttp::onResponseHeaderReceived(const QHttpResponseHeader &resp) +{ + QHttp *http = qobject_cast<QHttp*>(sender()); + if (http->currentId() == 0) { + qDebug() << "ERROR! Invalid job id. Why?"; // foxnews.com triggers this + return; + } + int c = getConnection(); + QWebNetworkJob *job = connection[c].current; + DEBUG() << "WebCoreHttp::slotResponseHeaderReceived connection=" << c; + DEBUG() << resp.toString(); + + job->setResponse(resp); + + job->networkInterface()->started(job); +} + +void WebCoreHttp::onReadyRead() +{ + QHttp *http = qobject_cast<QHttp*>(sender()); + if (http->currentId() == 0) { + qDebug() << "ERROR! Invalid job id. Why?"; // foxnews.com triggers this + return; + } + int c = getConnection(); + QWebNetworkJob *job = connection[c].current; + Q_ASSERT(http == connection[c].http); + //DEBUG() << "WebCoreHttp::slotReadyRead connection=" << c; + + QByteArray data; + data.resize(http->bytesAvailable()); + http->read(data.data(), data.length()); + job->networkInterface()->data(job, data); +} + +void WebCoreHttp::onRequestFinished(int id, bool error) +{ + int c = getConnection(); + if (connection[c].id != id) { + return; + } + + QWebNetworkJob *job = connection[c].current; + if (!job) { + scheduleNextRequest(); + return; + } + + QHttp *http = connection[c].http; + DEBUG() << "WebCoreHttp::slotFinished connection=" << c << error << job; + if (error) { + DEBUG() << " error: " << http->errorString(); + job->setErrorString(http->errorString()); + } + + if (!error && http->bytesAvailable()) { + QByteArray data; + data.resize(http->bytesAvailable()); + http->read(data.data(), data.length()); + job->networkInterface()->data(job, data); + } + + job->networkInterface()->finished(job, error ? 1 : 0); + connection[c].current = 0; + connection[c].id = -1; + scheduleNextRequest(); +} + +void WebCoreHttp::onDone(bool error) +{ + DEBUG() << "WebCoreHttp::onDone" << error; +} + +void WebCoreHttp::onStateChanged(int state) +{ + DEBUG() << "State changed to" << state << "and connections are" << connection[0].current << connection[1].current; + if (state == QHttp::Closing || state == QHttp::Unconnected) { + if (!m_inCancel && m_pendingRequests.isEmpty() + && !connection[0].current && !connection[1].current) + emit connectionClosed(info); + } +} + +void WebCoreHttp::cancel(QWebNetworkJob* request) +{ + bool doEmit = true; + m_inCancel = true; + for (int i = 0; i < 2; ++i) { + if (request == connection[i].current) { + connection[i].http->abort(); + doEmit = false; + } + } + if (!m_pendingRequests.removeAll(request)) + doEmit = false; + m_inCancel = false; + + if (doEmit) + request->networkInterface()->finished(request, 1); + + if (m_pendingRequests.isEmpty() + && !connection[0].current && !connection[1].current) + emit connectionClosed(info); +} + +void WebCoreHttp::onSslErrors(const QList<QSslError>& errors) +{ + int c = getConnection(); + QWebNetworkJob *job = connection[c].current; + if (job) { + bool continueAnyway = false; + emit job->networkInterface()->sslErrors(job->frame(), job->url(), errors, &continueAnyway); +#ifndef QT_NO_OPENSSL + if (continueAnyway) + connection[c].http->ignoreSslErrors(); +#endif + } +} + +void WebCoreHttp::onAuthenticationRequired(const QString& hostname, quint16 port, QAuthenticator *auth) +{ + int c = getConnection(); + QWebNetworkJob *job = connection[c].current; + if (job) { + emit job->networkInterface()->authenticate(job->frame(), job->url(), hostname, port, auth); + if (auth->isNull()) + connection[c].http->abort(); + } +} + +void WebCoreHttp::onProxyAuthenticationRequired(const QNetworkProxy& proxy, QAuthenticator *auth) +{ + int c = getConnection(); + QWebNetworkJob *job = connection[c].current; + if (job) { + emit job->networkInterface()->authenticateProxy(job->frame(), job->url(), proxy, auth); + if (auth->isNull()) + connection[c].http->abort(); + } +} + +HostInfo::HostInfo(const QUrl& url) + : protocol(url.scheme()) + , host(url.host()) + , port(url.port()) +{ + if (port < 0) { + if (protocol == QLatin1String("http")) + port = 80; + else if (protocol == QLatin1String("https")) + port = 443; + } +} + +#endif diff --git a/WebKit/qt/Api/qwebnetworkinterface.h b/WebKit/qt/Api/qwebnetworkinterface.h new file mode 100644 index 0000000..fdc38d1 --- /dev/null +++ b/WebKit/qt/Api/qwebnetworkinterface.h @@ -0,0 +1,175 @@ +/* + Copyright (C) 2007 Trolltech ASA + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. + + This class provides all functionality needed for loading images, style sheets and html + pages from the web. It has a memory cache for these objects. +*/ +#ifndef QWEBNETWORKINTERFACE_H +#define QWEBNETWORKINTERFACE_H + +#include <QtCore/qobject.h> +#include <QtCore/qurl.h> +#include <QtNetwork/qhttp.h> +#include <QtCore/qbytearray.h> + +#include "qwebkitglobal.h" + +#if QT_VERSION < 0x040400 + +class QAuthenticator; +class QNetworkProxy; +class QSslError; +class QWebFrame; +class QWebNetworkJobPrivate; +class QWebNetworkInterface; +class QWebObjectPluginConnector; + +namespace WebCore { + class WebCoreHttp; + class ResourceRequest; + class FrameLoaderClientQt; +} + +struct QWebNetworkRequestPrivate; +class QWEBKIT_EXPORT QWebNetworkRequest +{ +public: + enum Method { + Get, + Post + //Head + }; + + QWebNetworkRequest(); + explicit QWebNetworkRequest(const QUrl &url, Method method = Get, const QByteArray &postData = QByteArray()); + QWebNetworkRequest(const QWebNetworkRequest &other); + + QWebNetworkRequest &operator=(const QWebNetworkRequest &other); + ~QWebNetworkRequest(); + + QUrl url() const; + void setUrl(const QUrl &url); + + QHttpRequestHeader httpHeader() const; + void setHttpHeader(const QHttpRequestHeader &header) const; + + QString httpHeaderField(const QString &key) const; + void setHttpHeaderField(const QString &key, const QString &value); + + QByteArray postData() const; + void setPostData(const QByteArray &data); + +private: + explicit QWebNetworkRequest(const QWebNetworkRequestPrivate &priv); + explicit QWebNetworkRequest(const WebCore::ResourceRequest &request); + friend class QWebNetworkJob; + friend class WebCore::FrameLoaderClientQt; + + QWebNetworkRequestPrivate *d; + friend class QWebObjectPluginConnector; +}; + +class QWEBKIT_EXPORT QWebNetworkJob +{ +public: + + QUrl url() const; + QByteArray postData() const; + QHttpRequestHeader httpHeader() const; + QWebNetworkRequest request() const; + QString errorString() const; + + QHttpResponseHeader response() const; + void setResponse(const QHttpResponseHeader &response); + void setErrorString(const QString&); + + bool cancelled() const; + + void ref(); + bool deref(); + + QWebNetworkInterface *networkInterface() const; + + QWebFrame *frame() const; + +protected: + enum JobStatus { + JobCreated, + JobRecreated, + JobStarted, + JobReceivingData, + JobFinished + }; + + JobStatus status() const; + void setStatus(const JobStatus&); + +private: + QWebNetworkJob(); + ~QWebNetworkJob(); + + friend class QWebNetworkManager; + friend class QWebObjectPluginConnector; + friend class QWebNetworkJobPrivate; + + QWebNetworkJobPrivate *d; +}; + +class QWebNetworkInterfacePrivate; + +class QWEBKIT_EXPORT QWebNetworkInterface : public QObject +{ + Q_OBJECT +public: + QWebNetworkInterface(QObject *parent = 0); + ~QWebNetworkInterface(); + + static void setDefaultInterface(QWebNetworkInterface *defaultInterface); + static QWebNetworkInterface *defaultInterface(); + + virtual void addJob(QWebNetworkJob *job); + virtual void cancelJob(QWebNetworkJob *job); + +protected: + void started(QWebNetworkJob*); + void data(QWebNetworkJob*, const QByteArray &data); + void finished(QWebNetworkJob*, int errorCode); + +signals: + /** + * Signal is emitted when an SSL error occurs. + */ + void sslErrors(QWebFrame *frame, const QUrl& url, const QList<QSslError>& errors, bool *continueAnyway); + /** + * Signal is emitted when network authentication is required. + */ + void authenticate(QWebFrame *frame, const QUrl& url, const QString& hostname, quint16 port, QAuthenticator *auth); + /** + * Signal is emitted when proxy authentication is required. + */ + void authenticateProxy(QWebFrame *frame, const QUrl& url, const QNetworkProxy& proxy, QAuthenticator *auth); + +private: + friend class QWebNetworkInterfacePrivate; + friend class WebCore::WebCoreHttp; + QWebNetworkInterfacePrivate *d; +}; + +#endif + +#endif diff --git a/WebKit/qt/Api/qwebnetworkinterface_p.h b/WebKit/qt/Api/qwebnetworkinterface_p.h new file mode 100644 index 0000000..c712ae4 --- /dev/null +++ b/WebKit/qt/Api/qwebnetworkinterface_p.h @@ -0,0 +1,223 @@ +/* + Copyright (C) 2007 Trolltech ASA + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. + + This class provides all functionality needed for loading images, style sheets and html + pages from the web. It has a memory cache for these objects. +*/ +#ifndef QWEBNETWORKINTERFACE_P_H +#define QWEBNETWORKINTERFACE_P_H + +#include "qwebnetworkinterface.h" +#if QT_VERSION < 0x040400 +#include <qthread.h> +#include <qmutex.h> + +namespace WebCore { + struct HostInfo; + class ResourceRequest; +}; +uint qHash(const WebCore::HostInfo &info); +#include <qhash.h> + +namespace WebCore { + class ResourceHandle; +} + +struct QWebNetworkRequestPrivate +{ + QUrl url; + QHttpRequestHeader httpHeader; + QByteArray postData; + + void init(const WebCore::ResourceRequest &resourceRequest); + void init(const QString &method, const QUrl &url, const WebCore::ResourceRequest *resourceRequest = 0); + void setURL(const QUrl &u); +}; + +class QWebNetworkJobPrivate +{ +public: + QWebNetworkJobPrivate() + : ref(1) + , resourceHandle(0) + , redirected(false) + , interface(0) + , connector(0) + , jobStatus(QWebNetworkJob::JobCreated) + {} + int ref; + + QWebNetworkRequestPrivate request; + QHttpResponseHeader response; + + WebCore::ResourceHandle *resourceHandle; + bool redirected; + + QWebNetworkInterface *interface; + QWebObjectPluginConnector *connector; + QWebNetworkJob::JobStatus jobStatus; + QString errorString; +}; + +class QWebNetworkManager : public QObject +{ + Q_OBJECT +public: + enum JobMode { + AsynchronousJob, + SynchronousJob + }; + + static QWebNetworkManager *self(); + + bool add(WebCore::ResourceHandle *resourceHandle, QWebNetworkInterface *interface, JobMode = AsynchronousJob); + void cancel(WebCore::ResourceHandle *resourceHandle); + + void addHttpJob(QWebNetworkJob *job); + void cancelHttpJob(QWebNetworkJob *job); + +protected: + void queueStart(QWebNetworkJob*); + void queueData(QWebNetworkJob*, const QByteArray&); + void queueFinished(QWebNetworkJob*, int errorCode); + +private: + void started(QWebNetworkJob *); + void data(QWebNetworkJob *, const QByteArray &data); + void finished(QWebNetworkJob *, int errorCode); + void doScheduleWork(); + +signals: + void fileRequest(QWebNetworkJob*); + void scheduleWork(); + +private slots: + void httpConnectionClosed(const WebCore::HostInfo &); + void doWork(); + +private: + friend class QWebNetworkInterface; + QWebNetworkManager(); + QHash<WebCore::HostInfo, WebCore::WebCoreHttp *> m_hostMapping; + + struct JobWork { + enum WorkType { + JobStarted, + JobData, + JobFinished + }; + + explicit JobWork(QWebNetworkJob* _job) + : workType(JobStarted) + , errorCode(-1) + , job(_job) + {} + + explicit JobWork(QWebNetworkJob* _job, int _errorCode) + : workType(JobFinished) + , errorCode(_errorCode) + , job(_job) + {} + + explicit JobWork(QWebNetworkJob* _job, const QByteArray& _data) + : workType(JobData) + , errorCode(-1) + , job(_job) + , data(_data) + {} + + const WorkType workType; + int errorCode; + QByteArray data; + QWebNetworkJob* job; + }; + + QMutex m_queueMutex; + bool m_scheduledWork; + QList<JobWork*> m_pendingWork; + QHash<QWebNetworkJob*, int> m_synchronousJobs; +}; + + +namespace WebCore { + + class NetworkLoader; + + struct HostInfo { + HostInfo() {} + HostInfo(const QUrl& url); + QString protocol; + QString host; + int port; + }; + + class WebCoreHttp : public QObject + { + Q_OBJECT + public: + WebCoreHttp(QObject *parent, const HostInfo&); + ~WebCoreHttp(); + + void request(QWebNetworkJob* resource); + void cancel(QWebNetworkJob*); + + signals: + void connectionClosed(const WebCore::HostInfo &); + + private slots: + void onResponseHeaderReceived(const QHttpResponseHeader& resp); + void onReadyRead(); + void onRequestFinished(int, bool); + void onDone(bool); + void onStateChanged(int); + void onSslErrors(const QList<QSslError>&); + void onAuthenticationRequired(const QString& hostname, quint16 port, QAuthenticator *); + void onProxyAuthenticationRequired(const QNetworkProxy& proxy, QAuthenticator *); + + void scheduleNextRequest(); + + int getConnection(); + + public: + HostInfo info; + private: + QList<QWebNetworkJob *> m_pendingRequests; + struct HttpConnection { + HttpConnection() : http(0), current(0), id(-1) {} + QHttp *http; + QWebNetworkJob *current; + int id; // the QHttp id + }; + HttpConnection connection[2]; + bool m_inCancel; + }; + +} + +class QWebNetworkInterfacePrivate +{ +public: + void sendFileData(QWebNetworkJob* job, int statusCode, const QByteArray &data); + void parseDataUrl(QWebNetworkJob* job); + + QWebNetworkInterface *q; +}; + +#endif + +#endif diff --git a/WebKit/qt/Api/qwebobjectplugin.cpp b/WebKit/qt/Api/qwebobjectplugin.cpp new file mode 100644 index 0000000..b24d604 --- /dev/null +++ b/WebKit/qt/Api/qwebobjectplugin.cpp @@ -0,0 +1,192 @@ +/* + Copyright (C) 2007 Trolltech ASA + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. + +*/ +#include "qwebobjectplugin_p.h" +#include <qwebobjectpluginconnector.h> +#include <qcoreapplication.h> +#include <qfileinfo.h> + +#if QT_VERSION < 0x040400 + +#ifndef QT_NO_LIBRARY +Q_GLOBAL_STATIC_WITH_ARGS(QWebFactoryLoader, loader, + (QWebObjectPluginFactoryInterface_iid, QCoreApplication::libraryPaths(), QLatin1String("/webplugins"))) +#endif + + +QWebFactoryLoader::QWebFactoryLoader(const char *iid, const QStringList &paths, const QString &suffix, Qt::CaseSensitivity) + : QFactoryLoader(iid, paths, suffix) +{ + QStringList plugins = keys(); + foreach(QString k, plugins) { + QWebObjectPlugin *plugin = qobject_cast<QWebObjectPlugin *>(instance(k)); + if (!plugin) + continue; + Info info; + info.name = k; + info.description = plugin->descriptionForKey(k); + QStringList mimetypes = plugin->mimetypesForKey(k); + foreach(QString m, mimetypes) { + MimeInfo mime; + mime.type = m; + mime.extensions = plugin->extensionsForMimetype(m); + info.mimes << mime; + } + m_pluginInfo.append(info); + } +} + +QWebFactoryLoader *QWebFactoryLoader::self() +{ + return loader(); +} + + +QString QWebFactoryLoader::descriptionForName(const QString &key) const +{ + foreach(const Info &info, m_pluginInfo) { + if (info.name == key) + return info.description; + } + return QString(); +} + +QStringList QWebFactoryLoader::mimetypesForName(const QString &key) const +{ + foreach(const Info &info, m_pluginInfo) { + if (info.name == key) { + QStringList mimetypes; + foreach (const MimeInfo &m, info.mimes) + mimetypes.append(m.type); + return mimetypes; + } + } + return QStringList(); +} + +QString QWebFactoryLoader::mimeTypeForExtension(const QString &extension) +{ + foreach(const Info &info, m_pluginInfo) { + foreach (const MimeInfo &m, info.mimes) { + if (m.extensions.contains(extension)) + return m.type; + } + } + return QString(); +} + + +QStringList QWebFactoryLoader::extensions() const +{ + QStringList extensions; + foreach(const Info &info, m_pluginInfo) { + foreach (const MimeInfo &m, info.mimes) + extensions << m.extensions; + } + return QStringList(); + +} + +QString QWebFactoryLoader::nameForMimetype(const QString &mimeType) const +{ + foreach(const Info &info, m_pluginInfo) { + foreach (const MimeInfo &m, info.mimes) + if (m.type == mimeType) + return info.name; + } + return QString(); +} + +QObject *QWebFactoryLoader::create(QWebFrame *frame, + const QUrl &url, + const QString &_mimeType, + const QStringList &argumentNames, + const QStringList &argumentValues) +{ + QString mimeType = _mimeType; + if (mimeType.isEmpty()) { + QFileInfo fi(url.path()); + mimeType = mimeTypeForExtension(fi.suffix()); + } + QString name = nameForMimetype(mimeType); + QWebObjectPlugin *plugin = qobject_cast<QWebObjectPlugin *>(instance(name)); + if (!plugin) + return 0; + QWebObjectPluginConnector *connector = new QWebObjectPluginConnector(frame); + return plugin->create(connector, url, mimeType, argumentNames, argumentValues); +} + + + +/*! \class QWebObjectPlugin + + This class is a plugin for the HTML object tag. It can be used to embed arbitrary content in a web page. +*/ + + +QWebObjectPlugin::QWebObjectPlugin(QObject *parent) + : QObject(parent) +{ +} + +QWebObjectPlugin::~QWebObjectPlugin() +{ +} + +/*! + \fn QStringList QWebObjectPlugin::keys() const + + The keys should be unique names. +*/ + +/*! + A description for \a key. +*/ +QString QWebObjectPlugin::descriptionForKey(const QString &key) const +{ + return QString(); +} + +/*! + returns the mimetypes that can be handled by \a key. +*/ +QStringList QWebObjectPlugin::mimetypesForKey(const QString &key) const +{ + return QStringList(); +} + + +/*! + \fn QStringList QWebObjectPlugin::extensionsForMimetype() const + + Should return a list of extensions that are recognised to match the \a mimeType. +*/ +QStringList QWebObjectPlugin::extensionsForMimetype(const QString &mimeType) const +{ + return QStringList(); +} + +/*! + \fn QObject *QWebObjectPlugin::create(QWebObjectPluginConnector *connector, const QUrl &url, const QString &mimeType, const QStringList &argumentNames, const QStringList &argumentValues) const + + Creates a QObject with \a connector to handle \a mimeType. \a argumentNames and \a argumentValues are a set of key-value pairs passed directly + from the <param> elements contained in the HTML object tag. +*/ + +#endif diff --git a/WebKit/qt/Api/qwebobjectplugin.h b/WebKit/qt/Api/qwebobjectplugin.h new file mode 100644 index 0000000..3c7caf7 --- /dev/null +++ b/WebKit/qt/Api/qwebobjectplugin.h @@ -0,0 +1,66 @@ +/* + Copyright (C) 2007 Trolltech ASA + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. + +*/ +#ifndef QWEBOBJECTPLUGIN_H +#define QWEBOBJECTPLUGIN_H + +#include "qwebkitglobal.h" +#include <QtCore/qplugin.h> +#include <QtCore/qfactoryinterface.h> + +#if QT_VERSION < 0x040400 + +class QWebObjectPluginConnector; +class QUrl; + +struct QWEBKIT_EXPORT QWebObjectPluginFactoryInterface : public QFactoryInterface +{ + virtual QObject *create(QWebObjectPluginConnector *connector, + const QUrl &url, + const QString &mimeType, + const QStringList &argumentNames, + const QStringList &argumentValues) const = 0; +}; + +#define QWebObjectPluginFactoryInterface_iid "com.trolltech.Qt.QWebObjectPluginFactoryInterface" +Q_DECLARE_INTERFACE(QWebObjectPluginFactoryInterface, QWebObjectPluginFactoryInterface_iid) + +class QWEBKIT_EXPORT QWebObjectPlugin : public QObject, public QWebObjectPluginFactoryInterface +{ + Q_OBJECT + Q_INTERFACES(QWebObjectPluginFactoryInterface:QFactoryInterface) +public: + explicit QWebObjectPlugin(QObject *parent = 0); + virtual ~QWebObjectPlugin(); + + virtual QStringList keys() const = 0; + + virtual QString descriptionForKey(const QString &key) const; + virtual QStringList mimetypesForKey(const QString &key) const; + virtual QStringList extensionsForMimetype(const QString &mimeType) const; + virtual QObject *create(QWebObjectPluginConnector *connector, + const QUrl &url, + const QString &mimeType, + const QStringList &argumentNames, + const QStringList &argumentValues) const = 0; +}; + +#endif + +#endif diff --git a/WebKit/qt/Api/qwebobjectplugin_p.h b/WebKit/qt/Api/qwebobjectplugin_p.h new file mode 100644 index 0000000..e20261f --- /dev/null +++ b/WebKit/qt/Api/qwebobjectplugin_p.h @@ -0,0 +1,76 @@ +#ifndef QWEBOBJECTPLUGIN_P_H +#define QWEBOBJECTPLUGIN_P_H + +#include <QtCore/qglobal.h> +#include "qwebobjectplugin.h" + +#if QT_VERSION < 0x040400 + +/* + FIXME: This is copied from qfactoryloader_p.h. + Remove this once we made qfactoryloader public in Qt +*/ +class QFactoryLoaderPrivate; + +class Q_CORE_EXPORT QFactoryLoader : public QObject +{ + Q_OBJECT_FAKE + Q_DECLARE_PRIVATE(QFactoryLoader) + +public: + QFactoryLoader(const char *iid, + const QStringList &paths = QStringList(), + const QString &suffix = QString(), + Qt::CaseSensitivity = Qt::CaseSensitive); + ~QFactoryLoader(); + + QStringList keys() const; + QObject *instance(const QString &key) const; + +}; + +class QWebFrame; + +class QWebFactoryLoader : public QFactoryLoader +{ + Q_OBJECT +public: + QWebFactoryLoader(const char *iid, + const QStringList &paths = QStringList(), + const QString &suffix = QString(), + Qt::CaseSensitivity = Qt::CaseSensitive); + + static QWebFactoryLoader *self(); + + QStringList names() const { return keys(); } + QStringList extensions() const; + QString descriptionForName(const QString &key) const; + QStringList mimetypesForName(const QString &key) const; + QString nameForMimetype(const QString &mimeType) const; + inline bool supportsMimeType(const QString &mimeType) const { + return !nameForMimetype(mimeType).isEmpty(); + } + + QString mimeTypeForExtension(const QString &extension); + + QObject *create(QWebFrame *frame, + const QUrl &url, + const QString &mimeType, + const QStringList &argumentNames, + const QStringList &argumentValues); + + struct MimeInfo { + QString type; + QStringList extensions; + }; + struct Info { + QString name; + QString description; + QList<MimeInfo> mimes; + }; + QList<Info> m_pluginInfo; +}; + +#endif + +#endif diff --git a/WebKit/qt/Api/qwebobjectpluginconnector.cpp b/WebKit/qt/Api/qwebobjectpluginconnector.cpp new file mode 100644 index 0000000..f53c164 --- /dev/null +++ b/WebKit/qt/Api/qwebobjectpluginconnector.cpp @@ -0,0 +1,64 @@ +/* + Copyright (C) 2007 Trolltech ASA + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. + +*/ +#include "qwebobjectpluginconnector.h" +#if QT_VERSION < 0x040400 +#include "qwebnetworkinterface.h" +#include "qwebnetworkinterface_p.h" +#include "qwebframe.h" +#include "qwebpage.h" + +struct QWebObjectPluginConnectorPrivate +{ + QWebFrame *frame; +}; + +QWebObjectPluginConnector::QWebObjectPluginConnector(QWebFrame *frame) +{ + d = new QWebObjectPluginConnectorPrivate; + d->frame = frame; +} + +QWebFrame *QWebObjectPluginConnector::frame() const +{ + return d->frame; +} + +QWidget *QWebObjectPluginConnector::pluginParentWidget() const +{ + return d->frame->page()->view(); +} + +QWebNetworkJob *QWebObjectPluginConnector::requestUrl(const QWebNetworkRequest &request, Target target) +{ + if (target != Plugin) + return 0; + + QWebNetworkJob *job = new QWebNetworkJob; + QWebNetworkJobPrivate *p = job->d; + p->interface = d->frame->page()->networkInterface(); + p->connector = this; + + p->request = *request.d; + + d->frame->page()->networkInterface()->addJob(job); + return job; +} + +#endif diff --git a/WebKit/qt/Api/qwebobjectpluginconnector.h b/WebKit/qt/Api/qwebobjectpluginconnector.h new file mode 100644 index 0000000..62251a3 --- /dev/null +++ b/WebKit/qt/Api/qwebobjectpluginconnector.h @@ -0,0 +1,69 @@ +/* + Copyright (C) 2007 Trolltech ASA + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. + +*/ +#ifndef QWEBOBJECTPLUGINCONNECTOR_H +#define QWEBOBJECTPLUGINCONNECTOR_H + +#include "qwebkitglobal.h" +#include <QtCore/qobject.h> + +#if QT_VERSION < 0x040400 + +#include "qwebnetworkinterface.h" + +class QWebFrame; +class QWebPage; +class QWidget; +class QUrl; +class QWebObjectPluginConnectorPrivate; +class QWebFactoryLoader; +class QWebNetworkManager; + +class QWEBKIT_EXPORT QWebObjectPluginConnector : public QObject +{ + Q_OBJECT +public: + QWebFrame *frame() const; + QWidget *pluginParentWidget() const; + + enum Target { + Plugin, + New, + Self, + Parent, + Top + }; + QWebNetworkJob *requestUrl(const QWebNetworkRequest &request, Target target = Plugin); + +signals: + void started(QWebNetworkJob*); + void data(QWebNetworkJob*, const QByteArray &data); + void finished(QWebNetworkJob*, int errorCode); + +private: + friend class QWebFactoryLoader; + friend class QWebNetworkManager; + QWebObjectPluginConnector(QWebFrame *frame); + + QWebObjectPluginConnectorPrivate *d; +}; + +#endif + +#endif diff --git a/WebKit/qt/Api/qwebpage.cpp b/WebKit/qt/Api/qwebpage.cpp new file mode 100644 index 0000000..6e5e984 --- /dev/null +++ b/WebKit/qt/Api/qwebpage.cpp @@ -0,0 +1,1593 @@ +/* + Copyright (C) 2007 Trolltech ASA + Copyright (C) 2007 Staikos Computing Services Inc. + Copyright (C) 2007 Apple Inc. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. + + This class provides all functionality needed for loading images, style sheets and html + pages from the web. It has a memory cache for these objects. +*/ +#include "config.h" +#include "qwebpage.h" +#include "qwebview.h" +#include "qwebframe.h" +#include "qwebpage_p.h" +#include "qwebframe_p.h" +#include "qwebhistory.h" +#include "qwebhistory_p.h" +#include "qwebsettings.h" + +#include "Frame.h" +#include "FrameLoaderClientQt.h" +#include "ChromeClientQt.h" +#include "ContextMenu.h" +#include "ContextMenuClientQt.h" +#include "DragClientQt.h" +#include "DragController.h" +#include "DragData.h" +#include "EditorClientQt.h" +#include "Settings.h" +#include "Page.h" +#include "FrameLoader.h" +#include "FrameLoadRequest.h" +#include "KURL.h" +#include "Image.h" +#include "InspectorClientQt.h" +#include "InspectorController.h" +#include "FocusController.h" +#include "Editor.h" +#include "PlatformScrollBar.h" +#include "PlatformKeyboardEvent.h" +#include "PlatformWheelEvent.h" +#include "ProgressTracker.h" +#include "RefPtr.h" +#include "HashMap.h" +#include "HitTestResult.h" +#include "WindowFeatures.h" +#include "LocalizedStrings.h" + +#include <QDebug> +#include <QDragEnterEvent> +#include <QDragLeaveEvent> +#include <QDragMoveEvent> +#include <QDropEvent> +#include <QFileDialog> +#include <QHttpRequestHeader> +#include <QInputDialog> +#include <QMessageBox> +#include <QNetworkProxy> +#include <QUndoStack> +#include <QUrl> +#include <QPainter> +#if QT_VERSION >= 0x040400 +#include <QNetworkAccessManager> +#include <QNetworkRequest> +#else +#include "qwebnetworkinterface.h" +#endif + +using namespace WebCore; + +static inline DragOperation dropActionToDragOp(Qt::DropActions actions) +{ + unsigned result = 0; + if (actions & Qt::CopyAction) + result |= DragOperationCopy; + if (actions & Qt::MoveAction) + result |= DragOperationMove; + if (actions & Qt::LinkAction) + result |= DragOperationLink; + return (DragOperation)result; +} + +static inline Qt::DropAction dragOpToDropAction(unsigned actions) +{ + Qt::DropAction result = Qt::IgnoreAction; + if (actions & DragOperationCopy) + result = Qt::CopyAction; + else if (actions & DragOperationMove) + result = Qt::MoveAction; + else if (actions & DragOperationLink) + result = Qt::LinkAction; + return result; +} + +QWebPagePrivate::QWebPagePrivate(QWebPage *qq) + : q(qq) + , view(0) + , modified(false) +{ + chromeClient = new ChromeClientQt(q); + contextMenuClient = new ContextMenuClientQt(); + editorClient = new EditorClientQt(q); + page = new Page(chromeClient, contextMenuClient, editorClient, + new DragClientQt(q), new InspectorClientQt(q)); + + // ### should be configurable + page->settings()->setDefaultTextEncodingName("iso-8859-1"); + + settings = new QWebSettings(page->settings()); + + undoStack = 0; + mainFrame = 0; +#if QT_VERSION < 0x040400 + networkInterface = 0; +#else + networkManager = 0; +#endif + insideOpenCall = false; + + history.d = new QWebHistoryPrivate(page->backForwardList()); + memset(actions, 0, sizeof(actions)); +} + +QWebPagePrivate::~QWebPagePrivate() +{ + delete undoStack; + delete settings; + delete page; +#if QT_VERSION >= 0x040400 + delete networkManager; +#endif +} + +#if QT_VERSION < 0x040400 +QWebPage::NavigationRequestResponse QWebPagePrivate::navigationRequested(QWebFrame *frame, const QWebNetworkRequest &request, QWebPage::NavigationType type) +{ + if (insideOpenCall + && frame == mainFrame) + return QWebPage::AcceptNavigationRequest; + return q->navigationRequested(frame, request, type); +} +#else +QWebPage::NavigationRequestResponse QWebPagePrivate::navigationRequested(QWebFrame *frame, const QNetworkRequest &request, QWebPage::NavigationType type) +{ + if (insideOpenCall + && frame == mainFrame) + return QWebPage::AcceptNavigationRequest; + return q->navigationRequested(frame, request, type); +} +#endif + +void QWebPagePrivate::createMainFrame() +{ + if (!mainFrame) { + QWebFrameData frameData; + frameData.ownerElement = 0; + frameData.allowsScrolling = true; + frameData.marginWidth = 0; + frameData.marginHeight = 0; + mainFrame = new QWebFrame(q, &frameData); + mainFrame->d->frameView->setFrameGeometry(IntRect(IntPoint(0,0), q->viewportSize())); + + emit q->frameCreated(mainFrame); + } +} + +static QWebPage::WebAction webActionForContextMenuAction(WebCore::ContextMenuAction action) +{ + switch (action) { + case WebCore::ContextMenuItemTagOpenLink: return QWebPage::OpenLink; + case WebCore::ContextMenuItemTagOpenLinkInNewWindow: return QWebPage::OpenLinkInNewWindow; + case WebCore::ContextMenuItemTagDownloadLinkToDisk: return QWebPage::DownloadLinkToDisk; + case WebCore::ContextMenuItemTagCopyLinkToClipboard: return QWebPage::CopyLinkToClipboard; + case WebCore::ContextMenuItemTagOpenImageInNewWindow: return QWebPage::OpenImageInNewWindow; + case WebCore::ContextMenuItemTagDownloadImageToDisk: return QWebPage::DownloadImageToDisk; + case WebCore::ContextMenuItemTagCopyImageToClipboard: return QWebPage::CopyImageToClipboard; + case WebCore::ContextMenuItemTagOpenFrameInNewWindow: return QWebPage::OpenFrameInNewWindow; + case WebCore::ContextMenuItemTagCopy: return QWebPage::Copy; + case WebCore::ContextMenuItemTagGoBack: return QWebPage::GoBack; + case WebCore::ContextMenuItemTagGoForward: return QWebPage::GoForward; + case WebCore::ContextMenuItemTagStop: return QWebPage::Stop; + case WebCore::ContextMenuItemTagReload: return QWebPage::Reload; + case WebCore::ContextMenuItemTagCut: return QWebPage::Cut; + case WebCore::ContextMenuItemTagPaste: return QWebPage::Paste; + case WebCore::ContextMenuItemTagDefaultDirection: return QWebPage::SetTextDirectionDefault; + case WebCore::ContextMenuItemTagLeftToRight: return QWebPage::SetTextDirectionLeftToRight; + case WebCore::ContextMenuItemTagRightToLeft: return QWebPage::SetTextDirectionRightToLeft; + case WebCore::ContextMenuItemTagBold: return QWebPage::ToggleBold; + case WebCore::ContextMenuItemTagItalic: return QWebPage::ToggleItalic; + case WebCore::ContextMenuItemTagUnderline: return QWebPage::ToggleUnderline; + case WebCore::ContextMenuItemTagInspectElement: return QWebPage::InspectElement; + default: break; + } + return QWebPage::NoWebAction; +} + +QMenu *QWebPagePrivate::createContextMenu(const WebCore::ContextMenu *webcoreMenu, const QList<WebCore::ContextMenuItem> *items) +{ + QMenu *menu = new QMenu; + for (int i = 0; i < items->count(); ++i) { + const ContextMenuItem &item = items->at(i); + switch (item.type()) { + case WebCore::CheckableActionType: /* fall through */ + case WebCore::ActionType: { + QWebPage::WebAction action = webActionForContextMenuAction(item.action()); + QAction *a = q->action(action); + if (a) { + ContextMenuItem it(item); + webcoreMenu->checkOrEnableIfNeeded(it); + PlatformMenuItemDescription desc = it.releasePlatformDescription(); + a->setEnabled(desc.enabled); + a->setChecked(desc.checked); + a->setCheckable(item.type() == WebCore::CheckableActionType); + + menu->addAction(a); + } + break; + } + case WebCore::SeparatorType: + menu->addSeparator(); + break; + case WebCore::SubmenuType: { + QMenu *subMenu = createContextMenu(webcoreMenu, item.platformSubMenu()); + if (!subMenu->actions().isEmpty()) { + subMenu->setTitle(item.title()); + menu->addAction(subMenu->menuAction()); + } else { + delete subMenu; + } + break; + } + } + } + return menu; +} + +QWebFrame *QWebPagePrivate::frameAt(const QPoint &pos) const +{ + QWebFrame *frame = mainFrame; + +redo: + QList<QWebFrame*> children = frame->childFrames(); + for (int i = 0; i < children.size(); ++i) { + if (children.at(i)->geometry().contains(pos)) { + frame = children.at(i); + goto redo; + } + } + if (frame->geometry().contains(pos)) + return frame; + return 0; +} + +void QWebPagePrivate::_q_webActionTriggered(bool checked) +{ + QAction *a = qobject_cast<QAction *>(q->sender()); + if (!a) + return; + QWebPage::WebAction action = static_cast<QWebPage::WebAction>(a->data().toInt()); + q->triggerAction(action, checked); +} + +void QWebPagePrivate::updateAction(QWebPage::WebAction action) +{ + QAction *a = actions[action]; + if (!a || !mainFrame) + return; + + WebCore::FrameLoader *loader = mainFrame->d->frame->loader(); + WebCore::Editor *editor = page->focusController()->focusedOrMainFrame()->editor(); + + bool enabled = a->isEnabled(); + + switch (action) { + case QWebPage::GoBack: + enabled = loader->canGoBackOrForward(-1); + break; + case QWebPage::GoForward: + enabled = loader->canGoBackOrForward(1); + break; + case QWebPage::Stop: + enabled = loader->isLoading(); + break; + case QWebPage::Reload: + enabled = !loader->isLoading(); + break; + case QWebPage::Cut: + enabled = editor->canCut(); + break; + case QWebPage::Copy: + enabled = editor->canCopy(); + break; + case QWebPage::Paste: + enabled = editor->canPaste(); + break; + case QWebPage::Undo: + case QWebPage::Redo: + // those two are handled by QUndoStack + break; + default: break; + } + + a->setEnabled(enabled); +} + +void QWebPagePrivate::updateNavigationActions() +{ + updateAction(QWebPage::GoBack); + updateAction(QWebPage::GoForward); + updateAction(QWebPage::Stop); + updateAction(QWebPage::Reload); +} + +void QWebPagePrivate::updateEditorActions() +{ + updateAction(QWebPage::Cut); + updateAction(QWebPage::Copy); + updateAction(QWebPage::Paste); +} + +void QWebPagePrivate::mouseMoveEvent(QMouseEvent *ev) +{ + QWebFramePrivate::core(mainFrame)->eventHandler()->mouseMoved(PlatformMouseEvent(ev, 0)); +} + +void QWebPagePrivate::mousePressEvent(QMouseEvent *ev) +{ + QWebFramePrivate::core(mainFrame)->eventHandler()->handleMousePressEvent(PlatformMouseEvent(ev, 1)); +} + +void QWebPagePrivate::mouseDoubleClickEvent(QMouseEvent *ev) +{ + QWebFramePrivate::core(mainFrame)->eventHandler()->handleMousePressEvent(PlatformMouseEvent(ev, 2)); +} + +void QWebPagePrivate::mouseReleaseEvent(QMouseEvent *ev) +{ + QWebFramePrivate::core(mainFrame)->eventHandler()->handleMouseReleaseEvent(PlatformMouseEvent(ev, 0)); +} + +void QWebPagePrivate::contextMenuEvent(QContextMenuEvent *ev) +{ + page->contextMenuController()->clearContextMenu(); + + WebCore::Frame* focusedFrame = page->focusController()->focusedOrMainFrame(); + focusedFrame->eventHandler()->sendContextMenuEvent(PlatformMouseEvent(ev, 1)); + ContextMenu *menu = page->contextMenuController()->contextMenu(); + // If the website defines its own handler then sendContextMenuEvent takes care of + // calling/showing it and the context menu pointer will be zero. This is the case + // on maps.google.com for example. + if (!menu) + return; + + QWebPageContext oldContext = currentContext; + currentContext = QWebPageContext(menu->hitTestResult()); + + const QList<ContextMenuItem> *items = menu->platformDescription(); + QMenu *qmenu = createContextMenu(menu, items); + if (qmenu) { + qmenu->exec(ev->globalPos()); + delete qmenu; + } + currentContext = oldContext; +} + +void QWebPagePrivate::wheelEvent(QWheelEvent *ev) +{ + WebCore::PlatformWheelEvent pev(ev); + bool accepted = QWebFramePrivate::core(mainFrame)->eventHandler()->handleWheelEvent(pev); + ev->setAccepted(accepted); +} + +void QWebPagePrivate::keyPressEvent(QKeyEvent *ev) +{ + bool handled = false; + WebCore::Frame *frame = page->focusController()->focusedOrMainFrame(); + WebCore::Editor *editor = frame->editor(); + if (editor->canEdit()) { + if (ev == QKeySequence::Cut) { + q->triggerAction(QWebPage::Cut); + handled = true; + } else if (ev == QKeySequence::Copy) { + q->triggerAction(QWebPage::Copy); + handled = true; + } else if (ev == QKeySequence::Paste) { + q->triggerAction(QWebPage::Paste); + handled = true; + } else if (ev == QKeySequence::Undo) { + q->triggerAction(QWebPage::Undo); + handled = true; + } else if (ev == QKeySequence::Redo) { + q->triggerAction(QWebPage::Redo); + handled = true; + } else if(ev == QKeySequence::MoveToNextChar) { + q->triggerAction(QWebPage::MoveToNextChar); + handled = true; + } else if(ev == QKeySequence::MoveToPreviousChar) { + q->triggerAction(QWebPage::MoveToPreviousChar); + handled = true; + } else if(ev == QKeySequence::MoveToNextWord) { + q->triggerAction(QWebPage::MoveToNextWord); + handled = true; + } else if(ev == QKeySequence::MoveToPreviousWord) { + q->triggerAction(QWebPage::MoveToPreviousWord); + handled = true; + } else if(ev == QKeySequence::MoveToNextLine) { + q->triggerAction(QWebPage::MoveToNextLine); + handled = true; + } else if(ev == QKeySequence::MoveToPreviousLine) { + q->triggerAction(QWebPage::MoveToPreviousLine); + handled = true; +// } else if(ev == QKeySequence::MoveToNextPage) { +// } else if(ev == QKeySequence::MoveToPreviousPage) { + } else if(ev == QKeySequence::MoveToStartOfLine) { + q->triggerAction(QWebPage::MoveToStartOfLine); + handled = true; + } else if(ev == QKeySequence::MoveToEndOfLine) { + q->triggerAction(QWebPage::MoveToEndOfLine); + handled = true; + } else if(ev == QKeySequence::MoveToStartOfBlock) { + q->triggerAction(QWebPage::MoveToStartOfBlock); + handled = true; + } else if(ev == QKeySequence::MoveToEndOfBlock) { + q->triggerAction(QWebPage::MoveToEndOfBlock); + handled = true; + } else if(ev == QKeySequence::MoveToStartOfDocument) { + q->triggerAction(QWebPage::MoveToStartOfDocument); + handled = true; + } else if(ev == QKeySequence::MoveToEndOfDocument) { + q->triggerAction(QWebPage::MoveToEndOfDocument); + handled = true; + } else if(ev == QKeySequence::SelectNextChar) { + q->triggerAction(QWebPage::SelectNextChar); + handled = true; + } else if(ev == QKeySequence::SelectPreviousChar) { + q->triggerAction(QWebPage::SelectPreviousChar); + handled = true; + } else if(ev == QKeySequence::SelectNextWord) { + q->triggerAction(QWebPage::SelectNextWord); + handled = true; + } else if(ev == QKeySequence::SelectPreviousWord) { + q->triggerAction(QWebPage::SelectPreviousWord); + handled = true; + } else if(ev == QKeySequence::SelectNextLine) { + q->triggerAction(QWebPage::SelectNextLine); + handled = true; + } else if(ev == QKeySequence::SelectPreviousLine) { + q->triggerAction(QWebPage::SelectPreviousLine); + handled = true; +// } else if(ev == QKeySequence::SelectNextPage) { +// } else if(ev == QKeySequence::SelectPreviousPage) { + } else if(ev == QKeySequence::SelectStartOfLine) { + q->triggerAction(QWebPage::SelectStartOfLine); + handled = true; + } else if(ev == QKeySequence::SelectEndOfLine) { + q->triggerAction(QWebPage::SelectEndOfLine); + handled = true; + } else if(ev == QKeySequence::SelectStartOfBlock) { + q->triggerAction(QWebPage::SelectStartOfBlock); + handled = true; + } else if(ev == QKeySequence::SelectEndOfBlock) { + q->triggerAction(QWebPage::SelectEndOfBlock); + handled = true; + } else if(ev == QKeySequence::SelectStartOfDocument) { + q->triggerAction(QWebPage::SelectStartOfDocument); + handled = true; + } else if(ev == QKeySequence::SelectEndOfDocument) { + q->triggerAction(QWebPage::SelectEndOfDocument); + handled = true; + } else if(ev == QKeySequence::DeleteStartOfWord) { + q->triggerAction(QWebPage::DeleteStartOfWord); + handled = true; + } else if(ev == QKeySequence::DeleteEndOfWord) { + q->triggerAction(QWebPage::DeleteEndOfWord); + handled = true; +// } else if(ev == QKeySequence::DeleteEndOfLine) { + } + } + if (!handled) + handled = frame->eventHandler()->keyEvent(ev); + if (!handled) { + handled = true; + PlatformScrollbar *h, *v; + h = mainFrame->d->horizontalScrollBar(); + v = mainFrame->d->verticalScrollBar(); + QFont defaultFont; + if (view) + defaultFont = view->font(); + QFontMetrics fm(defaultFont); + int fontHeight = fm.height(); + if (ev == QKeySequence::MoveToNextPage + || ev->key() == Qt::Key_Space) { + if (v) + v->setValue(v->value() + q->viewportSize().height() - fontHeight); + } else if (ev == QKeySequence::MoveToPreviousPage) { + if (v) + v->setValue(v->value() - q->viewportSize().height() + fontHeight); + } else if (ev->key() == Qt::Key_Up && ev->modifiers() == Qt::ControlModifier) { + if (v) + v->setValue(0); + } else if (ev->key() == Qt::Key_Down && ev->modifiers() == Qt::ControlModifier) { + if (v) + v->setValue(INT_MAX); + } else { + switch (ev->key()) { + case Qt::Key_Up: + if (v) + v->setValue(v->value() - fontHeight); + break; + case Qt::Key_Down: + if (v) + v->setValue(v->value() + fontHeight); + break; + case Qt::Key_Left: + if (h) + h->setValue(h->value() - fontHeight); + break; + case Qt::Key_Right: + if (h) + h->setValue(h->value() + fontHeight); + break; + case Qt::Key_Backspace: + if (ev->modifiers() == Qt::ShiftModifier) + q->triggerAction(QWebPage::GoForward); + else + q->triggerAction(QWebPage::GoBack); + default: + handled = false; + break; + } + } + } + + ev->setAccepted(handled); +} + +void QWebPagePrivate::keyReleaseEvent(QKeyEvent *ev) +{ + if (ev->isAutoRepeat()) { + ev->setAccepted(true); + return; + } + + WebCore::Frame* frame = page->focusController()->focusedOrMainFrame(); + bool handled = frame->eventHandler()->keyEvent(ev); + ev->setAccepted(handled); +} + +void QWebPagePrivate::focusInEvent(QFocusEvent *ev) +{ + if (ev->reason() != Qt::PopupFocusReason) + page->focusController()->setFocusedFrame(QWebFramePrivate::core(mainFrame)); +} + +void QWebPagePrivate::focusOutEvent(QFocusEvent *ev) +{ + if (ev->reason() != Qt::PopupFocusReason) + page->focusController()->setFocusedFrame(0); +} + +void QWebPagePrivate::dragEnterEvent(QDragEnterEvent *ev) +{ +#ifndef QT_NO_DRAGANDDROP + DragData dragData(ev->mimeData(), ev->pos(), QCursor::pos(), + dropActionToDragOp(ev->possibleActions())); + Qt::DropAction action = dragOpToDropAction(page->dragController()->dragEntered(&dragData)); + ev->setDropAction(action); + ev->accept(); +#endif +} + +void QWebPagePrivate::dragLeaveEvent(QDragLeaveEvent *ev) +{ +#ifndef QT_NO_DRAGANDDROP + DragData dragData(0, IntPoint(), QCursor::pos(), DragOperationNone); + page->dragController()->dragExited(&dragData); + ev->accept(); +#endif +} + +void QWebPagePrivate::dragMoveEvent(QDragMoveEvent *ev) +{ +#ifndef QT_NO_DRAGANDDROP + DragData dragData(ev->mimeData(), ev->pos(), QCursor::pos(), + dropActionToDragOp(ev->possibleActions())); + Qt::DropAction action = dragOpToDropAction(page->dragController()->dragUpdated(&dragData)); + ev->setDropAction(action); + ev->accept(); +#endif +} + +void QWebPagePrivate::dropEvent(QDropEvent *ev) +{ +#ifndef QT_NO_DRAGANDDROP + DragData dragData(ev->mimeData(), ev->pos(), QCursor::pos(), + dropActionToDragOp(ev->possibleActions())); + Qt::DropAction action = dragOpToDropAction(page->dragController()->performDrag(&dragData)); + ev->accept(); +#endif +} + +/*! + \enum QWebPage::WebAction + + \value NoWebAction No action is triggered. + \value OpenLink Open the current link. + \value OpenLinkInNewWindow Open the current link in a new window. + \value OpenFrameInNewWindow Replicate the current frame in a new window. + \value DownloadLinkToDisk Download the current link to the disk. + \value CopyLinkToClipboard Copy the current link to the clipboard. + \value OpenImageInNewWindow Open the highlighted image in a new window. + \value DownloadImageToDisk Download the highlighted image to the disk. + \value CopyImageToClipboard Copy the highlighted image to the clipboard. + \value GoBack Navigate back in the history of navigated links. + \value GoForward Navigate forward in the history of navigated links. + \value Stop Stop loading the current page. + \value Reload Reload the current page. + \value Cut Cut the content currently selected into the clipboard. + \value Copy Copy the content currently selected into the clipboard. + \value Paste Paste content from the clipboard. + \value Undo Undo the last editing action. + \value Redo Redo the last editing action. + \value MoveToNextChar Move the cursor to the next character. + \value MoveToPreviousChar Move the cursor to the previous character. + \value MoveToNextWord Move the cursor to the next word. + \value MoveToPreviousWord Move the cursor to the previous word. + \value MoveToNextLine Move the cursor to the next line. + \value MoveToPreviousLine Move the cursor to the previous line. + \value MoveToStartOfLine Move the cursor to the start of the line. + \value MoveToEndOfLine Move the cursor to the end of the line. + \value MoveToStartOfBlock Move the cursor to the start of the block. + \value MoveToEndOfBlock Move the cursor to the end of the block. + \value MoveToStartOfDocument Move the cursor to the start of the document. + \value MoveToEndOfDocument Move the cursor to the end of the document. + \value SelectNextChar Select to the next character. + \value SelectPreviousChar Select to the previous character. + \value SelectNextWord Select to the next word. + \value SelectPreviousWord Select to the previous word. + \value SelectNextLine Select to the next line. + \value SelectPreviousLine Select to the previous line. + \value SelectStartOfLine Select to the start of the line. + \value SelectEndOfLine Select to the end of the line. + \value SelectStartOfBlock Select to the start of the block. + \value SelectEndOfBlock Select to the end of the block. + \value SelectStartOfDocument Select to the start of the document. + \value SelectEndOfDocument Select to the end of the document. + \value DeleteStartOfWord Delete to the start of the word. + \value DeleteEndOfWord Delete to the end of the word. + \value SetTextDirectionDefault Set the text direction to the default direction. + \value SetTextDirectionLeftToRight Set the text direction to left-to-right. + \value SetTextDirectionRightToLeft Set the text direction to right-to-left. + \value ToggleBold Toggle the formatting between bold and normal weight. + \value ToggleItalic Toggle the formatting between italic and normal style. + \value ToggleUnderline Toggle underlining. + \value InspectElement Show the Web Inspector with the currently highlighted HTML element. + \omitvalue WebActionCount + +*/ + +/*! + \class QWebPage + \since 4.4 + \brief The QWebPage class provides a widget that is used to view and edit web documents. + + QWebPage holds a main frame responsible for web content, settings, the history + of navigated links as well as actions. This class can be used, together with QWebFrame, + if you want to provide functionality like QWebView in a setup without widgets. +*/ + +/*! + Constructs an empty QWebView with parent \a parent. +*/ +QWebPage::QWebPage(QObject *parent) + : QObject(parent) + , d(new QWebPagePrivate(this)) +{ + setView(qobject_cast<QWidget *>(parent)); + + connect(this, SIGNAL(loadProgressChanged(int)), this, SLOT(_q_onLoadProgressChanged(int))); +} + +/*! + Destructor. +*/ +QWebPage::~QWebPage() +{ + FrameLoader *loader = d->mainFrame->d->frame->loader(); + if (loader) + loader->detachFromParent(); + delete d; +} + +/*! + Returns the main frame of the page. + + The main frame provides access to the hierarchy of sub-frames and is also needed if you + want to explicitly render a web page into a given painter. +*/ +QWebFrame *QWebPage::mainFrame() const +{ + d->createMainFrame(); + return d->mainFrame; +} + +/*! + Returns the frame currently active. +*/ +QWebFrame *QWebPage::currentFrame() const +{ + return static_cast<WebCore::FrameLoaderClientQt *>(d->page->focusController()->focusedOrMainFrame()->loader()->client())->webFrame(); +} + +/*! + Returns a pointer to the view's history of navigated web pages. + +*/ +QWebHistory *QWebPage::history() const +{ + return &d->history; +} + +/*! + Sets the \a view that is associated with the web page. + + \sa view() +*/ +void QWebPage::setView(QWidget *view) +{ + d->view = view; + setViewportSize(view ? view->size() : QSize(0, 0)); +} + +/*! + Returns the view widget that is associated with the web page. + + \sa setView() +*/ +QWidget *QWebPage::view() const +{ + return d->view; +} + + +/*! + This function is called whenever a JavaScript program tries to print to what is the console in web browsers. +*/ +void QWebPage::javaScriptConsoleMessage(const QString& message, unsigned int lineNumber, const QString& sourceID) +{ +} + +/*! + This function is called whenever a JavaScript program calls the alert() function. +*/ +void QWebPage::javaScriptAlert(QWebFrame *frame, const QString& msg) +{ + QMessageBox::information(d->view, mainFrame()->title(), msg, QMessageBox::Ok); +} + +/*! + This function is called whenever a JavaScript program calls the confirm() function. +*/ +bool QWebPage::javaScriptConfirm(QWebFrame *frame, const QString& msg) +{ + return 0 == QMessageBox::information(d->view, mainFrame()->title(), msg, QMessageBox::Yes, QMessageBox::No); +} + +/*! + This function is called whenever a JavaScript program tries to prompt the user of input. +*/ +bool QWebPage::javaScriptPrompt(QWebFrame *frame, const QString& msg, const QString& defaultValue, QString* result) +{ + bool ok = false; +#ifndef QT_NO_INPUTDIALOG + QString x = QInputDialog::getText(d->view, mainFrame()->title(), msg, QLineEdit::Normal, defaultValue, &ok); + if (ok && result) { + *result = x; + } +#endif + return ok; +} + +/*! + This function is called whenever WebKit wants to create a new window, for example as a result of + a JavaScript request to open a document in a new window. +*/ +QWebPage *QWebPage::createWindow() +{ + QWebView *webView = qobject_cast<QWebView *>(d->view); + if (webView) { + QWebView *newView = webView->createWindow(); + if (newView) + return newView->page(); + } + return 0; +} + +/*! + This function is called whenever WebKit wants to create a new window that should act as a modal dialog. +*/ +QWebPage *QWebPage::createModalDialog() +{ + return 0; +} + +/*! + This function is called whenever WebKit encounters a HTML object element with type "application/x-qt-plugin". + The \a classid, \a url, \a paramNames and \a paramValues correspond to the HTML object element attributes and + child elements to configure the embeddable object. +*/ +QObject *QWebPage::createPlugin(const QString &classid, const QUrl &url, const QStringList ¶mNames, const QStringList ¶mValues) +{ + Q_UNUSED(classid) + Q_UNUSED(url) + Q_UNUSED(paramNames) + Q_UNUSED(paramValues) + return 0; +} + +static WebCore::FrameLoadRequest frameLoadRequest(const QUrl &url, WebCore::Frame *frame) +{ + WebCore::ResourceRequest rr(url, frame->loader()->outgoingReferrer()); + return WebCore::FrameLoadRequest(rr); +} + +static void openNewWindow(const QUrl& url, WebCore::Frame* frame) +{ + if (Page* oldPage = frame->page()) { + WindowFeatures features; + if (Page* newPage = oldPage->chrome()->createWindow(frame, + frameLoadRequest(url, frame), features)) + newPage->chrome()->show(); + } +} + +/*! + This function can be called to trigger the specified \a action. + It is also called by QtWebKit if the user triggers the action, for example + through a context menu item. + + If \a action is a checkable action then \a checked specified whether the action + is toggled or not. +*/ +void QWebPage::triggerAction(WebAction action, bool checked) +{ + WebCore::Frame *frame = d->page->focusController()->focusedOrMainFrame(); + WebCore::Editor *editor = frame->editor(); + const char *command = 0; + + switch (action) { + case OpenLink: + if (QWebFrame *targetFrame = d->currentContext.targetFrame()) { + WTF::RefPtr<WebCore::Frame> wcFrame = targetFrame->d->frame; + targetFrame->d->frame->loader()->load(frameLoadRequest(d->currentContext.linkUrl(), wcFrame.get()), + /*lockHistory*/ false, + /*userGesture*/ true, + /*event*/ 0, + /*HTMLFormElement*/ 0, + /*formValues*/ + WTF::HashMap<String, String>()); + break; + } else { + } + // fall through + case OpenLinkInNewWindow: + openNewWindow(d->currentContext.linkUrl(), frame); + break; + case OpenFrameInNewWindow: + break; + case CopyLinkToClipboard: + editor->copyURL(d->currentContext.linkUrl(), d->currentContext.text()); + break; + case OpenImageInNewWindow: + openNewWindow(d->currentContext.imageUrl(), frame); + break; + case DownloadImageToDisk: + case DownloadLinkToDisk: + frame->loader()->client()->startDownload(WebCore::ResourceRequest(d->currentContext.linkUrl(), frame->loader()->outgoingReferrer())); + break; + case CopyImageToClipboard: + break; + case GoBack: + d->page->goBack(); + break; + case GoForward: + d->page->goForward(); + break; + case Stop: + mainFrame()->d->frame->loader()->stopForUserCancel(); + break; + case Reload: + mainFrame()->d->frame->loader()->reload(); + break; + case Cut: + command = "Cut"; + break; + case Copy: + command = "Copy"; + break; + case Paste: + command = "Paste"; + break; + + case Undo: + command = "Undo"; + break; + case Redo: + command = "Redo"; + break; + + case MoveToNextChar: + command = "MoveForward"; + break; + case MoveToPreviousChar: + command = "MoveBackward"; + break; + case MoveToNextWord: + command = "MoveWordForward"; + break; + case MoveToPreviousWord: + command = "MoveWordBackward"; + break; + case MoveToNextLine: + command = "MoveDown"; + break; + case MoveToPreviousLine: + command = "MoveUp"; + break; + case MoveToStartOfLine: + command = "MoveToBeginningOfLine"; + break; + case MoveToEndOfLine: + command = "MoveToEndOfLine"; + break; + case MoveToStartOfBlock: + command = "MoveToBeginningOfParagraph"; + break; + case MoveToEndOfBlock: + command = "MoveToEndOfParagraph"; + break; + case MoveToStartOfDocument: + command = "MoveToBeginningOfDocument"; + break; + case MoveToEndOfDocument: + command = "MoveToEndOfDocument"; + break; + case SelectNextChar: + command = "MoveForwardAndModifySelection"; + break; + case SelectPreviousChar: + command = "MoveBackwardAndModifySelection"; + break; + case SelectNextWord: + command = "MoveWordForwardAndModifySelection"; + break; + case SelectPreviousWord: + command = "MoveWordBackwardAndModifySelection"; + break; + case SelectNextLine: + command = "MoveDownAndModifySelection"; + break; + case SelectPreviousLine: + command = "MoveUpAndModifySelection"; + break; + case SelectStartOfLine: + command = "MoveToBeginningOfLineAndModifySelection"; + break; + case SelectEndOfLine: + command = "MoveToEndOfLineAndModifySelection"; + break; + case SelectStartOfBlock: + command = "MoveToBeginningOfParagraphAndModifySelection"; + break; + case SelectEndOfBlock: + command = "MoveToEndOfParagraphAndModifySelection"; + break; + case SelectStartOfDocument: + command = "MoveToBeginningOfDocumentAndModifySelection"; + break; + case SelectEndOfDocument: + command = "MoveToEndOfDocumentAndModifySelection"; + break; + case DeleteStartOfWord: + command = "DeleteWordBackward"; + break; + case DeleteEndOfWord: + command = "DeleteWordForward"; + break; + + case SetTextDirectionDefault: + editor->setBaseWritingDirection("inherit"); + break; + case SetTextDirectionLeftToRight: + editor->setBaseWritingDirection("ltr"); + break; + case SetTextDirectionRightToLeft: + editor->setBaseWritingDirection("rtl"); + break; + + case ToggleBold: + command = "ToggleBold"; + break; + case ToggleItalic: + command = "ToggleItalic"; + break; + case ToggleUnderline: + editor->toggleUnderline(); + + case InspectElement: + d->page->inspectorController()->inspect(d->currentContext.d->innerNonSharedNode.get()); + break; + + default: break; + } + + if (command) + editor->command(command).execute(); +} + +QSize QWebPage::viewportSize() const +{ + QWebFrame *frame = mainFrame(); + if (frame->d->frame && frame->d->frameView) + return frame->d->frameView->frameGeometry().size(); + return QSize(0, 0); +} + +/*! + \property QWebPage::viewportSize + + Specifies the size of the viewport. The size affects for example the visibility of scrollbars + if the document is larger than the viewport. +*/ +void QWebPage::setViewportSize(const QSize &size) const +{ + QWebFrame *frame = mainFrame(); + if (frame->d->frame && frame->d->frameView) { + frame->d->frameView->setFrameGeometry(QRect(QPoint(0, 0), size)); + frame->d->frame->forceLayout(); + frame->d->frame->view()->adjustViewSize(); + } +} + + +#if QT_VERSION < 0x040400 +QWebPage::NavigationRequestResponse QWebPage::navigationRequested(QWebFrame *frame, const QWebNetworkRequest &request, QWebPage::NavigationType type) +#else +QWebPage::NavigationRequestResponse QWebPage::navigationRequested(QWebFrame *frame, const QNetworkRequest &request, QWebPage::NavigationType type) +#endif +{ + Q_UNUSED(request) + return AcceptNavigationRequest; +} + +/*! + \property QWebPage::selectedText + + Returns the text currently selected. +*/ +QString QWebPage::selectedText() const +{ + return d->page->focusController()->focusedOrMainFrame()->selectedText(); +} + +/*! + Returns a QAction for the specified WebAction \a action. + + The action is owned by the QWebPage but you can customize the look by + changing its properties. + + QWebPage also takes care of implementing the action, so that upon + triggering the corresponding action is performed on the page. +*/ +QAction *QWebPage::action(WebAction action) const +{ + if (action == QWebPage::NoWebAction) return 0; + if (d->actions[action]) + return d->actions[action]; + + QString text; + bool checkable = false; + + switch (action) { + case OpenLink: + text = contextMenuItemTagOpenLink(); + break; + case OpenLinkInNewWindow: + text = contextMenuItemTagOpenLinkInNewWindow(); + break; + case OpenFrameInNewWindow: + text = contextMenuItemTagOpenFrameInNewWindow(); + break; + + case DownloadLinkToDisk: + text = contextMenuItemTagDownloadLinkToDisk(); + break; + case CopyLinkToClipboard: + text = contextMenuItemTagCopyLinkToClipboard(); + break; + + case OpenImageInNewWindow: + text = contextMenuItemTagOpenImageInNewWindow(); + break; + case DownloadImageToDisk: + text = contextMenuItemTagDownloadImageToDisk(); + break; + case CopyImageToClipboard: + text = contextMenuItemTagCopyImageToClipboard(); + break; + + case GoBack: + text = contextMenuItemTagGoBack(); + break; + case GoForward: + text = contextMenuItemTagGoForward(); + break; + case Stop: + text = contextMenuItemTagStop(); + break; + case Reload: + text = contextMenuItemTagReload(); + break; + + case Cut: + text = contextMenuItemTagCut(); + break; + case Copy: + text = contextMenuItemTagCopy(); + break; + case Paste: + text = contextMenuItemTagPaste(); + break; + + case Undo: { + QAction *a = undoStack()->createUndoAction(d->q); + d->actions[action] = a; + return a; + } + case Redo: { + QAction *a = undoStack()->createRedoAction(d->q); + d->actions[action] = a; + return a; + } + case MoveToNextChar: + case MoveToPreviousChar: + case MoveToNextWord: + case MoveToPreviousWord: + case MoveToNextLine: + case MoveToPreviousLine: + case MoveToStartOfLine: + case MoveToEndOfLine: + case MoveToStartOfBlock: + case MoveToEndOfBlock: + case MoveToStartOfDocument: + case MoveToEndOfDocument: + case SelectNextChar: + case SelectPreviousChar: + case SelectNextWord: + case SelectPreviousWord: + case SelectNextLine: + case SelectPreviousLine: + case SelectStartOfLine: + case SelectEndOfLine: + case SelectStartOfBlock: + case SelectEndOfBlock: + case SelectStartOfDocument: + case SelectEndOfDocument: + case DeleteStartOfWord: + case DeleteEndOfWord: + break; // #### + + case SetTextDirectionDefault: + text = contextMenuItemTagDefaultDirection(); + break; + case SetTextDirectionLeftToRight: + text = contextMenuItemTagLeftToRight(); + checkable = true; + break; + case SetTextDirectionRightToLeft: + text = contextMenuItemTagRightToLeft(); + checkable = true; + break; + + case ToggleBold: + text = contextMenuItemTagBold(); + checkable = true; + break; + case ToggleItalic: + text = contextMenuItemTagItalic(); + checkable = true; + break; + case ToggleUnderline: + text = contextMenuItemTagUnderline(); + checkable = true; + break; + + case InspectElement: + text = contextMenuItemTagInspectElement(); + break; + + case NoWebAction: + return 0; + } + + if (text.isEmpty()) + return 0; + + QAction *a = new QAction(d->q); + a->setText(text); + a->setData(action); + a->setCheckable(checkable); + + connect(a, SIGNAL(triggered(bool)), + this, SLOT(_q_webActionTriggered(bool))); + + d->actions[action] = a; + d->updateAction(action); + return a; +} + +/*! + \property QWebPage::modified + + Specifies if the page contains unsubmitted form data. +*/ +bool QWebPage::isModified() const +{ + return d->modified; +} + + +/*! + Returns a pointer to the undo stack used for editable content. +*/ +QUndoStack *QWebPage::undoStack() const +{ + if (!d->undoStack) + d->undoStack = new QUndoStack(const_cast<QWebPage *>(this)); + + return d->undoStack; +} + +/*! \reimp +*/ +bool QWebPage::event(QEvent *ev) +{ + switch (ev->type()) { + case QEvent::MouseMove: + d->mouseMoveEvent(static_cast<QMouseEvent*>(ev)); + break; + case QEvent::MouseButtonPress: + d->mousePressEvent(static_cast<QMouseEvent*>(ev)); + break; + case QEvent::MouseButtonDblClick: + d->mouseDoubleClickEvent(static_cast<QMouseEvent*>(ev)); + break; + case QEvent::MouseButtonRelease: + d->mouseReleaseEvent(static_cast<QMouseEvent*>(ev)); + break; + case QEvent::ContextMenu: + d->contextMenuEvent(static_cast<QContextMenuEvent*>(ev)); + break; + case QEvent::Wheel: + d->wheelEvent(static_cast<QWheelEvent*>(ev)); + break; + case QEvent::KeyPress: + d->keyPressEvent(static_cast<QKeyEvent*>(ev)); + break; + case QEvent::KeyRelease: + d->keyReleaseEvent(static_cast<QKeyEvent*>(ev)); + break; + case QEvent::FocusIn: + d->focusInEvent(static_cast<QFocusEvent*>(ev)); + break; + case QEvent::FocusOut: + d->focusOutEvent(static_cast<QFocusEvent*>(ev)); + break; +#ifndef QT_NO_DRAGANDDROP + case QEvent::DragEnter: + d->dragEnterEvent(static_cast<QDragEnterEvent*>(ev)); + break; + case QEvent::DragLeave: + d->dragLeaveEvent(static_cast<QDragLeaveEvent*>(ev)); + break; + case QEvent::DragMove: + d->dragMoveEvent(static_cast<QDragMoveEvent*>(ev)); + break; + case QEvent::Drop: + d->dropEvent(static_cast<QDropEvent*>(ev)); + break; +#endif + default: + return QObject::event(ev); + } + + return true; +} + +/*! + Similar to QWidget::focusNextPrevChild it focuses the next focusable web element + if \a next is true. Otherwise the previous element is focused. +*/ +bool QWebPage::focusNextPrevChild(bool next) +{ + QKeyEvent ev(QEvent::KeyPress, Qt::Key_Tab, Qt::KeyboardModifiers(next ? Qt::NoModifier : Qt::ShiftModifier)); + d->keyPressEvent(&ev); + bool hasFocusedNode = false; + Frame *frame = d->page->focusController()->focusedFrame(); + if (frame) { + Document *document = frame->document(); + hasFocusedNode = document && document->focusedNode(); + } + //qDebug() << "focusNextPrevChild(" << next << ") =" << ev.isAccepted() << "focusedNode?" << hasFocusedNode; + return hasFocusedNode; +} + +/*! + Returns a pointe to the page's settings object. +*/ +QWebSettings *QWebPage::settings() +{ + return d->settings; +} + +/*! + This function is called when the web content requests a file name, for example + as a result of the user clicking on a "file upload" button in a HTML form. +*/ +QString QWebPage::chooseFile(QWebFrame *parentFrame, const QString& oldFile) +{ +#ifndef QT_NO_FILEDIALOG + return QFileDialog::getOpenFileName(d->view, QString::null, oldFile); +#else + return QString::null; +#endif +} + +#if QT_VERSION < 0x040400 + +void QWebPage::setNetworkInterface(QWebNetworkInterface *interface) +{ + d->networkInterface = interface; +} + +QWebNetworkInterface *QWebPage::networkInterface() const +{ + if (d->networkInterface) + return d->networkInterface; + else + return QWebNetworkInterface::defaultInterface(); +} + +#ifndef QT_NO_NETWORKPROXY +void QWebPage::setNetworkProxy(const QNetworkProxy& proxy) +{ + d->networkProxy = proxy; +} + +QNetworkProxy QWebPage::networkProxy() const +{ + return d->networkProxy; +} +#endif + +#else + +/*! + Sets the QNetworkAccessManager \a manager that is responsible for serving network + requests for this QWebPage. + + \sa networkAccessManager +*/ +void QWebPage::setNetworkAccessManager(QNetworkAccessManager *manager) +{ + if (manager == d->networkManager) + return; + delete d->networkManager; + d->networkManager = manager; +} + +/*! + Returns the QNetworkAccessManager \a manager that is responsible for serving network + requests for this QWebPage. + + \sa setNetworkAccessManager +*/ +QNetworkAccessManager *QWebPage::networkAccessManager() const +{ + if (!d->networkManager) { + QWebPage *that = const_cast<QWebPage *>(this); + that->d->networkManager = new QNetworkAccessManager(that); + } + return d->networkManager; +} + +#endif + +/*! + This function is called when a user agent for HTTP requests is needed. You can re-implement this + function to dynamically return different user agent's for different urls, based on the \a url parameter. +*/ +QString QWebPage::userAgentFor(const QUrl& url) const +{ + Q_UNUSED(url) + return QLatin1String("Mozilla/5.0 (Macintosh; U; Intel Mac OS X; en) AppleWebKit/523.15 (KHTML, like Gecko) Safari/419.3 Qt"); +} + + +void QWebPagePrivate::_q_onLoadProgressChanged(int) { + m_totalBytes = page->progress()->totalPageAndResourceBytesToLoad(); + m_bytesReceived = page->progress()->totalBytesReceived(); +} + + +/*! + Returns the total number of bytes that were received from the network to render the current page, + including extra content such as embedded images. +*/ +quint64 QWebPage::totalBytes() const { + return d->m_bytesReceived; +} + + +/*! + Returns the number of bytes that were received from the network to render the current page. +*/ +quint64 QWebPage::bytesReceived() const { + return d->m_totalBytes; +} + +QWebPageContext::QWebPageContext(const WebCore::HitTestResult &hitTest) + : d(new QWebPageContextPrivate) +{ + d->pos = hitTest.point(); + d->text = hitTest.textContent(); + d->linkUrl = hitTest.absoluteLinkURL().string(); + d->imageUrl = hitTest.absoluteImageURL().string(); + d->innerNonSharedNode = hitTest.innerNonSharedNode(); + WebCore::Image *img = hitTest.image(); + if (img) { + QPixmap *pix = img->getPixmap(); + if (pix) + d->image = *pix; + } + WebCore::Frame *frame = hitTest.targetFrame(); + if (frame) + d->targetFrame = frame->view()->qwebframe(); +} + +QWebPageContext::QWebPageContext() + : d(0) +{ +} + +QWebPageContext::QWebPageContext(const QWebPageContext &other) + : d(0) +{ + if (other.d) + d = new QWebPageContextPrivate(*other.d); +} + +QWebPageContext &QWebPageContext::operator=(const QWebPageContext &other) +{ + if (this != &other) { + if (other.d) { + if (!d) + d = new QWebPageContextPrivate; + *d = *other.d; + } else { + delete d; + d = 0; + } + } + return *this; +} + +QWebPageContext::~QWebPageContext() +{ + delete d; +} + +QPoint QWebPageContext::pos() const +{ + if (!d) + return QPoint(); + return d->pos; +} + +QString QWebPageContext::text() const +{ + if (!d) + return QString(); + return d->text; +} + +QUrl QWebPageContext::linkUrl() const +{ + if (!d) + return QUrl(); + return d->linkUrl; +} + +QUrl QWebPageContext::imageUrl() const +{ + if (!d) + return QUrl(); + return d->linkUrl; +} + +QPixmap QWebPageContext::image() const +{ + if (!d) + return QPixmap(); + return d->image; +} + +QWebFrame *QWebPageContext::targetFrame() const +{ + if (!d) + return 0; + return d->targetFrame; +} + +/*! + \fn void QWebPage::loadProgressChanged(int progress) + + This signal is emitted when the global progress status changes. + The current value is provided by \a progress in percent. + It accumulates changes from all the child frames. +*/ + +/*! + \fn void QWebPage::hoveringOverLink(const QString &link, const QString &title, const QString &textContent) + + This signal is emitted when the mouse is hovering over a link. + The first parameter is the \a link url, the second is the link \a title + if any, and third \a textContent is the text content. Method is emitter with both + empty parameters when the mouse isn't hovering over any link element. +*/ + +/*! + \fn void QWebPage::statusBarTextChanged(const QString& text) + + This signal is emitted when the statusbar \a text is changed by the page. +*/ + +/*! + \fn void QWebPage::frameCreated(QWebFrame *frame) + + This signal is emitted whenever the page creates a new \a frame. +*/ + +/*! + \fn void QWebPage::selectionChanged() + + This signal is emitted whenever the selection changes. +*/ + +/*! + \fn void QWebPage::geometryChangeRequest(const QRect& geom) + + This signal is emitted whenever the document wants to change the position and size of the + page to \a geom. This can happen for example through JavaScript. +*/ + +/*! + \fn void QWebPage::handleUnsupportedContent(QNetworkReply *reply) + + This signals is emitted when webkit cannot handle a link the user navigated to. + + At signal emissions time the meta data of the QNetworkReply is available. +*/ + +/*! + \fn void QWebPage::download(const QNetworkRequest &request) + + This signals is emitted when the user decides to download a link. +*/ + +#include "moc_qwebpage.cpp" diff --git a/WebKit/qt/Api/qwebpage.h b/WebKit/qt/Api/qwebpage.h new file mode 100644 index 0000000..e76f935 --- /dev/null +++ b/WebKit/qt/Api/qwebpage.h @@ -0,0 +1,242 @@ +/* + Copyright (C) 2007 Trolltech ASA + Copyright (C) 2007 Staikos Computing Services Inc. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. + + This class provides all functionality needed for loading images, style sheets and html + pages from the web. It has a memory cache for these objects. +*/ + +#ifndef QWEBPAGE_H +#define QWEBPAGE_H + +#include "qwebsettings.h" +#include "qwebkitglobal.h" + +#include <QtCore/qobject.h> +#include <QtGui/qwidget.h> +class QNetworkProxy; +class QUndoStack; +class QUrl; +class QWebFrame; +class QWebNetworkRequest; +class QNetworkRequest; +class QNetworkReply; +class QNetworkAccessManager; +class QWebHistory; + +class QWebPagePrivate; +class QWebFrameData; +class QWebNetworkInterface; + +namespace WebCore { + class ChromeClientQt; + class EditorClientQt; + class FrameLoaderClientQt; + class FrameLoadRequest; + class InspectorClientQt; + class ResourceHandle; + class HitTestResult; +} + +class QWEBKIT_EXPORT QWebPage : public QObject +{ + Q_OBJECT + + Q_PROPERTY(bool modified READ isModified) + Q_PROPERTY(QString selectedText READ selectedText) + Q_PROPERTY(QSize viewportSize READ viewportSize WRITE setViewportSize) +public: + enum NavigationRequestResponse { + AcceptNavigationRequest, + IgnoreNavigationRequest + }; + + enum NavigationType { + NavigationTypeLinkClicked, + NavigationTypeFormSubmitted, + NavigationTypeBackForward, + NavigationTypeReload, + NavigationTypeFormResubmitted, + NavigationTypeOther + }; + + enum WebAction { + NoWebAction = - 1, + + OpenLink, + + OpenLinkInNewWindow, + OpenFrameInNewWindow, + + DownloadLinkToDisk, + CopyLinkToClipboard, + + OpenImageInNewWindow, + DownloadImageToDisk, + CopyImageToClipboard, + + GoBack, // ###GoBackward instead? + GoForward, + Stop, + Reload, + + Cut, + Copy, + Paste, + + Undo, + Redo, + MoveToNextChar, + MoveToPreviousChar, + MoveToNextWord, + MoveToPreviousWord, + MoveToNextLine, + MoveToPreviousLine, + MoveToStartOfLine, + MoveToEndOfLine, + MoveToStartOfBlock, + MoveToEndOfBlock, + MoveToStartOfDocument, + MoveToEndOfDocument, + SelectNextChar, + SelectPreviousChar, + SelectNextWord, + SelectPreviousWord, + SelectNextLine, + SelectPreviousLine, + SelectStartOfLine, + SelectEndOfLine, + SelectStartOfBlock, + SelectEndOfBlock, + SelectStartOfDocument, + SelectEndOfDocument, + DeleteStartOfWord, + DeleteEndOfWord, + + SetTextDirectionDefault, + SetTextDirectionLeftToRight, + SetTextDirectionRightToLeft, + + ToggleBold, + ToggleItalic, + ToggleUnderline, + + InspectElement, + + WebActionCount + }; + + + explicit QWebPage(QObject *parent = 0); + ~QWebPage(); + + QWebFrame *mainFrame() const; + QWebFrame *currentFrame() const; + + QWebHistory *history() const; + + QWebSettings *settings(); + + void setView(QWidget *view); + QWidget *view() const; + + bool isModified() const; + QUndoStack *undoStack() const; + +#if QT_VERSION < 0x040400 + void setNetworkInterface(QWebNetworkInterface *interface); + QWebNetworkInterface *networkInterface() const; + + // #### why is this in the page itself? +#ifndef QT_NO_NETWORKPROXY + void setNetworkProxy(const QNetworkProxy& proxy); + QNetworkProxy networkProxy() const; +#endif + +#else + void setNetworkAccessManager(QNetworkAccessManager *manager); + QNetworkAccessManager *networkAccessManager() const; +#endif + + quint64 totalBytes() const; + quint64 bytesReceived() const; + + QString selectedText() const; + + QAction *action(WebAction action) const; + virtual void triggerAction(WebAction action, bool checked = false); + + QSize viewportSize() const; + void setViewportSize(const QSize &size) const; + + virtual bool event(QEvent*); + virtual bool focusNextPrevChild(bool next); + +Q_SIGNALS: + void loadProgressChanged(int progress); + void hoveringOverLink(const QString &link, const QString &title, const QString &textContent = QString()); + void statusBarTextChanged(const QString& text); + void selectionChanged(); + void frameCreated(QWebFrame *frame); + void geometryChangeRequest(const QRect& geom); + +#if QT_VERSION >= 0x040400 + void handleUnsupportedContent(QNetworkReply *reply); + void download(const QNetworkRequest &request); +#endif + + //void addEmbeddableWidget(QWidget *widget); + //void addEmbeddableWidget(const QString &classid, QWidget *widget); + //void removeEmbeddableWidget(QWidget *widget); + //QHash<QString, QWidget *> embeddableWidgets() const; + //void clearEmbeddableWidgets(); + +protected: + virtual QWebPage *createWindow(); + virtual QWebPage *createModalDialog(); + virtual QObject *createPlugin(const QString &classid, const QUrl &url, const QStringList ¶mNames, const QStringList ¶mValues); + +#if QT_VERSION < 0x040400 + virtual NavigationRequestResponse navigationRequested(QWebFrame *frame, const QWebNetworkRequest &request, NavigationType type); +#else + virtual NavigationRequestResponse navigationRequested(QWebFrame *frame, const QNetworkRequest &request, NavigationType type); +#endif + virtual QString chooseFile(QWebFrame *originatingFrame, const QString& oldFile); + virtual void javaScriptAlert(QWebFrame *originatingFrame, const QString& msg); + virtual bool javaScriptConfirm(QWebFrame *originatingFrame, const QString& msg); + virtual bool javaScriptPrompt(QWebFrame *originatingFrame, const QString& msg, const QString& defaultValue, QString* result); + virtual void javaScriptConsoleMessage(const QString& message, unsigned int lineNumber, const QString& sourceID); + + virtual QString userAgentFor(const QUrl& url) const; + +private: + Q_PRIVATE_SLOT(d, void _q_onLoadProgressChanged(int)) + Q_PRIVATE_SLOT(d, void _q_webActionTriggered(bool checked)); + friend class QWebFrame; + friend class QWebPagePrivate; + friend class WebCore::ChromeClientQt; + friend class WebCore::EditorClientQt; + friend class WebCore::FrameLoaderClientQt; + friend class WebCore::InspectorClientQt; + friend class WebCore::ResourceHandle; + QWebPagePrivate *d; +}; + + + +#endif diff --git a/WebKit/qt/Api/qwebpage_p.h b/WebKit/qt/Api/qwebpage_p.h new file mode 100644 index 0000000..80b1e29 --- /dev/null +++ b/WebKit/qt/Api/qwebpage_p.h @@ -0,0 +1,159 @@ +/* + Copyright (C) 2007 Trolltech ASA + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. + + This class provides all functionality needed for loading images, style sheets and html + pages from the web. It has a memory cache for these objects. +*/ +#ifndef QWEBPAGE_P_H +#define QWEBPAGE_P_H + +#include <qnetworkproxy.h> +#include <qpointer.h> + +#include "qwebpage.h" +#include "qwebhistory.h" +#include "qwebframe.h" + +#include "KURL.h" +#include "PlatformString.h" + +#include <wtf/RefPtr.h> + +namespace WebCore +{ + class ChromeClientQt; + class ContextMenuClientQt; + class ContextMenuItem; + class ContextMenu; + class EditorClientQt; + class Element; + class Node; + class Page; +} + +class QUndoStack; +class QMenu; + +class QWebPageContextPrivate +{ +public: + QPoint pos; + QString text; + QUrl linkUrl; + QUrl imageUrl; + QPixmap image; + QPointer<QWebFrame> targetFrame; + RefPtr<WebCore::Node> innerNonSharedNode; +}; + +class QWebPageContext +{ +public: + QWebPageContext(); + QWebPageContext(const QWebPageContext &other); + QWebPageContext &operator=(const QWebPageContext &other); + ~QWebPageContext(); + + QPoint pos() const; + QString text() const; + QUrl linkUrl() const; + QUrl imageUrl() const; + // ### we have a pixmap internally, should this be called pixmap() instead? + QPixmap image() const; + + QWebFrame *targetFrame() const; + +private: + QWebPageContext(const WebCore::HitTestResult &hitTest); + QWebPageContextPrivate *d; + + friend class QWebPage; + friend class QWebPagePrivate; +}; + +class QWebPagePrivate +{ +public: + QWebPagePrivate(QWebPage *); + ~QWebPagePrivate(); + void createMainFrame(); + QMenu *createContextMenu(const WebCore::ContextMenu *webcoreMenu, const QList<WebCore::ContextMenuItem> *items); + + QWebFrame *frameAt(const QPoint &pos) const; + + void _q_onLoadProgressChanged(int); + void _q_webActionTriggered(bool checked); + void updateAction(QWebPage::WebAction action); + void updateNavigationActions(); + void updateEditorActions(); + + void mouseMoveEvent(QMouseEvent*); + void mousePressEvent(QMouseEvent*); + void mouseDoubleClickEvent(QMouseEvent*); + void mouseReleaseEvent(QMouseEvent*); + void contextMenuEvent(QContextMenuEvent*); + void wheelEvent(QWheelEvent*); + void keyPressEvent(QKeyEvent*); + void keyReleaseEvent(QKeyEvent*); + void focusInEvent(QFocusEvent*); + void focusOutEvent(QFocusEvent*); + + void dragEnterEvent(QDragEnterEvent *); + void dragLeaveEvent(QDragLeaveEvent *); + void dragMoveEvent(QDragMoveEvent *); + void dropEvent(QDropEvent *); + + + WebCore::ChromeClientQt *chromeClient; + WebCore::ContextMenuClientQt *contextMenuClient; + WebCore::EditorClientQt *editorClient; + WebCore::Page *page; + + QPointer<QWebFrame> mainFrame; + + QWebPage *q; + QUndoStack *undoStack; + QWidget *view; + + bool modified; + + bool insideOpenCall; + quint64 m_totalBytes; + quint64 m_bytesReceived; + +#if QT_VERSION < 0x040400 + QWebPage::NavigationRequestResponse navigationRequested(QWebFrame *frame, const QWebNetworkRequest &request, QWebPage::NavigationType type); + + QWebNetworkInterface *networkInterface; +#ifndef QT_NO_NETWORKPROXY + QNetworkProxy networkProxy; +#endif + +#else + QWebPage::NavigationRequestResponse navigationRequested(QWebFrame *frame, const QNetworkRequest &request, QWebPage::NavigationType type); + QNetworkAccessManager *networkManager; +#endif + + QWebHistory history; + QWebPageContext currentContext; + QWebSettings *settings; + + QAction *actions[QWebPage::WebActionCount]; +}; + +#endif diff --git a/WebKit/qt/Api/qwebsettings.cpp b/WebKit/qt/Api/qwebsettings.cpp new file mode 100644 index 0000000..8109de1 --- /dev/null +++ b/WebKit/qt/Api/qwebsettings.cpp @@ -0,0 +1,384 @@ +/* + Copyright (C) 2007 Trolltech ASA + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. + + This class provides all functionality needed for loading images, style sheets and html + pages from the web. It has a memory cache for these objects. +*/ + +#include "config.h" +#include "qwebsettings.h" + +#include "qwebpage.h" +#include "qwebpage_p.h" + +#include "Page.h" +#include "Settings.h" +#include "KURL.h" +#include "PlatformString.h" +#include "IconDatabase.h" + +#include <QHash> +#include <QSharedData> +#include <QUrl> +#include <QFileInfo> + +class QWebSettingsPrivate +{ +public: + QWebSettingsPrivate(WebCore::Settings *wcSettings = 0) + : settings(wcSettings) + { + } + + QHash<int, QString> fontFamilies; + QHash<int, int> fontSizes; + QHash<int, bool> attributes; + QUrl userStyleSheetLocation; + + void apply(); + WebCore::Settings *settings; +}; + +typedef QHash<int, QPixmap> WebGraphicHash; +Q_GLOBAL_STATIC(WebGraphicHash, graphics) + +Q_GLOBAL_STATIC(QList<QWebSettingsPrivate *>, allSettings); + +void QWebSettingsPrivate::apply() +{ + if (settings) { + QWebSettingsPrivate *global = QWebSettings::defaultSettings()->d; + + QString family = fontFamilies.value(QWebSettings::StandardFont, + global->fontFamilies.value(QWebSettings::StandardFont)); + settings->setStandardFontFamily(family); + + family = fontFamilies.value(QWebSettings::FixedFont, + global->fontFamilies.value(QWebSettings::FixedFont)); + settings->setFixedFontFamily(family); + + family = fontFamilies.value(QWebSettings::SerifFont, + global->fontFamilies.value(QWebSettings::SerifFont)); + settings->setSerifFontFamily(family); + + family = fontFamilies.value(QWebSettings::SansSerifFont, + global->fontFamilies.value(QWebSettings::SansSerifFont)); + settings->setSansSerifFontFamily(family); + + family = fontFamilies.value(QWebSettings::CursiveFont, + global->fontFamilies.value(QWebSettings::CursiveFont)); + settings->setCursiveFontFamily(family); + + family = fontFamilies.value(QWebSettings::FantasyFont, + global->fontFamilies.value(QWebSettings::FantasyFont)); + settings->setFantasyFontFamily(family); + + int size = fontSizes.value(QWebSettings::MinimumFontSize, + global->fontSizes.value(QWebSettings::MinimumFontSize)); + settings->setMinimumFontSize(size); + + size = fontSizes.value(QWebSettings::MinimumLogicalFontSize, + global->fontSizes.value(QWebSettings::MinimumLogicalFontSize)); + settings->setMinimumLogicalFontSize(size); + + size = fontSizes.value(QWebSettings::DefaultFontSize, + global->fontSizes.value(QWebSettings::DefaultFontSize)); + settings->setDefaultFontSize(size); + + size = fontSizes.value(QWebSettings::DefaultFixedFontSize, + global->fontSizes.value(QWebSettings::DefaultFixedFontSize)); + settings->setDefaultFixedFontSize(size); + + bool value = attributes.value(QWebSettings::AutoLoadImages, + global->attributes.value(QWebSettings::AutoLoadImages)); + settings->setLoadsImagesAutomatically(value); + + value = attributes.value(QWebSettings::JavascriptEnabled, + global->attributes.value(QWebSettings::JavascriptEnabled)); + settings->setJavaScriptEnabled(value); + + value = attributes.value(QWebSettings::JavascriptCanOpenWindows, + global->attributes.value(QWebSettings::JavascriptCanOpenWindows)); + settings->setJavaScriptCanOpenWindowsAutomatically(value); + + value = attributes.value(QWebSettings::JavaEnabled, + global->attributes.value(QWebSettings::JavaEnabled)); + settings->setJavaEnabled(value); + + value = attributes.value(QWebSettings::PluginsEnabled, + global->attributes.value(QWebSettings::PluginsEnabled)); + settings->setPluginsEnabled(value); + + value = attributes.value(QWebSettings::PrivateBrowsingEnabled, + global->attributes.value(QWebSettings::PrivateBrowsingEnabled)); + settings->setPrivateBrowsingEnabled(value); + + value = attributes.value(QWebSettings::JavascriptCanAccessClipboard, + global->attributes.value(QWebSettings::JavascriptCanAccessClipboard)); + settings->setDOMPasteAllowed(value); + + value = attributes.value(QWebSettings::DeveloperExtrasEnabled, + global->attributes.value(QWebSettings::DeveloperExtrasEnabled)); + settings->setDeveloperExtrasEnabled(value); + + QUrl location = !userStyleSheetLocation.isEmpty() ? userStyleSheetLocation : global->userStyleSheetLocation; + settings->setUserStyleSheetLocation(WebCore::KURL(location)); + } else { + QList<QWebSettingsPrivate *> settings = *::allSettings(); + for (int i = 0; i < settings.count(); ++i) + settings[i]->apply(); + } +} + +/*! + Returns the global default settings object. + + Any setting changed on the default object is automatically applied to all + QWebPage instances where the particular setting is not overriden already. +*/ +QWebSettings *QWebSettings::defaultSettings() +{ + static QWebSettings *global = 0; + if (!global) + global = new QWebSettings; + return global; +} + +/*! + \internal +*/ +QWebSettings::QWebSettings() + : d(new QWebSettingsPrivate) +{ + // Initialize our global defaults + // changing any of those will likely break the LayoutTests + d->fontSizes.insert(QWebSettings::MinimumFontSize, 5); + d->fontSizes.insert(QWebSettings::MinimumLogicalFontSize, 5); + d->fontSizes.insert(QWebSettings::DefaultFontSize, 14); + d->fontSizes.insert(QWebSettings::DefaultFixedFontSize, 14); + d->fontFamilies.insert(QWebSettings::StandardFont, QLatin1String("Arial")); + d->fontFamilies.insert(QWebSettings::FixedFont, QLatin1String("Courier New")); + d->fontFamilies.insert(QWebSettings::SerifFont, QLatin1String("Times New Roman")); + d->fontFamilies.insert(QWebSettings::SansSerifFont, QLatin1String("Arial")); + d->fontFamilies.insert(QWebSettings::CursiveFont, QLatin1String("Arial")); + d->fontFamilies.insert(QWebSettings::FantasyFont, QLatin1String("Arial")); + + d->attributes.insert(QWebSettings::AutoLoadImages, true); + d->attributes.insert(QWebSettings::JavascriptEnabled, true); + d->attributes.insert(QWebSettings::LinksIncludedInFocusChain, true); +} + +/*! + \internal +*/ +QWebSettings::QWebSettings(WebCore::Settings *settings) + : d(new QWebSettingsPrivate(settings)) +{ + d->settings = settings; + d->apply(); + allSettings()->append(d); +} + +/*! + \internal +*/ +QWebSettings::~QWebSettings() +{ + if (d->settings) + allSettings()->removeAll(d); + + delete d; +} + +/*! + Sets the font size for \a type to \a size. +*/ +void QWebSettings::setFontSize(FontSize type, int size) +{ + d->fontSizes.insert(type, size); + d->apply(); +} + +/*! + Returns the default font size for \a type. +*/ +int QWebSettings::fontSize(FontSize type) const +{ + int defaultValue = 0; + if (d->settings) { + QWebSettingsPrivate *global = QWebSettings::defaultSettings()->d; + defaultValue = global->fontSizes.value(type); + } + return d->fontSizes.value(type, defaultValue); +} + +/*! + Resets the font size for \a type to the size specified in the default settings object. + + This function has not effect on the default QWebSettings instance. +*/ +void QWebSettings::resetFontSize(FontSize type) +{ + if (d->settings) { + d->fontSizes.remove(type); + d->apply(); + } +} + +/*! + Specifies the location of a user stylesheet to load with every web page. + + The location can be a URL as well as a path on the local filesystem. + + \sa userStyleSheetLocation +*/ +void QWebSettings::setUserStyleSheetLocation(const QUrl &location) +{ + d->userStyleSheetLocation = location; + d->apply(); +} + +/*! + Returns the location of the user stylesheet. + + \sa setUserStyleSheetLocation +*/ +QUrl QWebSettings::userStyleSheetLocation() const +{ + return d->userStyleSheetLocation; +} + +/*! + Enables or disables the icon database. The icon database is used to store favicons + associated with web sites. + + If \a enabled is true then \a location must be specified and point to an existing directory + where the icons are stored. +*/ +void QWebSettings::setIconDatabaseEnabled(bool enabled, const QString &location) +{ + WebCore::iconDatabase()->setEnabled(enabled); + if (enabled) { + QFileInfo info(location); + if (info.isDir() && info.isWritable()) + WebCore::iconDatabase()->open(location); + } else { + WebCore::iconDatabase()->close(); + } +} + +/*! + Returns whether the icon database is enabled or not. + + \sa setIconDatabaseEnabled +*/ +bool QWebSettings::iconDatabaseEnabled() +{ + return WebCore::iconDatabase()->isEnabled() && WebCore::iconDatabase()->isOpen(); +} + +/*! + Sets \a graphic to be drawn when QtWebKit needs to drawn an image of the given \a type. +*/ +void QWebSettings::setWebGraphic(WebGraphic type, const QPixmap &graphic) +{ + WebGraphicHash *h = graphics(); + if (graphic.isNull()) + h->remove(type); + else + h->insert(type, graphic); +} + +/*! + Returns a previously set pixmap that is used to draw replacement graphics of the specified \a type. +*/ +QPixmap QWebSettings::webGraphic(WebGraphic type) +{ + return graphics()->value(type); +} + +/*! + Sets the default font family to \a family for the specified \a type of font. +*/ +void QWebSettings::setFontFamily(FontType type, const QString &family) +{ + d->fontFamilies.insert(type, family); + d->apply(); +} + +/*! + Returns the default font family to \a family for the specified \a type of font. +*/ +QString QWebSettings::fontFamily(FontType type) const +{ + QString defaultValue; + if (d->settings) { + QWebSettingsPrivate *global = QWebSettings::defaultSettings()->d; + defaultValue = global->fontFamilies.value(type); + } + return d->fontFamilies.value(type, defaultValue); +} + +/*! + Resets the font family for specified \a type of fonts in a web page to the default. + + This function has not effect on the default QWebSettings instance. +*/ +void QWebSettings::resetFontFamily(FontType type) +{ + if (d->settings) { + d->fontFamilies.remove(type); + d->apply(); + } +} + +/*! + Enables or disables the specified \a attr feature depending on the value of \a on. +*/ +void QWebSettings::setAttribute(WebAttribute attr, bool on) +{ + d->attributes.insert(attr, on); + d->apply(); +} + +/*! + Returns true if \a attr is enabled; false otherwise. +*/ +bool QWebSettings::testAttribute(WebAttribute attr) const +{ + bool defaultValue = false; + if (d->settings) { + QWebSettingsPrivate *global = QWebSettings::defaultSettings()->d; + defaultValue = global->attributes.value(attr); + } + return d->attributes.value(attr, defaultValue); +} + +/*! + Clears the setting of \a attr. The global default for \a attr will be used instead. + + This function has not effect on the default QWebSettings instance. +*/ +void QWebSettings::clearAttribute(WebAttribute attr) +{ + if (d->settings) { + d->attributes.remove(attr); + d->apply(); + } +} + diff --git a/WebKit/qt/Api/qwebsettings.h b/WebKit/qt/Api/qwebsettings.h new file mode 100644 index 0000000..c071e51 --- /dev/null +++ b/WebKit/qt/Api/qwebsettings.h @@ -0,0 +1,112 @@ +/* + Copyright (C) 2007 Trolltech ASA + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. + + This class provides all functionality needed for loading images, style sheets and html + pages from the web. It has a memory cache for these objects. +*/ + +#ifndef QWEBSETTINGS_H +#define QWEBSETTINGS_H + +#include <qwebkitglobal.h> + +#include <QtCore/qstring.h> +#include <QtGui/qpixmap.h> +#include <QtCore/qshareddata.h> + +namespace WebCore +{ + class Settings; +}; + +class QWebPage; +class QWebSettingsPrivate; +class QUrl; + +class QWEBKIT_EXPORT QWebSettings +{ +public: + enum FontType { + StandardFont, + FixedFont, + SerifFont, + SansSerifFont, + CursiveFont, + FantasyFont + }; + enum WebAttribute { + AutoLoadImages, + JavascriptEnabled, + JavaEnabled, + PluginsEnabled, + PrivateBrowsingEnabled, + JavascriptCanOpenWindows, + JavascriptCanAccessClipboard, + DeveloperExtrasEnabled, + LinksIncludedInFocusChain + }; + enum WebGraphic { + MissingImageGraphic, + MissingPluginGraphic, + DefaultFaviconGraphic, + TextAreaResizeCornerGraphic + }; + enum FontSize { + MinimumFontSize, + MinimumLogicalFontSize, + DefaultFontSize, + DefaultFixedFontSize + }; + + static QWebSettings *defaultSettings(); + + void setFontFamily(FontType type, const QString &family); + QString fontFamily(FontType type) const; + void resetFontFamily(FontType type); + + void setFontSize(FontSize type, int size); + int fontSize(FontSize type) const; + void resetFontSize(FontSize type); + + void setAttribute(WebAttribute attr, bool on = true); + bool testAttribute(WebAttribute attr) const; + void clearAttribute(WebAttribute attr); + + void setUserStyleSheetLocation(const QUrl &location); + QUrl userStyleSheetLocation() const; + + static void setIconDatabaseEnabled(bool enabled, const QString &location = QString()); + static bool iconDatabaseEnabled(); + + static void setWebGraphic(WebGraphic type, const QPixmap &graphic); + static QPixmap webGraphic(WebGraphic type); + +private: + friend class QWebPagePrivate; + friend class QWebSettingsPrivate; + + Q_DISABLE_COPY(QWebSettings) + + QWebSettings(); + QWebSettings(WebCore::Settings *settings); + ~QWebSettings(); + + QWebSettingsPrivate *d; +}; + +#endif diff --git a/WebKit/qt/Api/qwebview.cpp b/WebKit/qt/Api/qwebview.cpp new file mode 100644 index 0000000..3d67437 --- /dev/null +++ b/WebKit/qt/Api/qwebview.cpp @@ -0,0 +1,593 @@ +/* + Copyright (C) 2007 Trolltech ASA + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include "config.h" +#include "qwebview.h" +#include "qwebframe.h" +#include "qevent.h" +#include "qpainter.h" + +class QWebViewPrivate +{ +public: + QWebPage *page; +}; + +/*! + \class QWebView + \since 4.4 + \brief The QWebView class provides a widget that is used to view and edit web documents. + + QWebView is the main widget component of the QtWebKit web browsing module. +*/ + +/*! + Constructs an empty QWebView with parent \a parent. +*/ +QWebView::QWebView(QWidget *parent) + : QWidget(parent) +{ + d = new QWebViewPrivate; + d->page = 0; + + QPalette pal = palette(); + pal.setBrush(QPalette::Background, Qt::white); + + setAttribute(Qt::WA_OpaquePaintEvent); + + setPalette(pal); + setAcceptDrops(true); + + setMouseTracking(true); + setFocusPolicy(Qt::WheelFocus); +} + +/*! + Destructor. +*/ +QWebView::~QWebView() +{ + if (d->page && d->page->parent() == this) + delete d->page; + delete d; +} + +/*! + Returns a pointer to the underlying web page. + + \sa setPage() +*/ +QWebPage *QWebView::page() const +{ + if (!d->page) { + QWebView *that = const_cast<QWebView *>(this); + that->setPage(new QWebPage(that)); + } + return d->page; +} + +/*! + Makes \a page the new web page of the web view. + + The parent QObject of the provided page remains the owner + of the object. If the current document is a child of the web + view, then it is deleted. + + \sa page() +*/ +void QWebView::setPage(QWebPage *page) +{ + if (d->page == page) + return; + if (d->page) { + if (d->page->parent() == this) { + delete d->page; + } else { + d->page->disconnect(this); + } + } + d->page = page; + if (d->page) { + d->page->setView(this); + // #### connect signals + QWebFrame *mainFrame = d->page->mainFrame(); + connect(mainFrame, SIGNAL(loadStarted()), + this, SIGNAL(loadStarted())); + connect(mainFrame, SIGNAL(loadFinished()), + this, SIGNAL(loadFinished())); + connect(mainFrame, SIGNAL(titleChanged(const QString&)), + this, SIGNAL(titleChanged(const QString&))); + connect(mainFrame, SIGNAL(iconLoaded()), + this, SIGNAL(iconLoaded())); + connect(mainFrame, SIGNAL(urlChanged(const QUrl &)), + this, SIGNAL(urlChanged(const QUrl &))); + + connect(d->page, SIGNAL(loadProgressChanged(int)), + this, SIGNAL(loadProgressChanged(int))); + connect(d->page, SIGNAL(statusBarTextChanged(const QString &)), + this, SIGNAL(statusBarTextChanged(const QString &))); + } + update(); +} + +/*! + Downloads the specified \a url and displays it. +*/ +void QWebView::load(const QUrl &url) +{ + page()->mainFrame()->load(url); +} + +#if QT_VERSION < 0x040400 +void QWebView::load(const QWebNetworkRequest &request) +#else +void QWebView::load(const QNetworkRequest &request, + QNetworkAccessManager::Operation operation, + const QByteArray &body) +#endif +{ + page()->mainFrame()->load(request +#if QT_VERSION >= 0x040400 + , operation, body +#endif + ); +} + +/*! + Sets the content of the web view to the specified \a html. + + External objects referenced in the HTML document are located relative to \a baseUrl. +*/ +void QWebView::setHtml(const QString &html, const QUrl &baseUrl) +{ + page()->mainFrame()->setHtml(html, baseUrl); +} + +/*! + Sets the content of the web view to the specified \a html. + + External objects referenced in the HTML document are located relative to \a baseUrl. +*/ +void QWebView::setHtml(const QByteArray &html, const QUrl &baseUrl) +{ + page()->mainFrame()->setHtml(html, baseUrl); +} + +/*! + Sets the content of the web view to the specified content \a data. If the \a mimeType argument + is empty it is assumed that the content is HTML. + + External objects referenced in the HTML document are located relative to \a baseUrl. +*/ +void QWebView::setContent(const QByteArray &data, const QString &mimeType, const QUrl &baseUrl) +{ + page()->mainFrame()->setContent(data, mimeType, baseUrl); +} + +/*! + Returns a pointer to the view's history of navigated web pages. + + It is equivalent to + + \snippet doc/src/snippets/code/src.3rdparty.webkit.WebKit.qt.Api.qwebview.cpp 0 +*/ +QWebHistory *QWebView::history() const +{ + return page()->history(); +} + +/*! + Returns a pointer to the view/page specific settings object. + + It is equivalent to + + \snippet doc/src/snippets/code/src.3rdparty.webkit.WebKit.qt.Api.qwebview.cpp 1 +*/ +QWebSettings *QWebView::settings() const +{ + return page()->settings(); +} + +/*! + \property QWebView::title + \brief the title of the web page currently viewed. +*/ +QString QWebView::title() const +{ + if (d->page) + return d->page->mainFrame()->title(); + return QString(); +} + +/*! + \property QWebView::url + \brief the url of the web page currently viewed. +*/ +QUrl QWebView::url() const +{ + if (d->page) + return d->page->mainFrame()->url(); + return QUrl(); +} + +/*! + \property QWebView::icon + \brief the icon associated with the web page currently viewed. +*/ +QPixmap QWebView::icon() const +{ + if (d->page) + return d->page->mainFrame()->icon(); + return QPixmap(); +} + +/*! + \property QWebView::selectedText + \brief the text currently selected. +*/ +QString QWebView::selectedText() const +{ + if (d->page) + return d->page->selectedText(); + return QString(); +} + +/*! + Returns a pointer to a QAction that encapsulates the specified web action \a action. +*/ +QAction *QWebView::action(QWebPage::WebAction action) const +{ + return page()->action(action); +} + +/*! + Triggers the specified \a action. If it is a checkable action the specified \a checked state is assumed. + + The following example triggers the copy action and therefore copies any selected text to the clipboard. + + \snippet doc/src/snippets/code/src.3rdparty.webkit.WebKit.qt.Api.qwebview.cpp 2 +*/ +void QWebView::triggerAction(QWebPage::WebAction action, bool checked) +{ + page()->triggerAction(action, checked); +} + +/*! + \property QWebView::modified + \brief whether the document was modified by the user + + Parts of HTML documents can be editable for example through the \c{contenteditable} attribute on + HTML elements. +*/ +bool QWebView::isModified() const +{ + if (d->page) + return d->page->isModified(); + return false; +} + +Qt::TextInteractionFlags QWebView::textInteractionFlags() const +{ + // ### FIXME (add to page) + return Qt::TextInteractionFlags(); +} + +/*! + \property QWebView::textInteractionFlags + \brief how the view should handle user input + + Specifies how the user can interact with the text on the page. +*/ + +void QWebView::setTextInteractionFlags(Qt::TextInteractionFlags flags) +{ + Q_UNUSED(flags) + // ### FIXME (add to page) +} + +/*! + \reimp +*/ +QSize QWebView::sizeHint() const +{ + return QSize(800, 600); // ####... +} + +/*! + Convenience slot that stops loading the document. + + It is equivalent to + + \snippet doc/src/snippets/code/src.3rdparty.webkit.WebKit.qt.Api.qwebview.cpp 3 +*/ +void QWebView::stop() +{ + if (d->page) + d->page->triggerAction(QWebPage::Stop); +} + +/*! + Convenience slot that loads the previous document in the list of + documents built by navigating links. Does nothing if there is no + previous document. + + It is equivalent to + + \snippet doc/src/snippets/code/src.3rdparty.webkit.WebKit.qt.Api.qwebview.cpp 4 +*/ +void QWebView::backward() +{ + if (d->page) + d->page->triggerAction(QWebPage::GoBack); +} + +/*! + Convenience slot that loads the next document in the list of + documents built by navigating links. Does nothing if there is no + next document. + + It is equivalent to + + \snippet doc/src/snippets/code/src.3rdparty.webkit.WebKit.qt.Api.qwebview.cpp 5 +*/ +void QWebView::forward() +{ + if (d->page) + d->page->triggerAction(QWebPage::GoForward); +} + +/*! + Reloads the current document. +*/ +void QWebView::reload() +{ + if (d->page) + d->page->triggerAction(QWebPage::Reload); +} + +/*! \reimp +*/ +void QWebView::resizeEvent(QResizeEvent *e) +{ + if (d->page) + d->page->setViewportSize(e->size()); +} + +/*! \reimp +*/ +void QWebView::paintEvent(QPaintEvent *ev) +{ + if (!d->page) + return; +#ifdef QWEBKIT_TIME_RENDERING + QTime time; + time.start(); +#endif + + QWebFrame *frame = d->page->mainFrame(); + QPainter p(this); + + frame->render(&p, ev->region()); + +#ifdef QWEBKIT_TIME_RENDERING + int elapsed = time.elapsed(); + qDebug()<<"paint event on "<<ev->region()<<", took to render = "<<elapsed; +#endif +} + +/*! + This function is called whenever WebKit wants to create a new window, for example as a result of + a JavaScript request to open a document in a new window. +*/ +QWebView *QWebView::createWindow() +{ + return 0; +} + +/*! \reimp +*/ +void QWebView::mouseMoveEvent(QMouseEvent* ev) +{ + if (d->page) + d->page->event(ev); +} + +/*! \reimp +*/ +void QWebView::mousePressEvent(QMouseEvent* ev) +{ + if (d->page) + d->page->event(ev); +} + +/*! \reimp +*/ +void QWebView::mouseDoubleClickEvent(QMouseEvent* ev) +{ + if (d->page) + d->page->event(ev); +} + +/*! \reimp +*/ +void QWebView::mouseReleaseEvent(QMouseEvent* ev) +{ + if (d->page) + d->page->event(ev); +} + +/*! \reimp +*/ +void QWebView::contextMenuEvent(QContextMenuEvent* ev) +{ + if (d->page) + d->page->event(ev); +} + +/*! \reimp +*/ +void QWebView::wheelEvent(QWheelEvent* ev) +{ + if (d->page) + d->page->event(ev); + + if (!ev->isAccepted()) + return QWidget::wheelEvent(ev); +} + +/*! \reimp +*/ +void QWebView::keyPressEvent(QKeyEvent* ev) +{ + if (d->page) + d->page->event(ev); + if (!ev->isAccepted()) + QWidget::keyPressEvent(ev); +} + +/*! \reimp +*/ +void QWebView::keyReleaseEvent(QKeyEvent* ev) +{ + if (d->page) + d->page->event(ev); + if (!ev->isAccepted()) + QWidget::keyReleaseEvent(ev); +} + +/*! \reimp +*/ +void QWebView::focusInEvent(QFocusEvent* ev) +{ + if (d->page) + d->page->event(ev); + QWidget::focusInEvent(ev); +} + +/*! \reimp +*/ +void QWebView::focusOutEvent(QFocusEvent* ev) +{ + QWidget::focusOutEvent(ev); + if (d->page) + d->page->event(ev); +} + +/*! \reimp +*/ +void QWebView::dragEnterEvent(QDragEnterEvent* ev) +{ +#ifndef QT_NO_DRAGANDDROP + if (d->page) + d->page->event(ev); +#endif +} + +/*! \reimp +*/ +void QWebView::dragLeaveEvent(QDragLeaveEvent* ev) +{ +#ifndef QT_NO_DRAGANDDROP + if (d->page) + d->page->event(ev); +#endif +} + +/*! \reimp +*/ +void QWebView::dragMoveEvent(QDragMoveEvent* ev) +{ +#ifndef QT_NO_DRAGANDDROP + if (d->page) + d->page->event(ev); +#endif +} + +/*! \reimp +*/ +void QWebView::dropEvent(QDropEvent* ev) +{ +#ifndef QT_NO_DRAGANDDROP + if (d->page) + d->page->event(ev); +#endif +} + +/*! \reimp +*/ +bool QWebView::focusNextPrevChild(bool next) +{ + if (d->page && d->page->focusNextPrevChild(next)) + return true; + return QWidget::focusNextPrevChild(next); +} + +/*! + \fn void QWebView::titleChanged(const QString &title) + + This signal is emitted whenever the \a title of the main frame changes. + + \sa title() +*/ + +/*! + \fn void QWebView::urlChanged(const QUrl &url) + + This signal is emitted whenever the \a url of the main frame changes. + + \sa url() +*/ + +/*! + \fn void QWebView::statusBarTextChanged(const QString& text) + + This signal is emitted when the statusbar \a text is changed by the page. +*/ + +/*! + \fn void QWebView::iconLoaded() + + This signal is emitted whenever the icon of the page is loaded or changes. +*/ + +/*! + \fn void QWebView::loadStarted() + + This signal is emitted when a new load of the frame is started. +*/ + +/*! + \fn void QWebView::loadFinished() + + This signal is emitted when a load of the frame is finished. +*/ + +/*! + \fn void QWebView::selectionChanged() + + This signal is emitted whenever the selection changes. +*/ + +/*! + \fn void QWebView::loadProgressChanged(int progress) + + This signal is emitted when the global progress status changes. + The current value is provided by \a progress in percent. + It accumulates changes from all the child frames. +*/ diff --git a/WebKit/qt/Api/qwebview.h b/WebKit/qt/Api/qwebview.h new file mode 100644 index 0000000..53043ae --- /dev/null +++ b/WebKit/qt/Api/qwebview.h @@ -0,0 +1,135 @@ +/* + Copyright (C) 2007 Trolltech ASA + Copyright (C) 2007 Staikos Computing Services Inc. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ +#ifndef QWEBVIEW_H +#define QWEBVIEW_H + +#include "qwebkitglobal.h" +#include "qwebpage.h" +#include <QtGui/qwidget.h> +#include <QtCore/qurl.h> +#if QT_VERSION >= 0x040400 +#include <QtNetwork/qnetworkaccessmanager.h> +#endif + +class QWebPage; +class QWebViewPrivate; +class QNetworkRequest; +class QWebNetworkRequest; + +class QWEBKIT_EXPORT QWebView : public QWidget +{ + Q_OBJECT + Q_PROPERTY(QString title READ title) + Q_PROPERTY(QUrl url READ url WRITE load) + Q_PROPERTY(QPixmap icon READ icon) + Q_PROPERTY(QString selectedText READ selectedText) + Q_PROPERTY(bool modified READ isModified) + Q_PROPERTY(Qt::TextInteractionFlags textInteractionFlags READ textInteractionFlags WRITE setTextInteractionFlags) +public: + explicit QWebView(QWidget *parent = 0); + virtual ~QWebView(); + + QWebPage *page() const; + void setPage(QWebPage *page); + + void load(const QUrl &url); +#if QT_VERSION < 0x040400 + void load(const QWebNetworkRequest &request); +#else + void load(const QNetworkRequest &request, + QNetworkAccessManager::Operation operation = QNetworkAccessManager::GetOperation, + const QByteArray &body = QByteArray()); +#endif + void setHtml(const QString &html, const QUrl &baseUrl = QUrl()); + void setHtml(const QByteArray &html, const QUrl &baseUrl = QUrl()); + void setContent(const QByteArray &data, const QString &mimeType = QString(), const QUrl &baseUrl = QUrl()); + + QWebHistory *history() const; + QWebSettings *settings() const; + + QString title() const; + QUrl url() const; + QPixmap icon() const; + + QString selectedText() const; + + QAction *action(QWebPage::WebAction action) const; + void triggerAction(QWebPage::WebAction action, bool checked = false); + + bool isModified() const; + + Qt::TextInteractionFlags textInteractionFlags() const; + void setTextInteractionFlags(Qt::TextInteractionFlags flags); + + /* #### QTextBrowser compatibility? + bool openLinks() const; + void setOpenLinks(bool open); + + bool openExternalLinks() const; + void setOpenExternalLinks(bool open); + */ + + QSize sizeHint() const; +public Q_SLOTS: + void stop(); + void backward(); + void forward(); + void reload(); + +Q_SIGNALS: + void loadStarted(); + void loadProgressChanged(int progress); + void loadFinished(); + void titleChanged(const QString& title); + void statusBarTextChanged(const QString& text); + void linkClicked(const QUrl &url); + void selectionChanged(); + void iconLoaded(); + void urlChanged(const QUrl &url); + +protected: + void resizeEvent(QResizeEvent *e); + void paintEvent(QPaintEvent *ev); + + virtual QWebView *createWindow(); + + virtual void mouseMoveEvent(QMouseEvent*); + virtual void mousePressEvent(QMouseEvent*); + virtual void mouseDoubleClickEvent(QMouseEvent*); + virtual void mouseReleaseEvent(QMouseEvent*); + virtual void contextMenuEvent(QContextMenuEvent*); + virtual void wheelEvent(QWheelEvent*); + virtual void keyPressEvent(QKeyEvent*); + virtual void keyReleaseEvent(QKeyEvent*); + virtual void dragEnterEvent(QDragEnterEvent *); + virtual void dragLeaveEvent(QDragLeaveEvent *); + virtual void dragMoveEvent(QDragMoveEvent *); + virtual void dropEvent(QDropEvent *); + virtual void focusInEvent(QFocusEvent*); + virtual void focusOutEvent(QFocusEvent*); + + virtual bool focusNextPrevChild(bool next); + +private: + friend class QWebPage; + QWebViewPrivate *d; +}; + +#endif // QWEBVIEW_H |