From d037c87d94666f94faf2c6fbb0f5d11107496de4 Mon Sep 17 00:00:00 2001 From: Christian Stromme Date: Fri, 13 Oct 2017 22:31:58 +0200 Subject: Make QtWebView plugin based This removes the hard build dependency to QtWebEngine, which opens up the possibility for QtWebEngine, or others, to provide their own plugin. Another benefit of having the backends loaded at run-time, is that we can provide an alternative for developers that wants to publish their application in the App Store, where shipping QtWebEngine isn't an option, due to store policies, and where we already have an alternative/experimental backend that can be used. [ChangeLog][WebView] QtWebView will now load its backends at run-time. Task-number: QTBUG-63137 Change-Id: I581940fe4c3b5e6bb41896367d3163ac8bc7b6b9 Reviewed-by: Kai Koehne --- src/plugins/android/android.json | 3 + src/plugins/android/android.pro | 20 + src/plugins/android/qandroidwebview.cpp | 437 ++++++++++++++ src/plugins/android/qandroidwebview_p.h | 105 ++++ src/plugins/android/qandroidwebviewplugin.cpp | 56 ++ src/plugins/darwin/darwin.json | 4 + src/plugins/darwin/darwin.pro | 21 + src/plugins/darwin/qdarwinwebview.mm | 450 ++++++++++++++ src/plugins/darwin/qdarwinwebview_p.h | 121 ++++ src/plugins/darwin/qdarwinwebviewplugin.cpp | 68 +++ src/plugins/plugins.pro | 13 + src/plugins/webengine/qwebenginewebview.cpp | 229 ++++++++ src/plugins/webengine/qwebenginewebview_p.h | 121 ++++ src/plugins/webengine/qwebenginewebviewplugin.cpp | 63 ++ src/plugins/webengine/webengine.json | 4 + src/plugins/webengine/webengine.pro | 19 + src/plugins/winrt/qwinrtwebview.cpp | 682 +++++++++++++++++++++ src/plugins/winrt/qwinrtwebview_p.h | 109 ++++ src/plugins/winrt/qwinrtwebviewplugin.cpp | 56 ++ src/plugins/winrt/winrt.json | 3 + src/plugins/winrt/winrt.pro | 21 + src/src.pro | 7 +- src/webview/qabstractwebview_p.h | 81 +++ src/webview/qtwebviewfunctions.cpp | 41 +- src/webview/qtwebviewfunctions_p.h | 62 -- src/webview/qwebview.cpp | 42 +- src/webview/qwebview_android.cpp | 442 -------------- src/webview/qwebview_android_p.h | 105 ---- src/webview/qwebview_darwin.mm | 462 --------------- src/webview/qwebview_darwin_p.h | 121 ---- src/webview/qwebview_p.h | 5 +- src/webview/qwebview_p_p.h | 83 --- src/webview/qwebview_webengine.cpp | 236 -------- src/webview/qwebview_webengine_p.h | 121 ---- src/webview/qwebview_winrt.cpp | 687 ---------------------- src/webview/qwebview_winrt_p.h | 109 ---- src/webview/qwebviewfactory.cpp | 130 ++++ src/webview/qwebviewfactory_p.h | 66 +++ src/webview/qwebviewplugin.cpp | 56 ++ src/webview/qwebviewplugin_p.h | 74 +++ src/webview/webview-lib.pri | 75 --- src/webview/webview.pro | 40 +- 42 files changed, 3076 insertions(+), 2574 deletions(-) create mode 100644 src/plugins/android/android.json create mode 100644 src/plugins/android/android.pro create mode 100644 src/plugins/android/qandroidwebview.cpp create mode 100644 src/plugins/android/qandroidwebview_p.h create mode 100644 src/plugins/android/qandroidwebviewplugin.cpp create mode 100644 src/plugins/darwin/darwin.json create mode 100644 src/plugins/darwin/darwin.pro create mode 100644 src/plugins/darwin/qdarwinwebview.mm create mode 100644 src/plugins/darwin/qdarwinwebview_p.h create mode 100644 src/plugins/darwin/qdarwinwebviewplugin.cpp create mode 100644 src/plugins/plugins.pro create mode 100644 src/plugins/webengine/qwebenginewebview.cpp create mode 100644 src/plugins/webengine/qwebenginewebview_p.h create mode 100644 src/plugins/webengine/qwebenginewebviewplugin.cpp create mode 100644 src/plugins/webengine/webengine.json create mode 100644 src/plugins/webengine/webengine.pro create mode 100644 src/plugins/winrt/qwinrtwebview.cpp create mode 100644 src/plugins/winrt/qwinrtwebview_p.h create mode 100644 src/plugins/winrt/qwinrtwebviewplugin.cpp create mode 100644 src/plugins/winrt/winrt.json create mode 100644 src/plugins/winrt/winrt.pro create mode 100644 src/webview/qabstractwebview_p.h delete mode 100644 src/webview/qtwebviewfunctions_p.h delete mode 100644 src/webview/qwebview_android.cpp delete mode 100644 src/webview/qwebview_android_p.h delete mode 100644 src/webview/qwebview_darwin.mm delete mode 100644 src/webview/qwebview_darwin_p.h delete mode 100644 src/webview/qwebview_p_p.h delete mode 100644 src/webview/qwebview_webengine.cpp delete mode 100644 src/webview/qwebview_webengine_p.h delete mode 100644 src/webview/qwebview_winrt.cpp delete mode 100644 src/webview/qwebview_winrt_p.h create mode 100644 src/webview/qwebviewfactory.cpp create mode 100644 src/webview/qwebviewfactory_p.h create mode 100644 src/webview/qwebviewplugin.cpp create mode 100644 src/webview/qwebviewplugin_p.h delete mode 100644 src/webview/webview-lib.pri (limited to 'src') diff --git a/src/plugins/android/android.json b/src/plugins/android/android.json new file mode 100644 index 0000000..9f65fd4 --- /dev/null +++ b/src/plugins/android/android.json @@ -0,0 +1,3 @@ +{ + "Keys": ["native"] +} diff --git a/src/plugins/android/android.pro b/src/plugins/android/android.pro new file mode 100644 index 0000000..c10a9d4 --- /dev/null +++ b/src/plugins/android/android.pro @@ -0,0 +1,20 @@ +TARGET = qtwebview_android + +PLUGIN_TYPE = webview +PLUGIN_CLASS_NAME = QAndroidWebViewPlugin +load(qt_plugin) + +QT += core gui webview-private +LIBS_PRIVATE += -ljnigraphics + +HEADERS += \ + qandroidwebview_p.h + +SOURCES += \ + qandroidwebviewplugin.cpp \ + qandroidwebview.cpp + +OTHER_FILES += + +DISTFILES += \ + android.json diff --git a/src/plugins/android/qandroidwebview.cpp b/src/plugins/android/qandroidwebview.cpp new file mode 100644 index 0000000..94e123c --- /dev/null +++ b/src/plugins/android/qandroidwebview.cpp @@ -0,0 +1,437 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtWebView module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qandroidwebview_p.h" +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +QT_BEGIN_NAMESPACE + +static const char qtAndroidWebViewControllerClass[] = "org/qtproject/qt5/android/view/QtAndroidWebViewController"; + +//static bool favIcon(JNIEnv *env, jobject icon, QImage *image) +//{ +// // TODO: +// AndroidBitmapInfo bitmapInfo; +// if (AndroidBitmap_getInfo(env, icon, &bitmapInfo) != ANDROID_BITMAP_RESULT_SUCCESS) +// return false; + +// void *pixelData; +// if (AndroidBitmap_lockPixels(env, icon, &pixelData) != ANDROID_BITMAP_RESULT_SUCCESS) +// return false; + +// *image = QImage::fromData(static_cast(pixelData), bitmapInfo.width * bitmapInfo.height); +// AndroidBitmap_unlockPixels(env, icon); + +// return true; +//} + +typedef QMap WebViews; +Q_GLOBAL_STATIC(WebViews, g_webViews) + +QAndroidWebViewPrivate::QAndroidWebViewPrivate(QObject *p) + : QAbstractWebView(p) + , m_id(reinterpret_cast(this)) + , m_callbackId(0) + , m_window(0) +{ + m_viewController = QJNIObjectPrivate(qtAndroidWebViewControllerClass, + "(Landroid/app/Activity;J)V", + QtAndroidPrivate::activity(), + m_id); + m_webView = m_viewController.callObjectMethod("getWebView", + "()Landroid/webkit/WebView;"); + + m_window = QWindow::fromWinId(reinterpret_cast(m_webView.object())); + g_webViews->insert(m_id, this); + connect(qApp, &QGuiApplication::applicationStateChanged, + this, &QAndroidWebViewPrivate::onApplicationStateChanged); +} + +QAndroidWebViewPrivate::~QAndroidWebViewPrivate() +{ + g_webViews->take(m_id); + if (m_window != 0) { + m_window->setVisible(false); + m_window->setParent(0); + delete m_window; + } + + m_viewController.callMethod("destroy"); +} + +QUrl QAndroidWebViewPrivate::url() const +{ + return QUrl::fromUserInput(m_viewController.callObjectMethod("getUrl").toString()); +} + +void QAndroidWebViewPrivate::setUrl(const QUrl &url) +{ + m_viewController.callMethod("loadUrl", + "(Ljava/lang/String;)V", + QJNIObjectPrivate::fromString(url.toString()).object()); +} + +void QAndroidWebViewPrivate::loadHtml(const QString &html, const QUrl &baseUrl) +{ + const QJNIObjectPrivate &htmlString = QJNIObjectPrivate::fromString(html); + const QJNIObjectPrivate &mimeTypeString = QJNIObjectPrivate::fromString(QLatin1String("text/html;charset=UTF-8")); + + baseUrl.isEmpty() ? m_viewController.callMethod("loadData", + "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V", + htmlString.object(), + mimeTypeString.object(), + 0) + + : m_viewController.callMethod("loadDataWithBaseURL", + "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V", + QJNIObjectPrivate::fromString(baseUrl.toString()).object(), + htmlString.object(), + mimeTypeString.object(), + 0, + 0); +} + +bool QAndroidWebViewPrivate::canGoBack() const +{ + return m_viewController.callMethod("canGoBack"); +} + +void QAndroidWebViewPrivate::goBack() +{ + m_viewController.callMethod("goBack"); +} + +bool QAndroidWebViewPrivate::canGoForward() const +{ + return m_viewController.callMethod("canGoForward"); +} + +void QAndroidWebViewPrivate::goForward() +{ + m_viewController.callMethod("goForward"); +} + +void QAndroidWebViewPrivate::reload() +{ + m_viewController.callMethod("reload"); +} + +QString QAndroidWebViewPrivate::title() const +{ + return m_viewController.callObjectMethod("getTitle").toString(); +} + +void QAndroidWebViewPrivate::setGeometry(const QRect &geometry) +{ + if (m_window == 0) + return; + + m_window->setGeometry(geometry); +} + +void QAndroidWebViewPrivate::setVisibility(QWindow::Visibility visibility) +{ + m_window->setVisibility(visibility); +} + +void QAndroidWebViewPrivate::runJavaScriptPrivate(const QString &script, + int callbackId) +{ + if (QtAndroidPrivate::androidSdkVersion() < 19) { + qWarning("runJavaScript() requires API level 19 or higher."); + if (callbackId == -1) + return; + + // Emit signal here to remove the callback. + Q_EMIT javaScriptResult(callbackId, QVariant()); + } + + m_viewController.callMethod("runJavaScript", + "(Ljava/lang/String;J)V", + static_cast(QJNIObjectPrivate::fromString(script).object()), + callbackId); +} + +void QAndroidWebViewPrivate::setVisible(bool visible) +{ + m_window->setVisible(visible); +} + +int QAndroidWebViewPrivate::loadProgress() const +{ + return m_viewController.callMethod("getProgress"); +} + +bool QAndroidWebViewPrivate::isLoading() const +{ + return m_viewController.callMethod("isLoading"); +} + +void QAndroidWebViewPrivate::setParentView(QObject *view) +{ + m_window->setParent(qobject_cast(view)); +} + +QObject *QAndroidWebViewPrivate::parentView() const +{ + return m_window->parent(); +} + +void QAndroidWebViewPrivate::stop() +{ + m_viewController.callMethod("stopLoading"); +} + +//void QAndroidWebViewPrivate::initialize() +//{ +// // TODO: +//} + +void QAndroidWebViewPrivate::onApplicationStateChanged(Qt::ApplicationState state) +{ + if (QtAndroidPrivate::androidSdkVersion() < 11) + return; + + if (state == Qt::ApplicationActive) + m_viewController.callMethod("onResume"); + else + m_viewController.callMethod("onPause"); +} + +QT_END_NAMESPACE + +static void c_onRunJavaScriptResult(JNIEnv *env, + jobject thiz, + jlong id, + jlong callbackId, + jstring result) +{ + Q_UNUSED(env) + Q_UNUSED(thiz) + + const WebViews &wv = (*g_webViews); + QAndroidWebViewPrivate *wc = static_cast(wv[id]); + if (!wc) + return; + + const QString &resultString = QJNIObjectPrivate(result).toString(); + + // The result string is in JSON format, lets parse it to see what we got. + QJsonValue jsonValue; + const QByteArray &jsonData = "{ \"data\": " + resultString.toUtf8() + " }"; + QJsonParseError error; + const QJsonDocument &jsonDoc = QJsonDocument::fromJson(jsonData, &error); + if (error.error == QJsonParseError::NoError && jsonDoc.isObject()) { + const QJsonObject &object = jsonDoc.object(); + jsonValue = object.value(QStringLiteral("data")); + } + + Q_EMIT wc->javaScriptResult(int(callbackId), + jsonValue.isNull() ? resultString + : jsonValue.toVariant()); +} + +static void c_onPageFinished(JNIEnv *env, + jobject thiz, + jlong id, + jstring url) +{ + Q_UNUSED(env) + Q_UNUSED(thiz) + const WebViews &wv = (*g_webViews); + QAndroidWebViewPrivate *wc = wv[id]; + if (!wc) + return; + + QWebViewLoadRequestPrivate loadRequest(QUrl(QJNIObjectPrivate(url).toString()), + QWebView::LoadSucceededStatus, + QString()); + Q_EMIT wc->loadingChanged(loadRequest); +} + +static void c_onPageStarted(JNIEnv *env, + jobject thiz, + jlong id, + jstring url, + jobject icon) +{ + Q_UNUSED(env) + Q_UNUSED(thiz) + Q_UNUSED(icon) + const WebViews &wv = (*g_webViews); + QAndroidWebViewPrivate *wc = wv[id]; + if (!wc) + return; + QWebViewLoadRequestPrivate loadRequest(QUrl(QJNIObjectPrivate(url).toString()), + QWebView::LoadStartedStatus, + QString()); + Q_EMIT wc->loadingChanged(loadRequest); + +// if (!icon) +// return; + +// QImage image; +// if (favIcon(env, icon, &image)) +// Q_EMIT wc->iconChanged(image); +} + +static void c_onProgressChanged(JNIEnv *env, + jobject thiz, + jlong id, + jint newProgress) +{ + Q_UNUSED(env) + Q_UNUSED(thiz) + const WebViews &wv = (*g_webViews); + QAndroidWebViewPrivate *wc = wv[id]; + if (!wc) + return; + + Q_EMIT wc->loadProgressChanged(newProgress); +} + +static void c_onReceivedIcon(JNIEnv *env, + jobject thiz, + jlong id, + jobject icon) +{ + Q_UNUSED(env) + Q_UNUSED(thiz) + Q_UNUSED(id) + Q_UNUSED(icon) + + const WebViews &wv = (*g_webViews); + QAndroidWebViewPrivate *wc = wv[id]; + if (!wc) + return; + + if (!icon) + return; + +// QImage image; +// if (favIcon(env, icon, &image)) +// Q_EMIT wc->iconChanged(image); +} + +static void c_onReceivedTitle(JNIEnv *env, + jobject thiz, + jlong id, + jstring title) +{ + Q_UNUSED(env) + Q_UNUSED(thiz) + const WebViews &wv = (*g_webViews); + QAndroidWebViewPrivate *wc = wv[id]; + if (!wc) + return; + + const QString &qTitle = QJNIObjectPrivate(title).toString(); + Q_EMIT wc->titleChanged(qTitle); +} + +static void c_onReceivedError(JNIEnv *env, + jobject thiz, + jlong id, + jint errorCode, + jstring description, + jstring url) +{ + Q_UNUSED(env) + Q_UNUSED(thiz) + Q_UNUSED(errorCode) + + const WebViews &wv = (*g_webViews); + QAndroidWebViewPrivate *wc = wv[id]; + if (!wc) + return; + QWebViewLoadRequestPrivate loadRequest(QUrl(QJNIObjectPrivate(url).toString()), + QWebView::LoadFailedStatus, + QJNIObjectPrivate(description).toString()); + Q_EMIT wc->loadingChanged(loadRequest); +} + +JNIEXPORT jint JNI_OnLoad(JavaVM* vm, void* /*reserved*/) +{ + static bool initialized = false; + if (initialized) + return JNI_VERSION_1_6; + initialized = true; + + typedef union { + JNIEnv *nativeEnvironment; + void *venv; + } UnionJNIEnvToVoid; + + UnionJNIEnvToVoid uenv; + uenv.venv = NULL; + + if (vm->GetEnv(&uenv.venv, JNI_VERSION_1_4) != JNI_OK) + return JNI_ERR; + + JNIEnv *env = uenv.nativeEnvironment; + + jclass clazz = QJNIEnvironmentPrivate::findClass(qtAndroidWebViewControllerClass, env); + if (!clazz) + return JNI_ERR; + + JNINativeMethod methods[] = { + {"c_onPageFinished", "(JLjava/lang/String;)V", reinterpret_cast(c_onPageFinished)}, + {"c_onPageStarted", "(JLjava/lang/String;Landroid/graphics/Bitmap;)V", reinterpret_cast(c_onPageStarted)}, + {"c_onProgressChanged", "(JI)V", reinterpret_cast(c_onProgressChanged)}, + {"c_onReceivedIcon", "(JLandroid/graphics/Bitmap;)V", reinterpret_cast(c_onReceivedIcon)}, + {"c_onReceivedTitle", "(JLjava/lang/String;)V", reinterpret_cast(c_onReceivedTitle)}, + {"c_onRunJavaScriptResult", "(JJLjava/lang/String;)V", reinterpret_cast(c_onRunJavaScriptResult)}, + {"c_onReceivedError", "(JILjava/lang/String;Ljava/lang/String;)V", reinterpret_cast(c_onReceivedError)} + }; + + const int nMethods = sizeof(methods) / sizeof(methods[0]); + + if (env->RegisterNatives(clazz, methods, nMethods) != JNI_OK) + return JNI_ERR; + + return JNI_VERSION_1_4; +} diff --git a/src/plugins/android/qandroidwebview_p.h b/src/plugins/android/qandroidwebview_p.h new file mode 100644 index 0000000..9c1d364 --- /dev/null +++ b/src/plugins/android/qandroidwebview_p.h @@ -0,0 +1,105 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtWebView module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QANDROIDWEBVIEW_P_H +#define QANDROIDWEBVIEW_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include +#include +#include +#include + +#include + +QT_BEGIN_NAMESPACE + +class QAndroidWebViewPrivate : public QAbstractWebView +{ + Q_OBJECT +public: + explicit QAndroidWebViewPrivate(QObject *p = 0); + ~QAndroidWebViewPrivate() Q_DECL_OVERRIDE; + + QUrl url() const Q_DECL_OVERRIDE; + void setUrl(const QUrl &url) Q_DECL_OVERRIDE; + bool canGoBack() const Q_DECL_OVERRIDE; + bool canGoForward() const Q_DECL_OVERRIDE; + QString title() const Q_DECL_OVERRIDE; + int loadProgress() const Q_DECL_OVERRIDE; + bool isLoading() const Q_DECL_OVERRIDE; + + void setParentView(QObject *view) Q_DECL_OVERRIDE; + QObject *parentView() const Q_DECL_OVERRIDE; + void setGeometry(const QRect &geometry) Q_DECL_OVERRIDE; + void setVisibility(QWindow::Visibility visibility) Q_DECL_OVERRIDE; + void setVisible(bool visible) Q_DECL_OVERRIDE; + +public Q_SLOTS: + void goBack() Q_DECL_OVERRIDE; + void goForward() Q_DECL_OVERRIDE; + void reload() Q_DECL_OVERRIDE; + void stop() Q_DECL_OVERRIDE; + void loadHtml(const QString &html, const QUrl &baseUrl = QUrl()) Q_DECL_OVERRIDE; + +protected: + void runJavaScriptPrivate(const QString& script, + int callbackId) Q_DECL_OVERRIDE; + +private Q_SLOTS: + void onApplicationStateChanged(Qt::ApplicationState state); + +private: + quintptr m_id; + quint64 m_callbackId; + QWindow *m_window; + QJNIObjectPrivate m_viewController; + QJNIObjectPrivate m_webView; +}; + +QT_END_NAMESPACE + +#endif // QANDROIDWEBVIEW_P_H diff --git a/src/plugins/android/qandroidwebviewplugin.cpp b/src/plugins/android/qandroidwebviewplugin.cpp new file mode 100644 index 0000000..1d9f1b4 --- /dev/null +++ b/src/plugins/android/qandroidwebviewplugin.cpp @@ -0,0 +1,56 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtWebView module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qandroidwebview_p.h" +#include + +QT_BEGIN_NAMESPACE + +class QAndroidWebViewPlugin : public QWebViewPlugin +{ + Q_OBJECT + Q_PLUGIN_METADATA(IID QWebViewPluginInterface_iid FILE "android.json") + +public: + QAbstractWebView *create(const QString &key) const override + { + return (key == QLatin1String("webview")) ? new QAndroidWebViewPrivate() : nullptr; + } +}; + +QT_END_NAMESPACE + +#include "qandroidwebviewplugin.moc" diff --git a/src/plugins/darwin/darwin.json b/src/plugins/darwin/darwin.json new file mode 100644 index 0000000..daa9d6f --- /dev/null +++ b/src/plugins/darwin/darwin.json @@ -0,0 +1,4 @@ +{ + "Keys": ["native"], + "RequiresInit": true +} diff --git a/src/plugins/darwin/darwin.pro b/src/plugins/darwin/darwin.pro new file mode 100644 index 0000000..9723eb2 --- /dev/null +++ b/src/plugins/darwin/darwin.pro @@ -0,0 +1,21 @@ +TARGET = qtwebview_darwin + +PLUGIN_TYPE = webview +PLUGIN_CLASS_NAME = QDarwinWebViewPlugin +load(qt_plugin) + +QT += core gui webview-private +LIBS_PRIVATE += -framework Foundation -framework AppKit -framework WebKit +ios: LIBS_PRIVATE += -framework UIKit + +HEADERS += \ + qdarwinwebview_p.h + +SOURCES += \ + qdarwinwebviewplugin.cpp + +OBJECTIVE_SOURCES += \ + qdarwinwebview.mm + +DISTFILES += \ + darwin.json diff --git a/src/plugins/darwin/qdarwinwebview.mm b/src/plugins/darwin/qdarwinwebview.mm new file mode 100644 index 0000000..b31bdaf --- /dev/null +++ b/src/plugins/darwin/qdarwinwebview.mm @@ -0,0 +1,450 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtWebView module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qdarwinwebview_p.h" +#include +#include +#include "qtwebviewfunctions.h" + +#include +#include +#include +#include + +#include +#include + +#ifdef Q_OS_IOS +#import +#import +#endif + +#ifdef Q_OS_MACOS +#include + +typedef NSView UIView; +#endif + +QT_BEGIN_NAMESPACE + +static inline CGRect toCGRect(const QRectF &rect) +{ + return CGRectMake(rect.x(), rect.y(), rect.width(), rect.height()); +} + +QT_END_NAMESPACE +// ------------------------------------------------------------------------- + +#ifdef Q_OS_IOS +@implementation QIOSNativeViewSelectedRecognizer + +- (id)initWithQWindowControllerItem:(QNativeViewController *)item +{ + self = [super initWithTarget:self action:@selector(nativeViewSelected:)]; + if (self) { + self.cancelsTouchesInView = NO; + self.delaysTouchesEnded = NO; + m_item = item; + } + return self; +} + +- (BOOL)canPreventGestureRecognizer:(UIGestureRecognizer *)other +{ + Q_UNUSED(other); + return NO; +} + +- (BOOL)canBePreventedByGestureRecognizer:(UIGestureRecognizer *)other +{ + Q_UNUSED(other); + return NO; +} + +- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event +{ + Q_UNUSED(touches); + Q_UNUSED(event); + self.state = UIGestureRecognizerStateRecognized; +} + +- (void)nativeViewSelected:(UIGestureRecognizer *)gestureRecognizer +{ + Q_UNUSED(gestureRecognizer); + m_item->setFocus(true); +} + +@end +#endif + +// ------------------------------------------------------------------------- + +@interface QtWKWebViewDelegate : NSObject { + QDarwinWebViewPrivate *qDarwinWebViewPrivate; +} +- (QtWKWebViewDelegate *)initWithQAbstractWebView:(QDarwinWebViewPrivate *)webViewPrivate; +- (void)pageDone; + +// protocol: +- (void)webView:(WKWebView *)webView didStartProvisionalNavigation:(WKNavigation *)navigation; +- (void)webView:(WKWebView *)webView didFinishNavigation:(WKNavigation *)navigation; +- (void)webView:(WKWebView *)webView didFailProvisionalNavigation:(WKNavigation *)navigation + withError:(NSError *)error; +@end + +@implementation QtWKWebViewDelegate +- (QtWKWebViewDelegate *)initWithQAbstractWebView:(QDarwinWebViewPrivate *)webViewPrivate +{ + if ((self = [super init])) { + Q_ASSERT(webViewPrivate); + qDarwinWebViewPrivate = webViewPrivate; + } + return self; +} + +- (void)pageDone +{ + Q_EMIT qDarwinWebViewPrivate->loadProgressChanged(qDarwinWebViewPrivate->loadProgress()); + Q_EMIT qDarwinWebViewPrivate->titleChanged(qDarwinWebViewPrivate->title()); +} + +- (void)webView:(WKWebView *)webView didStartProvisionalNavigation:(WKNavigation *)navigation +{ + Q_UNUSED(webView); + Q_UNUSED(navigation); + // WKNavigationDelegate gives us per-frame notifications while the QWebView API + // should provide per-page notifications. Keep track of started frame loads + // and emit notifications when the final frame completes. + if (++qDarwinWebViewPrivate->requestFrameCount == 1) { + Q_EMIT qDarwinWebViewPrivate->loadingChanged( + QWebViewLoadRequestPrivate(qDarwinWebViewPrivate->url(), + QWebView::LoadStartedStatus, + QString())); + } + + Q_EMIT qDarwinWebViewPrivate->loadProgressChanged(qDarwinWebViewPrivate->loadProgress()); +} + +- (void)webView:(WKWebView *)webView didFinishNavigation:(WKNavigation *)navigation +{ + Q_UNUSED(webView); + Q_UNUSED(navigation); + if (--qDarwinWebViewPrivate->requestFrameCount == 0) { + [self pageDone]; + Q_EMIT qDarwinWebViewPrivate->loadingChanged( + QWebViewLoadRequestPrivate(qDarwinWebViewPrivate->url(), + QWebView::LoadSucceededStatus, + QString())); + } +} + +- (void)webView:(WKWebView *)webView didFailProvisionalNavigation:(WKNavigation *)navigation + withError:(NSError *)error +{ + Q_UNUSED(webView); + Q_UNUSED(navigation); + if (--qDarwinWebViewPrivate->requestFrameCount == 0) { + [self pageDone]; + NSString *errorString = [error localizedDescription]; + NSURL *failingURL = error.userInfo[@"NSErrorFailingURLKey"]; + const QUrl url = [failingURL isKindOfClass:[NSURL class]] + ? QUrl::fromNSURL(failingURL) + : qDarwinWebViewPrivate->url(); + Q_EMIT qDarwinWebViewPrivate->loadingChanged( + QWebViewLoadRequestPrivate(url, + QWebView::LoadFailedStatus, + QString::fromNSString(errorString))); + } +} + +- (void)webView:(WKWebView *)webView +decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction + decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler + __attribute__((availability(ios_app_extension,unavailable))) +{ + Q_UNUSED(webView); + NSURL *url = navigationAction.request.URL; + const BOOL handled = (^{ +#if QT_MACOS_IOS_PLATFORM_SDK_EQUAL_OR_ABOVE(101300, 110000) + if (__builtin_available(macOS 10.13, iOS 11.0, *)) { + return [WKWebView handlesURLScheme:url.scheme]; + } else +#endif + { + // +[WKWebView handlesURLScheme:] is a stub that calls + // WebCore::SchemeRegistry::isBuiltinScheme(); + // replicate that as closely as possible + return [@[ + @"about", @"applewebdata", @"blob", @"data", + @"file", @"http", @"https", @"javascript", +#ifdef Q_OS_MACOS + @"safari-extension", +#endif + @"webkit-fake-url", @"wss", @"x-apple-content-filter", +#ifdef Q_OS_MACOS + @"x-apple-ql-id" +#endif + ] containsObject:url.scheme]; + } + })(); + if (!handled) { +#ifdef Q_OS_MACOS + [[NSWorkspace sharedWorkspace] openURL:url]; +#elif defined(Q_OS_IOS) + [[UIApplication sharedApplication] openURL:url options:@{} completionHandler:nil]; +#endif + } + decisionHandler(handled ? WKNavigationActionPolicyAllow : WKNavigationActionPolicyCancel); +} + +- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change + context:(void *)context { + Q_UNUSED(object); + Q_UNUSED(change); + Q_UNUSED(context); + if ([keyPath isEqualToString:@"estimatedProgress"]) { + Q_EMIT qDarwinWebViewPrivate->loadProgressChanged(qDarwinWebViewPrivate->loadProgress()); + } +} + +@end + +QT_BEGIN_NAMESPACE + +QDarwinWebViewPrivate::QDarwinWebViewPrivate(QObject *p) + : QAbstractWebView(p) + , wkWebView(nil) +#ifdef Q_OS_IOS + , m_recognizer(0) +#endif +{ + CGRect frame = CGRectMake(0.0, 0.0, 400, 400); + wkWebView = [[WKWebView alloc] initWithFrame:frame]; + wkWebView.navigationDelegate = [[QtWKWebViewDelegate alloc] initWithQAbstractWebView:this]; + [wkWebView addObserver:wkWebView.navigationDelegate forKeyPath:@"estimatedProgress" + options:NSKeyValueObservingOptions(NSKeyValueObservingOptionNew) + context:nil]; + +#ifdef Q_OS_IOS + m_recognizer = [[QIOSNativeViewSelectedRecognizer alloc] initWithQWindowControllerItem:this]; + [wkWebView addGestureRecognizer:m_recognizer]; +#endif +} + +QDarwinWebViewPrivate::~QDarwinWebViewPrivate() +{ + [wkWebView stopLoading]; + [wkWebView removeObserver:wkWebView.navigationDelegate forKeyPath:@"estimatedProgress" + context:nil]; + [wkWebView.navigationDelegate release]; + wkWebView.navigationDelegate = nil; + [wkWebView release]; +#ifdef Q_OS_IOS + [m_recognizer release]; +#endif +} + +QUrl QDarwinWebViewPrivate::url() const +{ + return QUrl::fromNSURL(wkWebView.URL); +} + +void QDarwinWebViewPrivate::setUrl(const QUrl &url) +{ + if (url.isValid()) { + requestFrameCount = 0; + +#if QT_MACOS_IOS_PLATFORM_SDK_EQUAL_OR_ABOVE(101100, 90000) + if (url.isLocalFile()) { + // We need to pass local files via loadFileURL and the read access should cover + // the directory that the file is in, to facilitate loading referenced images etc + if (__builtin_available(macOS 10.11, iOS 9, *)) { + [wkWebView loadFileURL:url.toNSURL() + allowingReadAccessToURL:QUrl(url.toString(QUrl::RemoveFilename)).toNSURL()]; + return; + } + } +#endif + [wkWebView loadRequest:[NSURLRequest requestWithURL:url.toNSURL()]]; + } +} + +void QDarwinWebViewPrivate::loadHtml(const QString &html, const QUrl &baseUrl) +{ + [wkWebView loadHTMLString:html.toNSString() baseURL:baseUrl.toNSURL()]; +} + +bool QDarwinWebViewPrivate::canGoBack() const +{ + return wkWebView.canGoBack; +} + +bool QDarwinWebViewPrivate::canGoForward() const +{ + return wkWebView.canGoForward; +} + +QString QDarwinWebViewPrivate::title() const +{ + return QString::fromNSString(wkWebView.title); +} + +int QDarwinWebViewPrivate::loadProgress() const +{ + return int(wkWebView.estimatedProgress * 100); +} + +bool QDarwinWebViewPrivate::isLoading() const +{ + return wkWebView.loading; +} + +void QDarwinWebViewPrivate::setParentView(QObject *view) +{ + m_parentView = view; + + if (!wkWebView) + return; + + QWindow *w = qobject_cast(view); + if (w) { + UIView *parentView = reinterpret_cast(w->winId()); + [parentView addSubview:wkWebView]; + } else { + [wkWebView removeFromSuperview]; + } +} + +QObject *QDarwinWebViewPrivate::parentView() const +{ + return m_parentView; +} + +void QDarwinWebViewPrivate::setGeometry(const QRect &geometry) +{ + if (!wkWebView) + return; + + [wkWebView setFrame:toCGRect(geometry)]; +} + +void QDarwinWebViewPrivate::setVisibility(QWindow::Visibility visibility) +{ + Q_UNUSED(visibility); +} + +void QDarwinWebViewPrivate::setVisible(bool visible) +{ + [wkWebView setHidden:!visible]; +} + +void QDarwinWebViewPrivate::setFocus(bool focus) +{ + Q_EMIT requestFocus(focus); +} + +void QDarwinWebViewPrivate::goBack() +{ + [wkWebView goBack]; +} + +void QDarwinWebViewPrivate::goForward() +{ + [wkWebView goForward]; +} + +void QDarwinWebViewPrivate::stop() +{ + [wkWebView stopLoading]; +} + +void QDarwinWebViewPrivate::reload() +{ + [wkWebView reload]; +} + +QVariant fromNSNumber(const NSNumber *number) +{ + if (!number) + return QVariant(); + if (strcmp([number objCType], @encode(BOOL)) == 0) { + return QVariant::fromValue(!![number boolValue]); + } else if (strcmp([number objCType], @encode(signed char)) == 0) { + return QVariant::fromValue([number charValue]); + } else if (strcmp([number objCType], @encode(unsigned char)) == 0) { + return QVariant::fromValue([number unsignedCharValue]); + } else if (strcmp([number objCType], @encode(signed short)) == 0) { + return QVariant::fromValue([number shortValue]); + } else if (strcmp([number objCType], @encode(unsigned short)) == 0) { + return QVariant::fromValue([number unsignedShortValue]); + } else if (strcmp([number objCType], @encode(signed int)) == 0) { + return QVariant::fromValue([number intValue]); + } else if (strcmp([number objCType], @encode(unsigned int)) == 0) { + return QVariant::fromValue([number unsignedIntValue]); + } else if (strcmp([number objCType], @encode(signed long long)) == 0) { + return QVariant::fromValue([number longLongValue]); + } else if (strcmp([number objCType], @encode(unsigned long long)) == 0) { + return QVariant::fromValue([number unsignedLongLongValue]); + } else if (strcmp([number objCType], @encode(float)) == 0) { + return QVariant::fromValue([number floatValue]); + } else if (strcmp([number objCType], @encode(double)) == 0) { + return QVariant::fromValue([number doubleValue]); + } + return QVariant(); +} + +QVariant fromJSValue(id result) +{ + if ([result isKindOfClass:[NSString class]]) + return QString::fromNSString(static_cast(result)); + if ([result isKindOfClass:[NSNumber class]]) + return fromNSNumber(static_cast(result)); + if ([result isKindOfClass:[NSDate class]]) + return QDateTime::fromNSDate(static_cast(result)); + + // JSValue also supports arrays and dictionaries, but we don't handle that yet + return QVariant(); +} + +void QDarwinWebViewPrivate::runJavaScriptPrivate(const QString &script, int callbackId) +{ + [wkWebView evaluateJavaScript:script.toNSString() completionHandler:^(id result, NSError *) { + if (callbackId != -1) + Q_EMIT javaScriptResult(callbackId, fromJSValue(result)); + }]; +} + +QT_END_NAMESPACE diff --git a/src/plugins/darwin/qdarwinwebview_p.h b/src/plugins/darwin/qdarwinwebview_p.h new file mode 100644 index 0000000..8bc9c13 --- /dev/null +++ b/src/plugins/darwin/qdarwinwebview_p.h @@ -0,0 +1,121 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtWebView module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QDARWINWEBVIEW_P_H +#define QDARWINWEBVIEW_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include +#include +#include + +#include + +#if defined(Q_OS_IOS) && defined(__OBJC__) +#include + +@interface QIOSNativeViewSelectedRecognizer : UIGestureRecognizer +{ +@public + QNativeViewController *m_item; +} +- (id)initWithQWindowControllerItem:(QNativeViewController *)item; +@end +#endif + +Q_FORWARD_DECLARE_OBJC_CLASS(WKWebView); + +#ifdef Q_OS_IOS +Q_FORWARD_DECLARE_OBJC_CLASS(UIGestureRecognizer); +#endif + +QT_BEGIN_NAMESPACE + +class QDarwinWebViewPrivate : public QAbstractWebView +{ + Q_OBJECT +public: + explicit QDarwinWebViewPrivate(QObject *p = 0); + ~QDarwinWebViewPrivate() Q_DECL_OVERRIDE; + + QUrl url() const Q_DECL_OVERRIDE; + void setUrl(const QUrl &url) Q_DECL_OVERRIDE; + bool canGoBack() const Q_DECL_OVERRIDE; + bool canGoForward() const Q_DECL_OVERRIDE; + QString title() const Q_DECL_OVERRIDE; + int loadProgress() const Q_DECL_OVERRIDE; + bool isLoading() const Q_DECL_OVERRIDE; + + void setParentView(QObject *view) Q_DECL_OVERRIDE; + QObject *parentView() const Q_DECL_OVERRIDE; + void setGeometry(const QRect &geometry) Q_DECL_OVERRIDE; + void setVisibility(QWindow::Visibility visibility) Q_DECL_OVERRIDE; + void setVisible(bool visible) Q_DECL_OVERRIDE; + void setFocus(bool focus) Q_DECL_OVERRIDE; + +public Q_SLOTS: + void goBack() Q_DECL_OVERRIDE; + void goForward() Q_DECL_OVERRIDE; + void reload() Q_DECL_OVERRIDE; + void stop() Q_DECL_OVERRIDE; + void loadHtml(const QString &html, const QUrl &baseUrl = QUrl()) Q_DECL_OVERRIDE; + +protected: + void runJavaScriptPrivate(const QString& script, + int callbackId) Q_DECL_OVERRIDE; + +public: + WKWebView *wkWebView; +#ifdef Q_OS_IOS + UIGestureRecognizer *m_recognizer; +#endif + int requestFrameCount; + QPointer m_parentView; +}; + +QT_END_NAMESPACE + +#endif // QDARWINWEBVIEW_P_H diff --git a/src/plugins/darwin/qdarwinwebviewplugin.cpp b/src/plugins/darwin/qdarwinwebviewplugin.cpp new file mode 100644 index 0000000..9c03989 --- /dev/null +++ b/src/plugins/darwin/qdarwinwebviewplugin.cpp @@ -0,0 +1,68 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtWebView module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qdarwinwebview_p.h" +#include +#include + +QT_BEGIN_NAMESPACE + +class QDarwinWebViewPlugin : public QWebViewPlugin +{ + Q_OBJECT + Q_PLUGIN_METADATA(IID QWebViewPluginInterface_iid FILE "darwin.json") + +public: + QAbstractWebView *create(const QString &key) const override + { + return (key == QLatin1String("webview")) ? new QDarwinWebViewPrivate() : nullptr; + } + + void prepare() const override + { +#ifdef Q_OS_MACOS + // On macOS, correct WebView / QtQuick compositing and stacking requires running + // Qt in layer-backed mode, which again resuires rendering on the Gui thread. + qWarning("Setting QT_MAC_WANTS_LAYER=1 and QSG_RENDER_LOOP=basic"); + qputenv("QT_MAC_WANTS_LAYER", "1"); + qputenv("QSG_RENDER_LOOP", "basic"); +#endif // Q_OS_MACOS + } +}; + +QT_END_NAMESPACE + +#include "qdarwinwebviewplugin.moc" diff --git a/src/plugins/plugins.pro b/src/plugins/plugins.pro new file mode 100644 index 0000000..60c5078 --- /dev/null +++ b/src/plugins/plugins.pro @@ -0,0 +1,13 @@ +TEMPLATE = subdirs + +android { + SUBDIRS += android +} else:if(ios|macos) { + SUBDIRS += darwin +} else:winrt { + SUBDIRS += winrt +} + +qtHaveModule(webengine) { + SUBDIRS += webengine +} diff --git a/src/plugins/webengine/qwebenginewebview.cpp b/src/plugins/webengine/qwebenginewebview.cpp new file mode 100644 index 0000000..d083b8d --- /dev/null +++ b/src/plugins/webengine/qwebenginewebview.cpp @@ -0,0 +1,229 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtWebView module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qwebenginewebview_p.h" +#include +#include + +#include + +#include +#include +#include +#include +#include + +#include + +#include +#include +#include + +#include +#include + +QT_BEGIN_NAMESPACE + +static QByteArray qmlSource() +{ + return QByteArrayLiteral("import QtWebEngine 1.1\n" + " WebEngineView {\n" + "}\n"); +} + +QWebEngineWebViewPrivate::QWebEngineWebViewPrivate(QObject *p) + : QAbstractWebView(p) +{ + m_webEngineView.m_parent = this; +} + +QWebEngineWebViewPrivate::~QWebEngineWebViewPrivate() +{ +} + +QUrl QWebEngineWebViewPrivate::url() const +{ + return m_webEngineView->url(); +} + +void QWebEngineWebViewPrivate::setUrl(const QUrl &url) +{ + m_webEngineView->setUrl(url); +} + +void QWebEngineWebViewPrivate::loadHtml(const QString &html, const QUrl &baseUrl) +{ + m_webEngineView->loadHtml(html, baseUrl); +} + +bool QWebEngineWebViewPrivate::canGoBack() const +{ + return m_webEngineView->canGoBack(); +} + +void QWebEngineWebViewPrivate::goBack() +{ + m_webEngineView->goBack(); +} + +bool QWebEngineWebViewPrivate::canGoForward() const +{ + return m_webEngineView->canGoForward(); +} + +void QWebEngineWebViewPrivate::goForward() +{ + m_webEngineView->goForward(); +} + +void QWebEngineWebViewPrivate::reload() +{ + m_webEngineView->reload(); +} + +QString QWebEngineWebViewPrivate::title() const +{ + return m_webEngineView->title(); +} + +void QWebEngineWebViewPrivate::setGeometry(const QRect &geometry) +{ + m_webEngineView->setSize(geometry.size()); +} + +void QWebEngineWebViewPrivate::setVisibility(QWindow::Visibility visibility) +{ + setVisible(visibility != QWindow::Hidden ? true : false); +} + +void QWebEngineWebViewPrivate::runJavaScriptPrivate(const QString &script, + int callbackId) +{ + m_webEngineView->runJavaScript(script, QQuickWebView::takeCallback(callbackId)); +} + +void QWebEngineWebViewPrivate::setVisible(bool visible) +{ + m_webEngineView->setVisible(visible); +} + +void QWebEngineWebViewPrivate::setFocus(bool focus) +{ + if (focus) + m_webEngineView->forceActiveFocus(); +} + +int QWebEngineWebViewPrivate::loadProgress() const +{ + return m_webEngineView->loadProgress(); +} + +bool QWebEngineWebViewPrivate::isLoading() const +{ + return m_webEngineView->isLoading(); +} + +void QWebEngineWebViewPrivate::setParentView(QObject *parentView) +{ + Q_UNUSED(parentView); +} + +QObject *QWebEngineWebViewPrivate::parentView() const +{ + return m_webEngineView->window(); +} + +void QWebEngineWebViewPrivate::stop() +{ + m_webEngineView->stop(); +} + +void QWebEngineWebViewPrivate::q_urlChanged() +{ + Q_EMIT urlChanged(m_webEngineView->url()); +} + +void QWebEngineWebViewPrivate::q_loadProgressChanged() +{ + Q_EMIT loadProgressChanged(m_webEngineView->loadProgress()); +} + +void QWebEngineWebViewPrivate::q_titleChanged() +{ + Q_EMIT titleChanged(m_webEngineView->title()); +} + +void QWebEngineWebViewPrivate::q_loadingChanged(QQuickWebEngineLoadRequest *loadRequest) +{ + QWebViewLoadRequestPrivate lr(loadRequest->url(), + static_cast(loadRequest->status()), // These "should" match... + loadRequest->errorString()); + + Q_EMIT loadingChanged(lr); +} + +void QWebEngineWebViewPrivate::QQuickWebEngineViewPtr::init() const +{ + Q_ASSERT(!m_webEngineView); + QObject *p = qobject_cast(m_parent); + QQuickItem *parentItem = nullptr; + while (p) { + p = p->parent(); + parentItem = qobject_cast(p); + if (parentItem) + break; + } + + if (!parentItem) + return; + + QQmlEngine *engine = qmlEngine(parentItem); + if (!engine) + return; + + QQmlComponent *component = new QQmlComponent(engine); + component->setData(qmlSource(), QUrl::fromLocalFile(QLatin1String(""))); + QQuickWebEngineView *webEngineView = qobject_cast(component->create()); + Q_ASSERT(webEngineView); + QObject::connect(webEngineView, &QQuickWebEngineView::urlChanged, m_parent, &QWebEngineWebViewPrivate::q_urlChanged); + QObject::connect(webEngineView, &QQuickWebEngineView::loadProgressChanged, m_parent, &QWebEngineWebViewPrivate::q_loadProgressChanged); + QObject::connect(webEngineView, &QQuickWebEngineView::loadingChanged, m_parent, &QWebEngineWebViewPrivate::q_loadingChanged); + QObject::connect(webEngineView, &QQuickWebEngineView::titleChanged, m_parent, &QWebEngineWebViewPrivate::q_titleChanged); + webEngineView->setParentItem(parentItem); + m_webEngineView.reset(webEngineView); +} + +QT_END_NAMESPACE diff --git a/src/plugins/webengine/qwebenginewebview_p.h b/src/plugins/webengine/qwebenginewebview_p.h new file mode 100644 index 0000000..88d6284 --- /dev/null +++ b/src/plugins/webengine/qwebenginewebview_p.h @@ -0,0 +1,121 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtWebView module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QWEBENGINEWEBVIEW_P_H +#define QWEBENGINEWEBVIEW_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include +#include +#include + +#include + +#include + +QT_BEGIN_NAMESPACE + +class QQuickWebEngineView; +class QQuickWebEngineLoadRequest; + +class QWebEngineWebViewPrivate : public QAbstractWebView +{ + Q_OBJECT +public: + explicit QWebEngineWebViewPrivate(QObject *p = 0); + ~QWebEngineWebViewPrivate() Q_DECL_OVERRIDE; + + QUrl url() const Q_DECL_OVERRIDE; + void setUrl(const QUrl &url) Q_DECL_OVERRIDE; + bool canGoBack() const Q_DECL_OVERRIDE; + bool canGoForward() const Q_DECL_OVERRIDE; + QString title() const Q_DECL_OVERRIDE; + int loadProgress() const Q_DECL_OVERRIDE; + bool isLoading() const Q_DECL_OVERRIDE; + + void setParentView(QObject *parentView) Q_DECL_OVERRIDE; + QObject *parentView() const Q_DECL_OVERRIDE; + void setGeometry(const QRect &geometry) Q_DECL_OVERRIDE; + void setVisibility(QWindow::Visibility visibility) Q_DECL_OVERRIDE; + void setVisible(bool visible) Q_DECL_OVERRIDE; + void setFocus(bool focus) Q_DECL_OVERRIDE; + +public Q_SLOTS: + void goBack() Q_DECL_OVERRIDE; + void goForward() Q_DECL_OVERRIDE; + void reload() Q_DECL_OVERRIDE; + void stop() Q_DECL_OVERRIDE; + void loadHtml(const QString &html, const QUrl &baseUrl = QUrl()) Q_DECL_OVERRIDE; + +private Q_SLOTS: + void q_urlChanged(); + void q_loadProgressChanged(); + void q_titleChanged(); + void q_loadingChanged(QQuickWebEngineLoadRequest *loadRequest); + +protected: + void runJavaScriptPrivate(const QString& script, + int callbackId) Q_DECL_OVERRIDE; + +private: + struct QQuickWebEngineViewPtr + { + inline QQuickWebEngineView *operator->() const + { + if (!m_webEngineView) + init(); + return m_webEngineView.data(); + } + void init() const; + + QWebEngineWebViewPrivate *m_parent; + mutable QScopedPointer m_webEngineView; + } m_webEngineView; +}; + +QT_END_NAMESPACE + +#endif // QWEBENGINEWEBVIEW_P_H diff --git a/src/plugins/webengine/qwebenginewebviewplugin.cpp b/src/plugins/webengine/qwebenginewebviewplugin.cpp new file mode 100644 index 0000000..0765b49 --- /dev/null +++ b/src/plugins/webengine/qwebenginewebviewplugin.cpp @@ -0,0 +1,63 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtWebView module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qwebenginewebview_p.h" +#include + +#include + +QT_BEGIN_NAMESPACE + +class QWebEngineWebViewPlugin : public QWebViewPlugin +{ + Q_OBJECT + Q_PLUGIN_METADATA(IID QWebViewPluginInterface_iid FILE "webengine.json") + +public: + QAbstractWebView *create(const QString &key) const override + { + return (key == QLatin1String("webview")) ? new QWebEngineWebViewPrivate() : nullptr; + } + + void prepare() const override + { + QtWebEngine::initialize(); + } +}; + +QT_END_NAMESPACE + +#include "qwebenginewebviewplugin.moc" diff --git a/src/plugins/webengine/webengine.json b/src/plugins/webengine/webengine.json new file mode 100644 index 0000000..67049d4 --- /dev/null +++ b/src/plugins/webengine/webengine.json @@ -0,0 +1,4 @@ +{ + "Keys": ["webengine"], + "RequiresInit": true +} diff --git a/src/plugins/webengine/webengine.pro b/src/plugins/webengine/webengine.pro new file mode 100644 index 0000000..b0a03ac --- /dev/null +++ b/src/plugins/webengine/webengine.pro @@ -0,0 +1,19 @@ +TARGET = qtwebview_webengine + +PLUGIN_TYPE = webview +PLUGIN_CLASS_NAME = QWebEngineWebViewPlugin +load(qt_plugin) + +QT += core gui webengine-private webview-private + +HEADERS += \ + qwebenginewebview_p.h + +SOURCES += \ + qwebenginewebview.cpp \ + qwebenginewebviewplugin.cpp + +OTHER_FILES += + +DISTFILES += \ + webengine.json diff --git a/src/plugins/winrt/qwinrtwebview.cpp b/src/plugins/winrt/qwinrtwebview.cpp new file mode 100644 index 0000000..a9ae659 --- /dev/null +++ b/src/plugins/winrt/qwinrtwebview.cpp @@ -0,0 +1,682 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtWebView module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qwinrtwebview_p.h" +#include + +#include + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +using namespace Microsoft::WRL; +using namespace Microsoft::WRL::Wrappers; +using namespace ABI::Windows::Foundation; +using namespace ABI::Windows::Foundation::Collections; +using namespace ABI::Windows::Graphics::Display; +using namespace ABI::Windows::System; +using namespace ABI::Windows::UI; +using namespace ABI::Windows::UI::Xaml; +using namespace ABI::Windows::UI::Xaml::Controls; +using namespace ABI::Windows::UI::Xaml::Markup; +using namespace ABI::Windows::Web; + +class HStringListIterator : public RuntimeClass, IIterator> +{ +public: + HStringListIterator(HSTRING *data, int size) : data(data), size(size), pos(0) + { + } + + HRESULT __stdcall get_Current(HSTRING *current) override + { + *current = pos >= size ? nullptr : data[pos]; + return S_OK; + } + + HRESULT __stdcall get_HasCurrent(boolean *hasCurrent) override + { + *hasCurrent = pos < size; + return S_OK; + } + + HRESULT __stdcall MoveNext(boolean *hasCurrent) override + { + *hasCurrent = ++pos < size; + return S_OK; + } + + HRESULT __stdcall GetMany(unsigned capacity, HSTRING *value, unsigned *actual) + { + unsigned i = 0; + for (; i < qMin(capacity, unsigned(size)); ++i) + value[i] = data[pos + i]; + *actual = i; + pos += i; + return S_OK; + } + +private: + HSTRING *data; + int size; + int pos; +}; + +class HStringList : public RuntimeClass, IIterable> +{ +public: + HStringList(const QList &stringList) + { + d.resize(stringList.size()); + for (int i = 0; i < stringList.size(); ++i) { + const QString qString = stringList.at(i).trimmed(); + HStringReference hString(reinterpret_cast(qString.utf16()), qString.length()); + hString.CopyTo(&d[i++]); + } + } + + ~HStringList() + { + for (const HSTRING &hString : qAsConst(d)) + WindowsDeleteString(hString); + } + + HRESULT __stdcall First(IIterator **first) override + { + ComPtr it = Make(d.data(), d.size()); + return it.Get()->QueryInterface(IID_PPV_ARGS(first)); + } + +private: + QVector d; +}; + +static QUrl qurlFromUri(IUriRuntimeClass *uri) +{ + HRESULT hr; + HString uriString; + hr = uri->get_AbsoluteUri(uriString.GetAddressOf()); + Q_ASSERT_SUCCEEDED(hr); + quint32 uriStringLength; + const wchar_t *uriStringBuffer = uriString.GetRawBuffer(&uriStringLength); + return QUrl(QString::fromWCharArray(uriStringBuffer, uriStringLength)); +} + +static QString webErrorStatusString(WebErrorStatus status) +{ + switch (status) { + case WebErrorStatus_Unknown: + return QStringLiteral("Unknown"); + case WebErrorStatus_CertificateCommonNameIsIncorrect: + return QStringLiteral("CertificateCommonNameIsIncorrect"); + case WebErrorStatus_CertificateExpired: + return QStringLiteral("CertificateExpired"); + case WebErrorStatus_CertificateContainsErrors: + return QStringLiteral("CertificateContainsErrors"); + case WebErrorStatus_CertificateRevoked: + return QStringLiteral("CertificateRevoked"); + case WebErrorStatus_CertificateIsInvalid: + return QStringLiteral("CertificateIsInvalid"); + case WebErrorStatus_ServerUnreachable: + return QStringLiteral("ServerUnreachable"); + case WebErrorStatus_Timeout: + return QStringLiteral("Timeout"); + case WebErrorStatus_ErrorHttpInvalidServerResponse: + return QStringLiteral("ErrorHttpInvalidServerResponse"); + case WebErrorStatus_ConnectionAborted: + return QStringLiteral("ConnectionAborted"); + case WebErrorStatus_ConnectionReset: + return QStringLiteral("ConnectionReset"); + case WebErrorStatus_Disconnected: + return QStringLiteral("Disconnected"); + case WebErrorStatus_HttpToHttpsOnRedirection: + return QStringLiteral("HttpToHttpsOnRedirection"); + case WebErrorStatus_HttpsToHttpOnRedirection: + return QStringLiteral("HttpsToHttpOnRedirection"); + case WebErrorStatus_CannotConnect: + return QStringLiteral("CannotConnect"); + case WebErrorStatus_HostNameNotResolved: + return QStringLiteral("HostNameNotResolved"); + case WebErrorStatus_OperationCanceled: + return QStringLiteral("OperationCanceled"); + case WebErrorStatus_RedirectFailed: + return QStringLiteral("RedirectFailed"); + case WebErrorStatus_UnexpectedStatusCode: + return QStringLiteral("UnexpectedStatusCode"); + case WebErrorStatus_UnexpectedRedirection: + return QStringLiteral("UnexpectedRedirection"); + case WebErrorStatus_UnexpectedClientError: + return QStringLiteral("UnexpectedClientError"); + case WebErrorStatus_UnexpectedServerError: + return QStringLiteral("UnexpectedServerError"); + case WebErrorStatus_MultipleChoices: + return QStringLiteral("MultipleChoices"); + case WebErrorStatus_MovedPermanently: + return QStringLiteral("MovedPermanently"); + case WebErrorStatus_Found: + return QStringLiteral("Found"); + case WebErrorStatus_SeeOther: + return QStringLiteral("SeeOther"); + case WebErrorStatus_NotModified: + return QStringLiteral("NotModified"); + case WebErrorStatus_UseProxy: + return QStringLiteral("UseProxy"); + case WebErrorStatus_TemporaryRedirect: + return QStringLiteral("TemporaryRedirect"); + case WebErrorStatus_BadRequest: + return QStringLiteral("BadRequest"); + case WebErrorStatus_Unauthorized: + return QStringLiteral("Unauthorized"); + case WebErrorStatus_PaymentRequired: + return QStringLiteral("PaymentRequired"); + case WebErrorStatus_Forbidden: + return QStringLiteral("Forbidden"); + case WebErrorStatus_NotFound: + return QStringLiteral("NotFound"); + case WebErrorStatus_MethodNotAllowed: + return QStringLiteral("MethodNotAllowed"); + case WebErrorStatus_NotAcceptable: + return QStringLiteral("NotAcceptable"); + case WebErrorStatus_ProxyAuthenticationRequired: + return QStringLiteral("ProxyAuthenticationRequired"); + case WebErrorStatus_RequestTimeout: + return QStringLiteral("RequestTimeout"); + case WebErrorStatus_Conflict: + return QStringLiteral("Conflict"); + case WebErrorStatus_Gone: + return QStringLiteral("Gone"); + case WebErrorStatus_LengthRequired: + return QStringLiteral("LengthRequired"); + case WebErrorStatus_PreconditionFailed: + return QStringLiteral("PreconditionFailed"); + case WebErrorStatus_RequestEntityTooLarge: + return QStringLiteral("RequestEntityTooLarge"); + case WebErrorStatus_RequestUriTooLong: + return QStringLiteral("RequestUriTooLong"); + case WebErrorStatus_UnsupportedMediaType: + return QStringLiteral("UnsupportedMediaType"); + case WebErrorStatus_RequestedRangeNotSatisfiable: + return QStringLiteral("RequestedRangeNotSatisfiable"); + case WebErrorStatus_ExpectationFailed: + return QStringLiteral("ExpectationFailed"); + case WebErrorStatus_InternalServerError: + return QStringLiteral("InternalServerError"); + case WebErrorStatus_NotImplemented: + return QStringLiteral("NotImplemented"); + case WebErrorStatus_BadGateway: + return QStringLiteral("BadGateway"); + case WebErrorStatus_ServiceUnavailable: + return QStringLiteral("ServiceUnavailable"); + case WebErrorStatus_GatewayTimeout: + return QStringLiteral("GatewayTimeout"); + case WebErrorStatus_HttpVersionNotSupported: + return QStringLiteral("HttpVersionNotSupported"); + default: + break; + } + return QString(); +} + +struct WinRTWebView +{ + ComPtr base; + ComPtr ext; + ComPtr host; + + ComPtr canvas; + ComPtr uriFactory; + ComPtr displayInformation; + ComPtr launcherStatics; + + QPointer window; + QHash *, int> callbacks; + + EventRegistrationToken navigationStartingToken; + EventRegistrationToken navigationCompletedToken; + bool isLoading : 1; +}; + +#define LSTRING(str) L#str +static const wchar_t webviewXaml[] = LSTRING( + +); + +QWinRTWebViewPrivate::QWinRTWebViewPrivate(QObject *parent) + : QAbstractWebView(parent), d(new WinRTWebView) +{ + d->isLoading = false; + + QEventDispatcherWinRT::runOnXamlThread([this]() { + HRESULT hr; + ComPtr xamlReader; + hr = RoGetActivationFactory(HString::MakeReference(RuntimeClass_Windows_UI_Xaml_Markup_XamlReader).Get(), + IID_PPV_ARGS(&xamlReader)); + Q_ASSERT_SUCCEEDED(hr); + + // Directly instantiating a WebView works, but it throws an exception + // when navigating. Using a XamlReader appears to set it up properly. + ComPtr element; + hr = xamlReader->Load(HString::MakeReference(webviewXaml).Get(), &element); + Q_ASSERT_SUCCEEDED(hr); + hr = element.As(&d->base); + Q_ASSERT_SUCCEEDED(hr); + hr = d->base.As(&d->ext); + Q_ASSERT_SUCCEEDED(hr); + hr = RoGetActivationFactory(HString::MakeReference(RuntimeClass_Windows_System_Launcher).Get(), + IID_PPV_ARGS(&d->launcherStatics)); + Q_ASSERT_SUCCEEDED(hr); + + hr = d->ext->add_NavigationStarting( + Callback>(this, &QWinRTWebViewPrivate::onNavigationStarted).Get(), + &d->navigationStartingToken); + Q_ASSERT_SUCCEEDED(hr); + hr = d->ext->add_NavigationCompleted( + Callback>(this, &QWinRTWebViewPrivate::onNavigationCompleted).Get(), + &d->navigationCompletedToken); + Q_ASSERT_SUCCEEDED(hr); + + ComPtr displayInformationStatics; + hr = RoGetActivationFactory(HString::MakeReference(RuntimeClass_Windows_Graphics_Display_DisplayInformation).Get(), + IID_PPV_ARGS(&displayInformationStatics)); + Q_ASSERT_SUCCEEDED(hr); + hr = displayInformationStatics->GetForCurrentView(&d->displayInformation); + Q_ASSERT_SUCCEEDED(hr); + return hr; + }); + + HRESULT hr; + hr = RoGetActivationFactory(HString::MakeReference(RuntimeClass_Windows_UI_Xaml_Controls_Canvas).Get(), + IID_PPV_ARGS(&d->canvas)); + Q_ASSERT_SUCCEEDED(hr); + hr = RoGetActivationFactory(HString::MakeReference(RuntimeClass_Windows_Foundation_Uri).Get(), + IID_PPV_ARGS(&d->uriFactory)); + Q_ASSERT_SUCCEEDED(hr); +} + +QWinRTWebViewPrivate::~QWinRTWebViewPrivate() +{ + QEventDispatcherWinRT::runOnXamlThread([this]() { + HRESULT hr; + hr = d->ext->remove_NavigationStarting(d->navigationStartingToken); + Q_ASSERT_SUCCEEDED(hr); + hr = d->ext->remove_NavigationCompleted(d->navigationCompletedToken); + Q_ASSERT_SUCCEEDED(hr); + ComPtr> children; + hr = d->host->get_Children(&children); + Q_ASSERT_SUCCEEDED(hr); + ComPtr uiElement; + hr = d->base.As(&uiElement); + Q_ASSERT_SUCCEEDED(hr); + quint32 index; + boolean found; + hr = children->IndexOf(uiElement.Get(), &index, &found); + Q_ASSERT_SUCCEEDED(hr); + if (found) { + hr = children->RemoveAt(index); + Q_ASSERT_SUCCEEDED(hr); + } + return hr; + }); +} + +QUrl QWinRTWebViewPrivate::url() const +{ + ComPtr uri; + QEventDispatcherWinRT::runOnXamlThread([this, &uri]() { + HRESULT hr; + hr = d->base->get_Source(&uri); + Q_ASSERT_SUCCEEDED(hr); + return hr; + }); + return qurlFromUri(uri.Get()); +} + +void QWinRTWebViewPrivate::setUrl(const QUrl &url) +{ + QEventDispatcherWinRT::runOnXamlThread([this, &url]() { + HRESULT hr; + const QString urlString = url.toString(); + ComPtr uri; + HStringReference uriString(reinterpret_cast(urlString.utf16()), + urlString.length()); + hr = d->uriFactory->CreateUri(uriString.Get(), &uri); + Q_ASSERT_SUCCEEDED(hr); + hr = d->base->Navigate(uri.Get()); + // Directly running into an abort means, that the URI is not supported. Ask the user what to do + if (hr == E_ABORT) { + ComPtr> op; + hr = d->launcherStatics->LaunchUriAsync(uri.Get(), &op); + } + Q_ASSERT_SUCCEEDED(hr); + return hr; + }); +} + +bool QWinRTWebViewPrivate::canGoBack() const +{ + boolean canGoBack; + QEventDispatcherWinRT::runOnXamlThread([this, &canGoBack]() { + HRESULT hr; + hr = d->ext->get_CanGoBack(&canGoBack); + Q_ASSERT_SUCCEEDED(hr); + return hr; + }); + return canGoBack; +} + +bool QWinRTWebViewPrivate::canGoForward() const +{ + boolean canGoForward; + QEventDispatcherWinRT::runOnXamlThread([this, &canGoForward]() { + HRESULT hr; + hr = d->ext->get_CanGoForward(&canGoForward); + Q_ASSERT_SUCCEEDED(hr); + return hr; + }); + return canGoForward; +} + +QString QWinRTWebViewPrivate::title() const +{ + HString title; + QEventDispatcherWinRT::runOnXamlThread([this, &title]() { + HRESULT hr; + hr = d->ext->get_DocumentTitle(title.GetAddressOf()); + Q_ASSERT_SUCCEEDED(hr); + return hr; + }); + quint32 titleLength; + const wchar_t *titleBuffer = title.GetRawBuffer(&titleLength); + return QString::fromWCharArray(titleBuffer, titleLength); +} + +int QWinRTWebViewPrivate::loadProgress() const +{ + return d->isLoading ? 0 : 100; +} + +bool QWinRTWebViewPrivate::isLoading() const +{ + return d->isLoading; +} + +void QWinRTWebViewPrivate::setParentView(QObject *view) +{ + d->window = qobject_cast(view); + if (!d->window) + return; + + ComPtr host = reinterpret_cast(d->window->winId()); + if (!host) + return; + + QEventDispatcherWinRT::runOnXamlThread([this, &host]() { + HRESULT hr; + ComPtr frameworkHost; + hr = host.As(&frameworkHost); + RETURN_HR_IF_FAILED("Failed to cast the window ID to IFrameworkElement"); + ComPtr parent; + hr = frameworkHost->get_Parent(&parent); + RETURN_HR_IF_FAILED("Failed to get the parent object of the window"); + hr = parent.As(&d->host); + RETURN_HR_IF_FAILED("Failed to cast the window container to IPanel"); + ComPtr> children; + hr = d->host->get_Children(&children); + Q_ASSERT_SUCCEEDED(hr); + ComPtr uiElement; + hr = d->base.As(&uiElement); + Q_ASSERT_SUCCEEDED(hr); + hr = children->Append(uiElement.Get()); + Q_ASSERT_SUCCEEDED(hr); + return hr; + }); +} + +QObject *QWinRTWebViewPrivate::parentView() const +{ + return d->window; +} + +void QWinRTWebViewPrivate::setGeometry(const QRect &geometry) +{ + QEventDispatcherWinRT::runOnXamlThread([this, &geometry]() { + HRESULT hr; + double scaleFactor; +#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_PHONE_APP) + ComPtr displayInformation; + hr = d->displayInformation.As(&displayInformation); + Q_ASSERT_SUCCEEDED(hr); + hr = displayInformation->get_RawPixelsPerViewPixel(&scaleFactor); + Q_ASSERT_SUCCEEDED(hr); + scaleFactor = 1.0 / scaleFactor; + Q_ASSERT(d->window); + const QScreen *screen = d->window->screen(); + Q_ASSERT(screen); + const QPoint screenTopLeft = screen->availableGeometry().topLeft(); + const QPointF topLeft = QHighDpi::toNativePixels(QPointF(geometry.topLeft() + screenTopLeft) * scaleFactor, screen); + const QSizeF size = QHighDpi::toNativePixels(QSizeF(geometry.size()) * scaleFactor, screen); +#else + ResolutionScale resolutionScale; + hr = d->displayInformation->get_ResolutionScale(&resolutionScale); + Q_ASSERT_SUCCEEDED(hr); + scaleFactor = 100.0 / double(resolutionScale); + const QPointF topLeft = QPointF(geometry.topLeft()) * scaleFactor; + const QSizeF size = QSizeF(geometry.size()) * scaleFactor; +#endif + ComPtr uiElement; + hr = d->base.As(&uiElement); + Q_ASSERT_SUCCEEDED(hr); + hr = d->canvas->SetLeft(uiElement.Get(), topLeft.x()); + Q_ASSERT_SUCCEEDED(hr); + hr = d->canvas->SetTop(uiElement.Get(), topLeft.y()); + Q_ASSERT_SUCCEEDED(hr); + ComPtr frameworkElement; + hr = d->base.As(&frameworkElement); + Q_ASSERT_SUCCEEDED(hr); + hr = frameworkElement->put_Width(size.width()); + Q_ASSERT_SUCCEEDED(hr); + hr = frameworkElement->put_Height(size.height()); + Q_ASSERT_SUCCEEDED(hr); + return hr; + }); +} + +void QWinRTWebViewPrivate::setVisibility(QWindow::Visibility visibility) +{ + setVisible(visibility != QWindow::Hidden); +} + +void QWinRTWebViewPrivate::setVisible(bool visible) +{ + QEventDispatcherWinRT::runOnXamlThread([this, &visible]() { + HRESULT hr; + ComPtr uiElement; + hr = d->base.As(&uiElement); + Q_ASSERT_SUCCEEDED(hr); + hr = uiElement->put_Visibility(visible ? Visibility_Visible : Visibility_Collapsed); + Q_ASSERT_SUCCEEDED(hr); + return hr; + }); +} + +void QWinRTWebViewPrivate::goBack() +{ + QEventDispatcherWinRT::runOnXamlThread([this]() { + HRESULT hr; + hr = d->ext->GoBack(); + Q_ASSERT_SUCCEEDED(hr); + return hr; + }); +} + +void QWinRTWebViewPrivate::goForward() +{ + QEventDispatcherWinRT::runOnXamlThread([this]() { + HRESULT hr; + hr = d->ext->GoForward(); + Q_ASSERT_SUCCEEDED(hr); + return hr; + }); +} + +void QWinRTWebViewPrivate::reload() +{ + QEventDispatcherWinRT::runOnXamlThread([this]() { + HRESULT hr; + hr = d->ext->Refresh(); + Q_ASSERT_SUCCEEDED(hr); + return hr; + }); +} + +void QWinRTWebViewPrivate::stop() +{ + QEventDispatcherWinRT::runOnXamlThread([this]() { + HRESULT hr; + hr = d->ext->Stop(); + Q_ASSERT_SUCCEEDED(hr); + return hr; + }); +} + +void QWinRTWebViewPrivate::loadHtml(const QString &html, const QUrl &baseUrl) +{ + if (!baseUrl.isEmpty()) + qWarning("Base URLs for loadHtml() are not supported under WinRT."); + + HRESULT hr; + HStringReference htmlText(reinterpret_cast(html.utf16()), html.length()); + hr = d->base->NavigateToString(htmlText.Get()); + Q_ASSERT_SUCCEEDED(hr); +} + +void QWinRTWebViewPrivate::runJavaScriptPrivate(const QString &script, int callbackId) +{ + static QRegularExpression functionTemplate(QStringLiteral("^(.*)\\((.*)\\)[\\s;]*?$")); + QRegularExpressionMatch match = functionTemplate.match(script); + if (!match.hasMatch()) { + qWarning("The WinRT WebView only supports calling global functions, so please make your call" + " in the form myFunction(a, b, c). Also note that only string arguments can be passed."); + return; + } + + const QString method = match.captured(1).trimmed(); + HStringReference methodString(reinterpret_cast(method.utf16()), method.length()); + ComPtr argumentStrings = Make(match.captured(2).split(QLatin1Char(','))); + QEventDispatcherWinRT::runOnXamlThread([this, &methodString, &argumentStrings, &callbackId]() { + HRESULT hr; + ComPtr> op; + hr = d->ext->InvokeScriptAsync(methodString.Get(), argumentStrings.Get(), &op); + Q_ASSERT_SUCCEEDED(hr); + + d->callbacks.insert(op.Get(), callbackId); + hr = op->put_Completed(Callback>([this](IAsyncOperation *op, AsyncStatus status) { + int callbackId = d->callbacks.take(op); + HRESULT hr; + if (status != Completed) { + ComPtr info; + hr = op->QueryInterface(IID_PPV_ARGS(&info)); + Q_ASSERT_SUCCEEDED(hr); + HRESULT errorCode; + hr = info->get_ErrorCode(&errorCode); + Q_ASSERT_SUCCEEDED(hr); + emit javaScriptResult(callbackId, qt_error_string(errorCode)); + return S_OK; + } + HString result; + hr = op->GetResults(result.GetAddressOf()); + Q_ASSERT_SUCCEEDED(hr); + quint32 resultLength; + const wchar_t *resultBuffer = result.GetRawBuffer(&resultLength); + emit javaScriptResult(callbackId, QString::fromWCharArray(resultBuffer, resultLength)); + return S_OK; + }).Get()); + Q_ASSERT_SUCCEEDED(hr); + return hr; + }); +} + +HRESULT QWinRTWebViewPrivate::onNavigationStarted(IWebView *, IWebViewNavigationStartingEventArgs *args) +{ + d->isLoading = true; + HRESULT hr; + ComPtr uri; + hr = args->get_Uri(&uri); + Q_ASSERT_SUCCEEDED(hr); + const QUrl url = qurlFromUri(uri.Get()); + + emit loadingChanged(QWebViewLoadRequestPrivate(url, QWebView::LoadStartedStatus, QString())); + emit loadProgressChanged(0); + return S_OK; +} + +HRESULT QWinRTWebViewPrivate::onNavigationCompleted(IWebView *, IWebViewNavigationCompletedEventArgs *args) +{ + d->isLoading = false; + HRESULT hr; + ComPtr uri; + hr = args->get_Uri(&uri); + Q_ASSERT_SUCCEEDED(hr); + const QUrl url = qurlFromUri(uri.Get()); + + boolean isSuccess; + hr = args->get_IsSuccess(&isSuccess); + Q_ASSERT_SUCCEEDED(hr); + const QWebView::LoadStatus status = isSuccess ? QWebView::LoadSucceededStatus : QWebView::LoadFailedStatus; + + WebErrorStatus errorStatus; + hr = args->get_WebErrorStatus(&errorStatus); + Q_ASSERT_SUCCEEDED(hr); + const QString errorString = webErrorStatusString(errorStatus); + + emit loadingChanged(QWebViewLoadRequestPrivate(url, status, errorString)); + emit titleChanged(title()); + emit loadProgressChanged(100); + return S_OK; +} diff --git a/src/plugins/winrt/qwinrtwebview_p.h b/src/plugins/winrt/qwinrtwebview_p.h new file mode 100644 index 0000000..2b7d937 --- /dev/null +++ b/src/plugins/winrt/qwinrtwebview_p.h @@ -0,0 +1,109 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtWebView module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QWINRTWEBVIEW_P_H +#define QWINRTWEBVIEW_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include + +namespace ABI { + namespace Windows { + namespace UI { + namespace Xaml { + namespace Controls { + struct IWebView; + struct IWebViewNavigationStartingEventArgs; + struct IWebViewNavigationCompletedEventArgs; + } + } + } + } +} + +QT_BEGIN_NAMESPACE + +struct WinRTWebView; +class QWinRTWebViewPrivate : public QAbstractWebView +{ + Q_OBJECT +public: + explicit QWinRTWebViewPrivate(QObject *parent = nullptr); + ~QWinRTWebViewPrivate() Q_DECL_OVERRIDE; + + QUrl url() const Q_DECL_OVERRIDE; + void setUrl(const QUrl &url) Q_DECL_OVERRIDE; + bool canGoBack() const Q_DECL_OVERRIDE; + bool canGoForward() const Q_DECL_OVERRIDE; + QString title() const Q_DECL_OVERRIDE; + int loadProgress() const Q_DECL_OVERRIDE; + bool isLoading() const Q_DECL_OVERRIDE; + + void setParentView(QObject *view) Q_DECL_OVERRIDE; + QObject *parentView() const Q_DECL_OVERRIDE; + void setGeometry(const QRect &geometry) Q_DECL_OVERRIDE; + void setVisibility(QWindow::Visibility visibility) Q_DECL_OVERRIDE; + void setVisible(bool visible) Q_DECL_OVERRIDE; + +public Q_SLOTS: + void goBack() Q_DECL_OVERRIDE; + void goForward() Q_DECL_OVERRIDE; + void reload() Q_DECL_OVERRIDE; + void stop() Q_DECL_OVERRIDE; + void loadHtml(const QString &html, const QUrl &baseUrl = QUrl()) Q_DECL_OVERRIDE; + +protected: + void runJavaScriptPrivate(const QString &script, int callbackId) Q_DECL_OVERRIDE; + +private: + HRESULT onNavigationStarted(ABI::Windows::UI::Xaml::Controls::IWebView *, ABI::Windows::UI::Xaml::Controls::IWebViewNavigationStartingEventArgs *); + HRESULT onNavigationCompleted(ABI::Windows::UI::Xaml::Controls::IWebView *, ABI::Windows::UI::Xaml::Controls::IWebViewNavigationCompletedEventArgs *); + QScopedPointer d; +}; + +QT_END_NAMESPACE + +#endif // QWINRTWEBVIEW_P_H diff --git a/src/plugins/winrt/qwinrtwebviewplugin.cpp b/src/plugins/winrt/qwinrtwebviewplugin.cpp new file mode 100644 index 0000000..30138e1 --- /dev/null +++ b/src/plugins/winrt/qwinrtwebviewplugin.cpp @@ -0,0 +1,56 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtWebView module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qwinrtwebview_p.h" +#include + +QT_BEGIN_NAMESPACE + +class QWinRtWebViewPlugin : public QWebViewPlugin +{ + Q_OBJECT + Q_PLUGIN_METADATA(IID QWebViewPluginInterface_iid FILE "winrt.json") + +public: + QAbstractWebView *create(const QString &key) const override + { + return (key == QLatin1String("webview")) ? new QWinRTWebViewPrivate() : nullptr; + } +}; + +QT_END_NAMESPACE + +#include "qwinrtwebviewplugin.moc" diff --git a/src/plugins/winrt/winrt.json b/src/plugins/winrt/winrt.json new file mode 100644 index 0000000..9f65fd4 --- /dev/null +++ b/src/plugins/winrt/winrt.json @@ -0,0 +1,3 @@ +{ + "Keys": ["native"] +} diff --git a/src/plugins/winrt/winrt.pro b/src/plugins/winrt/winrt.pro new file mode 100644 index 0000000..dabcbfd --- /dev/null +++ b/src/plugins/winrt/winrt.pro @@ -0,0 +1,21 @@ +TARGET = qtwebview_winrt +QT += core gui webview-private + +PLUGIN_TYPE = webview +PLUGIN_CLASS_NAME = QWinrtWebViewPlugin + +load(qt_plugin) + +NO_PCH_SOURCES += \ + qwinrtwebview.cpp + +SOURCES += \ + qwinrtwebviewplugin.cpp + +HEADERS += \ + qwinrtwebview_p.h + +OTHER_FILES += + +DISTFILES += \ + winrt.json diff --git a/src/src.pro b/src/src.pro index c0420f5..7bc2ef7 100644 --- a/src/src.pro +++ b/src/src.pro @@ -1,8 +1,7 @@ TEMPLATE = subdirs -android|ios|macos|winrt|qtHaveModule(webengine) { - SUBDIRS += webview imports - imports.depends = webview -} +SUBDIRS += webview imports plugins +plugins.depends = webview +imports.depends = webview android: SUBDIRS += jar diff --git a/src/webview/qabstractwebview_p.h b/src/webview/qabstractwebview_p.h new file mode 100644 index 0000000..d2eec30 --- /dev/null +++ b/src/webview/qabstractwebview_p.h @@ -0,0 +1,81 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtWebView module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QABSTRACTWEBVIEW_P_H +#define QABSTRACTWEBVIEW_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include "qwebviewinterface_p.h" +#include "qnativeviewcontroller_p.h" + +QT_BEGIN_NAMESPACE + +class QWebView; +class QWebViewLoadRequestPrivate; + +class Q_WEBVIEW_EXPORT QAbstractWebView + : public QObject + , public QWebViewInterface + , public QNativeViewController +{ + Q_OBJECT + +Q_SIGNALS: + void titleChanged(const QString &title); + void urlChanged(const QUrl &url); + void loadingChanged(const QWebViewLoadRequestPrivate &loadRequest); + void loadProgressChanged(int progress); + void javaScriptResult(int id, const QVariant &result); + void requestFocus(bool focus); + +protected: + explicit QAbstractWebView(QObject *p = 0) : QObject(p) { } +}; + +QT_END_NAMESPACE + +#endif // QABSTRACTWEBVIEW_P_H + diff --git a/src/webview/qtwebviewfunctions.cpp b/src/webview/qtwebviewfunctions.cpp index 7509f21..975bb17 100644 --- a/src/webview/qtwebviewfunctions.cpp +++ b/src/webview/qtwebviewfunctions.cpp @@ -35,15 +35,9 @@ ****************************************************************************/ #include "qtwebviewfunctions.h" -#include "qtwebviewfunctions_p.h" -#ifdef QT_WEBVIEW_WEBENGINE_BACKEND -#include -#endif // QT_WEBVIEW_WEBENGINE_BACKEND - -#ifdef Q_OS_MACOS -#include -#endif +#include "qwebviewfactory_p.h" +#include "qwebviewplugin_p.h" QT_BEGIN_NAMESPACE @@ -66,32 +60,11 @@ QT_BEGIN_NAMESPACE void QtWebView::initialize() { -#if defined(Q_OS_MACOS) - if (QtWebViewPrivate::useNativeWebView()) { - // On macOS, correct WebView / QtQuick compositing and stacking requires running - // Qt in layer-backed mode, which again resuires rendering on the Gui thread. - qWarning("Setting QT_MAC_WANTS_LAYER=1 and QSG_RENDER_LOOP=basic"); - qputenv("QT_MAC_WANTS_LAYER", "1"); - qputenv("QSG_RENDER_LOOP", "basic"); - } else -#endif -#if defined(QT_WEBVIEW_WEBENGINE_BACKEND) - QtWebEngine::initialize(); -#endif -} - -/*! - * \fn QtWebView::useNativeWebView() - * \internal - */ - -bool QtWebViewPrivate::useNativeWebView() -{ -#ifdef Q_OS_MACOS - return qEnvironmentVariableIsSet("QT_MAC_USE_NATIVE_WEBVIEW"); -#else - return true; -#endif + if (QWebViewFactory::requiresExtraInitializationSteps()) { + QWebViewPlugin *plugin = QWebViewFactory::getPlugin(); + Q_ASSERT(plugin); + plugin->prepare(); + } } QT_END_NAMESPACE diff --git a/src/webview/qtwebviewfunctions_p.h b/src/webview/qtwebviewfunctions_p.h deleted file mode 100644 index afc7abc..0000000 --- a/src/webview/qtwebviewfunctions_p.h +++ /dev/null @@ -1,62 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: http://www.qt.io/licensing/ -** -** This file is part of the QtWebView module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL3$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see http://www.qt.io/terms-conditions. For further -** information use the contact form at http://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPLv3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or later as published by the Free -** Software Foundation and appearing in the file LICENSE.GPL included in -** the packaging of this file. Please review the following information to -** ensure the GNU General Public License version 2.0 requirements will be -** met: http://www.gnu.org/licenses/gpl-2.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QTWEBVIEWFUNCTIONS_P_H -#define QTWEBVIEWFUNCTIONS_P_H - -// -// W A R N I N G -// ------------- -// -// This file is not part of the Qt API. It exists purely as an -// implementation detail. This header file may change from version to -// version without notice, or even be removed. -// -// We mean it. -// - -#include - -QT_BEGIN_NAMESPACE - -namespace QtWebViewPrivate -{ - bool useNativeWebView(); -} - -QT_END_NAMESPACE - -#endif // QTWEBVIEWFUNCTIONS_P_H diff --git a/src/webview/qwebview.cpp b/src/webview/qwebview.cpp index 507d38a..7e457be 100644 --- a/src/webview/qwebview.cpp +++ b/src/webview/qwebview.cpp @@ -35,24 +35,27 @@ ****************************************************************************/ #include "qwebview_p.h" -#include -#include +#include "qwebviewplugin_p.h" +#include "qwebviewloadrequest_p.h" +#include "qwebviewfactory_p.h" + QT_BEGIN_NAMESPACE QWebView::QWebView(QObject *p) - : QObject(p), - d_ptr(QWebViewPrivate::create(this)) + : QObject(p) + , d(QWebViewFactory::createWebView()) , m_progress(0) { + d->setParent(this); qRegisterMetaType(); - Q_D(QWebView); - connect(d, &QWebViewPrivate::titleChanged, this, &QWebView::onTitleChanged); - connect(d, &QWebViewPrivate::urlChanged, this, &QWebView::onUrlChanged); - connect(d, &QWebViewPrivate::loadingChanged, this, &QWebView::onLoadingChanged); - connect(d, &QWebViewPrivate::loadProgressChanged, this, &QWebView::onLoadProgressChanged); - connect(d, &QWebViewPrivate::requestFocus, this, &QWebView::requestFocus); - connect(d, &QWebViewPrivate::javaScriptResult, + + connect(d, &QAbstractWebView::titleChanged, this, &QWebView::onTitleChanged); + connect(d, &QAbstractWebView::urlChanged, this, &QWebView::onUrlChanged); + connect(d, &QAbstractWebView::loadingChanged, this, &QWebView::onLoadingChanged); + connect(d, &QAbstractWebView::loadProgressChanged, this, &QWebView::onLoadProgressChanged); + connect(d, &QAbstractWebView::requestFocus, this, &QWebView::requestFocus); + connect(d, &QAbstractWebView::javaScriptResult, this, &QWebView::javaScriptResult); } @@ -67,43 +70,36 @@ QUrl QWebView::url() const void QWebView::setUrl(const QUrl &url) { - Q_D(QWebView); d->setUrl(url); } bool QWebView::canGoBack() const { - Q_D(const QWebView); return d->canGoBack(); } void QWebView::goBack() { - Q_D(QWebView); d->goBack(); } bool QWebView::canGoForward() const { - Q_D(const QWebView); return d->canGoForward(); } void QWebView::goForward() { - Q_D(QWebView); d->goForward(); } void QWebView::reload() { - Q_D(QWebView); d->reload(); } void QWebView::stop() { - Q_D(QWebView); d->stop(); } @@ -119,56 +115,47 @@ int QWebView::loadProgress() const bool QWebView::isLoading() const { - Q_D(const QWebView); return d->isLoading(); } void QWebView::setParentView(QObject *view) { - Q_D(QWebView); d->setParentView(view); } QObject *QWebView::parentView() const { - Q_D(const QWebView); return d->parentView(); } void QWebView::setGeometry(const QRect &geometry) { - Q_D(QWebView); d->setGeometry(geometry); } void QWebView::setVisibility(QWindow::Visibility visibility) { - Q_D(QWebView); d->setVisibility(visibility); } void QWebView::setVisible(bool visible) { - Q_D(QWebView); d->setVisible(visible); } void QWebView::setFocus(bool focus) { - Q_D(QWebView); d->setFocus(focus); } void QWebView::loadHtml(const QString &html, const QUrl &baseUrl) { - Q_D(QWebView); d->loadHtml(html, baseUrl); } void QWebView::runJavaScriptPrivate(const QString &script, int callbackId) { - Q_D(QWebView); d->runJavaScriptPrivate(script, callbackId); } @@ -211,7 +198,6 @@ void QWebView::onLoadingChanged(const QWebViewLoadRequestPrivate &loadRequest) void QWebView::init() { - Q_D(QWebView); d->init(); } diff --git a/src/webview/qwebview_android.cpp b/src/webview/qwebview_android.cpp deleted file mode 100644 index cec395d..0000000 --- a/src/webview/qwebview_android.cpp +++ /dev/null @@ -1,442 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2017 The Qt Company Ltd. -** Contact: http://www.qt.io/licensing/ -** -** This file is part of the QtWebView module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL3$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see http://www.qt.io/terms-conditions. For further -** information use the contact form at http://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPLv3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or later as published by the Free -** Software Foundation and appearing in the file LICENSE.GPL included in -** the packaging of this file. Please review the following information to -** ensure the GNU General Public License version 2.0 requirements will be -** met: http://www.gnu.org/licenses/gpl-2.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "qwebview_android_p.h" -#include "qwebview_p.h" -#include "qwebviewloadrequest_p.h" // TODO: -#include -#include - -#include -#include -#include -#include -#include -#include -#include - -QT_BEGIN_NAMESPACE - -QWebViewPrivate *QWebViewPrivate::create(QWebView *q) -{ - return new QAndroidWebViewPrivate(q); -} - -static const char qtAndroidWebViewControllerClass[] = "org/qtproject/qt5/android/view/QtAndroidWebViewController"; - -//static bool favIcon(JNIEnv *env, jobject icon, QImage *image) -//{ -// // TODO: -// AndroidBitmapInfo bitmapInfo; -// if (AndroidBitmap_getInfo(env, icon, &bitmapInfo) != ANDROID_BITMAP_RESULT_SUCCESS) -// return false; - -// void *pixelData; -// if (AndroidBitmap_lockPixels(env, icon, &pixelData) != ANDROID_BITMAP_RESULT_SUCCESS) -// return false; - -// *image = QImage::fromData(static_cast(pixelData), bitmapInfo.width * bitmapInfo.height); -// AndroidBitmap_unlockPixels(env, icon); - -// return true; -//} - -typedef QMap WebViews; -Q_GLOBAL_STATIC(WebViews, g_webViews) - -QAndroidWebViewPrivate::QAndroidWebViewPrivate(QObject *p) - : QWebViewPrivate(p) - , m_id(reinterpret_cast(this)) - , m_callbackId(0) - , m_window(0) -{ - m_viewController = QJNIObjectPrivate(qtAndroidWebViewControllerClass, - "(Landroid/app/Activity;J)V", - QtAndroidPrivate::activity(), - m_id); - m_webView = m_viewController.callObjectMethod("getWebView", - "()Landroid/webkit/WebView;"); - - m_window = QWindow::fromWinId(reinterpret_cast(m_webView.object())); - g_webViews->insert(m_id, this); - connect(qApp, &QGuiApplication::applicationStateChanged, - this, &QAndroidWebViewPrivate::onApplicationStateChanged); -} - -QAndroidWebViewPrivate::~QAndroidWebViewPrivate() -{ - g_webViews->take(m_id); - if (m_window != 0) { - m_window->setVisible(false); - m_window->setParent(0); - delete m_window; - } - - m_viewController.callMethod("destroy"); -} - -QUrl QAndroidWebViewPrivate::url() const -{ - return QUrl::fromUserInput(m_viewController.callObjectMethod("getUrl").toString()); -} - -void QAndroidWebViewPrivate::setUrl(const QUrl &url) -{ - m_viewController.callMethod("loadUrl", - "(Ljava/lang/String;)V", - QJNIObjectPrivate::fromString(url.toString()).object()); -} - -void QAndroidWebViewPrivate::loadHtml(const QString &html, const QUrl &baseUrl) -{ - const QJNIObjectPrivate &htmlString = QJNIObjectPrivate::fromString(html); - const QJNIObjectPrivate &mimeTypeString = QJNIObjectPrivate::fromString(QLatin1String("text/html;charset=UTF-8")); - - baseUrl.isEmpty() ? m_viewController.callMethod("loadData", - "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V", - htmlString.object(), - mimeTypeString.object(), - 0) - - : m_viewController.callMethod("loadDataWithBaseURL", - "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V", - QJNIObjectPrivate::fromString(baseUrl.toString()).object(), - htmlString.object(), - mimeTypeString.object(), - 0, - 0); -} - -bool QAndroidWebViewPrivate::canGoBack() const -{ - return m_viewController.callMethod("canGoBack"); -} - -void QAndroidWebViewPrivate::goBack() -{ - m_viewController.callMethod("goBack"); -} - -bool QAndroidWebViewPrivate::canGoForward() const -{ - return m_viewController.callMethod("canGoForward"); -} - -void QAndroidWebViewPrivate::goForward() -{ - m_viewController.callMethod("goForward"); -} - -void QAndroidWebViewPrivate::reload() -{ - m_viewController.callMethod("reload"); -} - -QString QAndroidWebViewPrivate::title() const -{ - return m_viewController.callObjectMethod("getTitle").toString(); -} - -void QAndroidWebViewPrivate::setGeometry(const QRect &geometry) -{ - if (m_window == 0) - return; - - m_window->setGeometry(geometry); -} - -void QAndroidWebViewPrivate::setVisibility(QWindow::Visibility visibility) -{ - m_window->setVisibility(visibility); -} - -void QAndroidWebViewPrivate::runJavaScriptPrivate(const QString &script, - int callbackId) -{ - if (QtAndroidPrivate::androidSdkVersion() < 19) { - qWarning("runJavaScript() requires API level 19 or higher."); - if (callbackId == -1) - return; - - // Emit signal here to remove the callback. - Q_EMIT javaScriptResult(callbackId, QVariant()); - } - - m_viewController.callMethod("runJavaScript", - "(Ljava/lang/String;J)V", - static_cast(QJNIObjectPrivate::fromString(script).object()), - callbackId); -} - -void QAndroidWebViewPrivate::setVisible(bool visible) -{ - m_window->setVisible(visible); -} - -int QAndroidWebViewPrivate::loadProgress() const -{ - return m_viewController.callMethod("getProgress"); -} - -bool QAndroidWebViewPrivate::isLoading() const -{ - return m_viewController.callMethod("isLoading"); -} - -void QAndroidWebViewPrivate::setParentView(QObject *view) -{ - m_window->setParent(qobject_cast(view)); -} - -QObject *QAndroidWebViewPrivate::parentView() const -{ - return m_window->parent(); -} - -void QAndroidWebViewPrivate::stop() -{ - m_viewController.callMethod("stopLoading"); -} - -//void QAndroidWebViewPrivate::initialize() -//{ -// // TODO: -//} - -void QAndroidWebViewPrivate::onApplicationStateChanged(Qt::ApplicationState state) -{ - if (QtAndroidPrivate::androidSdkVersion() < 11) - return; - - if (state == Qt::ApplicationActive) - m_viewController.callMethod("onResume"); - else - m_viewController.callMethod("onPause"); -} - -QT_END_NAMESPACE - -static void c_onRunJavaScriptResult(JNIEnv *env, - jobject thiz, - jlong id, - jlong callbackId, - jstring result) -{ - Q_UNUSED(env) - Q_UNUSED(thiz) - - const WebViews &wv = (*g_webViews); - QAndroidWebViewPrivate *wc = static_cast(wv[id]); - if (!wc) - return; - - const QString &resultString = QJNIObjectPrivate(result).toString(); - - // The result string is in JSON format, lets parse it to see what we got. - QJsonValue jsonValue; - const QByteArray &jsonData = "{ \"data\": " + resultString.toUtf8() + " }"; - QJsonParseError error; - const QJsonDocument &jsonDoc = QJsonDocument::fromJson(jsonData, &error); - if (error.error == QJsonParseError::NoError && jsonDoc.isObject()) { - const QJsonObject &object = jsonDoc.object(); - jsonValue = object.value(QStringLiteral("data")); - } - - Q_EMIT wc->javaScriptResult(int(callbackId), - jsonValue.isNull() ? resultString - : jsonValue.toVariant()); -} - -static void c_onPageFinished(JNIEnv *env, - jobject thiz, - jlong id, - jstring url) -{ - Q_UNUSED(env) - Q_UNUSED(thiz) - const WebViews &wv = (*g_webViews); - QAndroidWebViewPrivate *wc = wv[id]; - if (!wc) - return; - - QWebViewLoadRequestPrivate loadRequest(QUrl(QJNIObjectPrivate(url).toString()), - QWebView::LoadSucceededStatus, - QString()); - Q_EMIT wc->loadingChanged(loadRequest); -} - -static void c_onPageStarted(JNIEnv *env, - jobject thiz, - jlong id, - jstring url, - jobject icon) -{ - Q_UNUSED(env) - Q_UNUSED(thiz) - Q_UNUSED(icon) - const WebViews &wv = (*g_webViews); - QAndroidWebViewPrivate *wc = wv[id]; - if (!wc) - return; - QWebViewLoadRequestPrivate loadRequest(QUrl(QJNIObjectPrivate(url).toString()), - QWebView::LoadStartedStatus, - QString()); - Q_EMIT wc->loadingChanged(loadRequest); - -// if (!icon) -// return; - -// QImage image; -// if (favIcon(env, icon, &image)) -// Q_EMIT wc->iconChanged(image); -} - -static void c_onProgressChanged(JNIEnv *env, - jobject thiz, - jlong id, - jint newProgress) -{ - Q_UNUSED(env) - Q_UNUSED(thiz) - const WebViews &wv = (*g_webViews); - QAndroidWebViewPrivate *wc = wv[id]; - if (!wc) - return; - - Q_EMIT wc->loadProgressChanged(newProgress); -} - -static void c_onReceivedIcon(JNIEnv *env, - jobject thiz, - jlong id, - jobject icon) -{ - Q_UNUSED(env) - Q_UNUSED(thiz) - Q_UNUSED(id) - Q_UNUSED(icon) - - const WebViews &wv = (*g_webViews); - QAndroidWebViewPrivate *wc = wv[id]; - if (!wc) - return; - - if (!icon) - return; - -// QImage image; -// if (favIcon(env, icon, &image)) -// Q_EMIT wc->iconChanged(image); -} - -static void c_onReceivedTitle(JNIEnv *env, - jobject thiz, - jlong id, - jstring title) -{ - Q_UNUSED(env) - Q_UNUSED(thiz) - const WebViews &wv = (*g_webViews); - QAndroidWebViewPrivate *wc = wv[id]; - if (!wc) - return; - - const QString &qTitle = QJNIObjectPrivate(title).toString(); - Q_EMIT wc->titleChanged(qTitle); -} - -static void c_onReceivedError(JNIEnv *env, - jobject thiz, - jlong id, - jint errorCode, - jstring description, - jstring url) -{ - Q_UNUSED(env) - Q_UNUSED(thiz) - Q_UNUSED(errorCode) - - const WebViews &wv = (*g_webViews); - QAndroidWebViewPrivate *wc = wv[id]; - if (!wc) - return; - QWebViewLoadRequestPrivate loadRequest(QUrl(QJNIObjectPrivate(url).toString()), - QWebView::LoadFailedStatus, - QJNIObjectPrivate(description).toString()); - Q_EMIT wc->loadingChanged(loadRequest); -} - -JNIEXPORT jint JNI_OnLoad(JavaVM* vm, void* /*reserved*/) -{ - static bool initialized = false; - if (initialized) - return JNI_VERSION_1_6; - initialized = true; - - typedef union { - JNIEnv *nativeEnvironment; - void *venv; - } UnionJNIEnvToVoid; - - UnionJNIEnvToVoid uenv; - uenv.venv = NULL; - - if (vm->GetEnv(&uenv.venv, JNI_VERSION_1_4) != JNI_OK) - return JNI_ERR; - - JNIEnv *env = uenv.nativeEnvironment; - - jclass clazz = QJNIEnvironmentPrivate::findClass(qtAndroidWebViewControllerClass, env); - if (!clazz) - return JNI_ERR; - - JNINativeMethod methods[] = { - {"c_onPageFinished", "(JLjava/lang/String;)V", reinterpret_cast(c_onPageFinished)}, - {"c_onPageStarted", "(JLjava/lang/String;Landroid/graphics/Bitmap;)V", reinterpret_cast(c_onPageStarted)}, - {"c_onProgressChanged", "(JI)V", reinterpret_cast(c_onProgressChanged)}, - {"c_onReceivedIcon", "(JLandroid/graphics/Bitmap;)V", reinterpret_cast(c_onReceivedIcon)}, - {"c_onReceivedTitle", "(JLjava/lang/String;)V", reinterpret_cast(c_onReceivedTitle)}, - {"c_onRunJavaScriptResult", "(JJLjava/lang/String;)V", reinterpret_cast(c_onRunJavaScriptResult)}, - {"c_onReceivedError", "(JILjava/lang/String;Ljava/lang/String;)V", reinterpret_cast(c_onReceivedError)} - }; - - const int nMethods = sizeof(methods) / sizeof(methods[0]); - - if (env->RegisterNatives(clazz, methods, nMethods) != JNI_OK) - return JNI_ERR; - - return JNI_VERSION_1_4; -} diff --git a/src/webview/qwebview_android_p.h b/src/webview/qwebview_android_p.h deleted file mode 100644 index 9290289..0000000 --- a/src/webview/qwebview_android_p.h +++ /dev/null @@ -1,105 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2015 The Qt Company Ltd. -** Contact: http://www.qt.io/licensing/ -** -** This file is part of the QtWebView module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL3$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see http://www.qt.io/terms-conditions. For further -** information use the contact form at http://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPLv3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or later as published by the Free -** Software Foundation and appearing in the file LICENSE.GPL included in -** the packaging of this file. Please review the following information to -** ensure the GNU General Public License version 2.0 requirements will be -** met: http://www.gnu.org/licenses/gpl-2.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QWEBVIEW_ANDROID_P_H -#define QWEBVIEW_ANDROID_P_H - -// -// W A R N I N G -// ------------- -// -// This file is not part of the Qt API. It exists purely as an -// implementation detail. This header file may change from version to -// version without notice, or even be removed. -// -// We mean it. -// - -#include -#include -#include -#include - -#include "qwebview_p_p.h" - -QT_BEGIN_NAMESPACE - -class QAndroidWebViewPrivate : public QWebViewPrivate -{ - Q_OBJECT -public: - explicit QAndroidWebViewPrivate(QObject *p = 0); - ~QAndroidWebViewPrivate() Q_DECL_OVERRIDE; - - QUrl url() const Q_DECL_OVERRIDE; - void setUrl(const QUrl &url) Q_DECL_OVERRIDE; - bool canGoBack() const Q_DECL_OVERRIDE; - bool canGoForward() const Q_DECL_OVERRIDE; - QString title() const Q_DECL_OVERRIDE; - int loadProgress() const Q_DECL_OVERRIDE; - bool isLoading() const Q_DECL_OVERRIDE; - - void setParentView(QObject *view) Q_DECL_OVERRIDE; - QObject *parentView() const Q_DECL_OVERRIDE; - void setGeometry(const QRect &geometry) Q_DECL_OVERRIDE; - void setVisibility(QWindow::Visibility visibility) Q_DECL_OVERRIDE; - void setVisible(bool visible) Q_DECL_OVERRIDE; - -public Q_SLOTS: - void goBack() Q_DECL_OVERRIDE; - void goForward() Q_DECL_OVERRIDE; - void reload() Q_DECL_OVERRIDE; - void stop() Q_DECL_OVERRIDE; - void loadHtml(const QString &html, const QUrl &baseUrl = QUrl()) Q_DECL_OVERRIDE; - -protected: - void runJavaScriptPrivate(const QString& script, - int callbackId) Q_DECL_OVERRIDE; - -private Q_SLOTS: - void onApplicationStateChanged(Qt::ApplicationState state); - -private: - quintptr m_id; - quint64 m_callbackId; - QWindow *m_window; - QJNIObjectPrivate m_viewController; - QJNIObjectPrivate m_webView; -}; - -QT_END_NAMESPACE - -#endif // QWEBVIEW_ANDROID_P_H diff --git a/src/webview/qwebview_darwin.mm b/src/webview/qwebview_darwin.mm deleted file mode 100644 index 90f6551..0000000 --- a/src/webview/qwebview_darwin.mm +++ /dev/null @@ -1,462 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: http://www.qt.io/licensing/ -** -** This file is part of the QtWebView module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL3$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see http://www.qt.io/terms-conditions. For further -** information use the contact form at http://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPLv3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or later as published by the Free -** Software Foundation and appearing in the file LICENSE.GPL included in -** the packaging of this file. Please review the following information to -** ensure the GNU General Public License version 2.0 requirements will be -** met: http://www.gnu.org/licenses/gpl-2.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "qwebview_darwin_p.h" -#include "qwebview_p.h" -#include "qwebviewloadrequest_p.h" -#include "qtwebviewfunctions.h" -#include "qtwebviewfunctions_p.h" - -#include -#include -#include -#include - -#include -#include - -#ifdef Q_OS_IOS -#import -#import -#endif - -#ifdef Q_OS_MACOS -#include "qwebview_webengine_p.h" - -#include - -typedef NSView UIView; -#endif - -QT_BEGIN_NAMESPACE - -QWebViewPrivate *QWebViewPrivate::create(QWebView *q) -{ -#ifdef Q_OS_MACOS - if (!QtWebViewPrivate::useNativeWebView()) - return new QWebEngineWebViewPrivate(q); -#endif - return new QDarwinWebViewPrivate(q); -} - -static inline CGRect toCGRect(const QRectF &rect) -{ - return CGRectMake(rect.x(), rect.y(), rect.width(), rect.height()); -} - -QT_END_NAMESPACE -// ------------------------------------------------------------------------- - -#ifdef Q_OS_IOS -@implementation QIOSNativeViewSelectedRecognizer - -- (id)initWithQWindowControllerItem:(QNativeViewController *)item -{ - self = [super initWithTarget:self action:@selector(nativeViewSelected:)]; - if (self) { - self.cancelsTouchesInView = NO; - self.delaysTouchesEnded = NO; - m_item = item; - } - return self; -} - -- (BOOL)canPreventGestureRecognizer:(UIGestureRecognizer *)other -{ - Q_UNUSED(other); - return NO; -} - -- (BOOL)canBePreventedByGestureRecognizer:(UIGestureRecognizer *)other -{ - Q_UNUSED(other); - return NO; -} - -- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event -{ - Q_UNUSED(touches); - Q_UNUSED(event); - self.state = UIGestureRecognizerStateRecognized; -} - -- (void)nativeViewSelected:(UIGestureRecognizer *)gestureRecognizer -{ - Q_UNUSED(gestureRecognizer); - m_item->setFocus(true); -} - -@end -#endif - -// ------------------------------------------------------------------------- - -@interface QtWKWebViewDelegate : NSObject { - QDarwinWebViewPrivate *qDarwinWebViewPrivate; -} -- (QtWKWebViewDelegate *)initWithQAbstractWebView:(QDarwinWebViewPrivate *)webViewPrivate; -- (void)pageDone; - -// protocol: -- (void)webView:(WKWebView *)webView didStartProvisionalNavigation:(WKNavigation *)navigation; -- (void)webView:(WKWebView *)webView didFinishNavigation:(WKNavigation *)navigation; -- (void)webView:(WKWebView *)webView didFailProvisionalNavigation:(WKNavigation *)navigation - withError:(NSError *)error; -@end - -@implementation QtWKWebViewDelegate -- (QtWKWebViewDelegate *)initWithQAbstractWebView:(QDarwinWebViewPrivate *)webViewPrivate -{ - if ((self = [super init])) { - Q_ASSERT(webViewPrivate); - qDarwinWebViewPrivate = webViewPrivate; - } - return self; -} - -- (void)pageDone -{ - Q_EMIT qDarwinWebViewPrivate->loadProgressChanged(qDarwinWebViewPrivate->loadProgress()); - Q_EMIT qDarwinWebViewPrivate->titleChanged(qDarwinWebViewPrivate->title()); -} - -- (void)webView:(WKWebView *)webView didStartProvisionalNavigation:(WKNavigation *)navigation -{ - Q_UNUSED(webView); - Q_UNUSED(navigation); - // WKNavigationDelegate gives us per-frame notifications while the QWebView API - // should provide per-page notifications. Keep track of started frame loads - // and emit notifications when the final frame completes. - if (++qDarwinWebViewPrivate->requestFrameCount == 1) { - Q_EMIT qDarwinWebViewPrivate->loadingChanged( - QWebViewLoadRequestPrivate(qDarwinWebViewPrivate->url(), - QWebView::LoadStartedStatus, - QString())); - } - - Q_EMIT qDarwinWebViewPrivate->loadProgressChanged(qDarwinWebViewPrivate->loadProgress()); -} - -- (void)webView:(WKWebView *)webView didFinishNavigation:(WKNavigation *)navigation -{ - Q_UNUSED(webView); - Q_UNUSED(navigation); - if (--qDarwinWebViewPrivate->requestFrameCount == 0) { - [self pageDone]; - Q_EMIT qDarwinWebViewPrivate->loadingChanged( - QWebViewLoadRequestPrivate(qDarwinWebViewPrivate->url(), - QWebView::LoadSucceededStatus, - QString())); - } -} - -- (void)webView:(WKWebView *)webView didFailProvisionalNavigation:(WKNavigation *)navigation - withError:(NSError *)error -{ - Q_UNUSED(webView); - Q_UNUSED(navigation); - if (--qDarwinWebViewPrivate->requestFrameCount == 0) { - [self pageDone]; - NSString *errorString = [error localizedDescription]; - NSURL *failingURL = error.userInfo[@"NSErrorFailingURLKey"]; - const QUrl url = [failingURL isKindOfClass:[NSURL class]] - ? QUrl::fromNSURL(failingURL) - : qDarwinWebViewPrivate->url(); - Q_EMIT qDarwinWebViewPrivate->loadingChanged( - QWebViewLoadRequestPrivate(url, - QWebView::LoadFailedStatus, - QString::fromNSString(errorString))); - } -} - -- (void)webView:(WKWebView *)webView -decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction - decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler - __attribute__((availability(ios_app_extension,unavailable))) -{ - Q_UNUSED(webView); - NSURL *url = navigationAction.request.URL; - const BOOL handled = (^{ -#if QT_MACOS_IOS_PLATFORM_SDK_EQUAL_OR_ABOVE(101300, 110000) - if (__builtin_available(macOS 10.13, iOS 11.0, *)) { - return [WKWebView handlesURLScheme:url.scheme]; - } else -#endif - { - // +[WKWebView handlesURLScheme:] is a stub that calls - // WebCore::SchemeRegistry::isBuiltinScheme(); - // replicate that as closely as possible - return [@[ - @"about", @"applewebdata", @"blob", @"data", - @"file", @"http", @"https", @"javascript", -#ifdef Q_OS_MACOS - @"safari-extension", -#endif - @"webkit-fake-url", @"wss", @"x-apple-content-filter", -#ifdef Q_OS_MACOS - @"x-apple-ql-id" -#endif - ] containsObject:url.scheme]; - } - })(); - if (!handled) { -#ifdef Q_OS_MACOS - [[NSWorkspace sharedWorkspace] openURL:url]; -#elif defined(Q_OS_IOS) - [[UIApplication sharedApplication] openURL:url options:@{} completionHandler:nil]; -#endif - } - decisionHandler(handled ? WKNavigationActionPolicyAllow : WKNavigationActionPolicyCancel); -} - -- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change - context:(void *)context { - Q_UNUSED(object); - Q_UNUSED(change); - Q_UNUSED(context); - if ([keyPath isEqualToString:@"estimatedProgress"]) { - Q_EMIT qDarwinWebViewPrivate->loadProgressChanged(qDarwinWebViewPrivate->loadProgress()); - } -} - -@end - -QT_BEGIN_NAMESPACE - -QDarwinWebViewPrivate::QDarwinWebViewPrivate(QObject *p) - : QWebViewPrivate(p) - , wkWebView(nil) -#ifdef Q_OS_IOS - , m_recognizer(0) -#endif -{ - CGRect frame = CGRectMake(0.0, 0.0, 400, 400); - wkWebView = [[WKWebView alloc] initWithFrame:frame]; - wkWebView.navigationDelegate = [[QtWKWebViewDelegate alloc] initWithQAbstractWebView:this]; - [wkWebView addObserver:wkWebView.navigationDelegate forKeyPath:@"estimatedProgress" - options:NSKeyValueObservingOptions(NSKeyValueObservingOptionNew) - context:nil]; - -#ifdef Q_OS_IOS - m_recognizer = [[QIOSNativeViewSelectedRecognizer alloc] initWithQWindowControllerItem:this]; - [wkWebView addGestureRecognizer:m_recognizer]; -#endif -} - -QDarwinWebViewPrivate::~QDarwinWebViewPrivate() -{ - [wkWebView stopLoading]; - [wkWebView removeObserver:wkWebView.navigationDelegate forKeyPath:@"estimatedProgress" - context:nil]; - [wkWebView.navigationDelegate release]; - wkWebView.navigationDelegate = nil; - [wkWebView release]; -#ifdef Q_OS_IOS - [m_recognizer release]; -#endif -} - -QUrl QDarwinWebViewPrivate::url() const -{ - return QUrl::fromNSURL(wkWebView.URL); -} - -void QDarwinWebViewPrivate::setUrl(const QUrl &url) -{ - if (url.isValid()) { - requestFrameCount = 0; - -#if QT_MACOS_IOS_PLATFORM_SDK_EQUAL_OR_ABOVE(101100, 90000) - if (url.isLocalFile()) { - // We need to pass local files via loadFileURL and the read access should cover - // the directory that the file is in, to facilitate loading referenced images etc - if (__builtin_available(macOS 10.11, iOS 9, *)) { - [wkWebView loadFileURL:url.toNSURL() - allowingReadAccessToURL:QUrl(url.toString(QUrl::RemoveFilename)).toNSURL()]; - return; - } - } -#endif - [wkWebView loadRequest:[NSURLRequest requestWithURL:url.toNSURL()]]; - } -} - -void QDarwinWebViewPrivate::loadHtml(const QString &html, const QUrl &baseUrl) -{ - [wkWebView loadHTMLString:html.toNSString() baseURL:baseUrl.toNSURL()]; -} - -bool QDarwinWebViewPrivate::canGoBack() const -{ - return wkWebView.canGoBack; -} - -bool QDarwinWebViewPrivate::canGoForward() const -{ - return wkWebView.canGoForward; -} - -QString QDarwinWebViewPrivate::title() const -{ - return QString::fromNSString(wkWebView.title); -} - -int QDarwinWebViewPrivate::loadProgress() const -{ - return int(wkWebView.estimatedProgress * 100); -} - -bool QDarwinWebViewPrivate::isLoading() const -{ - return wkWebView.loading; -} - -void QDarwinWebViewPrivate::setParentView(QObject *view) -{ - m_parentView = view; - - if (!wkWebView) - return; - - QWindow *w = qobject_cast(view); - if (w) { - UIView *parentView = reinterpret_cast(w->winId()); - [parentView addSubview:wkWebView]; - } else { - [wkWebView removeFromSuperview]; - } -} - -QObject *QDarwinWebViewPrivate::parentView() const -{ - return m_parentView; -} - -void QDarwinWebViewPrivate::setGeometry(const QRect &geometry) -{ - if (!wkWebView) - return; - - [wkWebView setFrame:toCGRect(geometry)]; -} - -void QDarwinWebViewPrivate::setVisibility(QWindow::Visibility visibility) -{ - Q_UNUSED(visibility); -} - -void QDarwinWebViewPrivate::setVisible(bool visible) -{ - [wkWebView setHidden:!visible]; -} - -void QDarwinWebViewPrivate::setFocus(bool focus) -{ - Q_EMIT requestFocus(focus); -} - -void QDarwinWebViewPrivate::goBack() -{ - [wkWebView goBack]; -} - -void QDarwinWebViewPrivate::goForward() -{ - [wkWebView goForward]; -} - -void QDarwinWebViewPrivate::stop() -{ - [wkWebView stopLoading]; -} - -void QDarwinWebViewPrivate::reload() -{ - [wkWebView reload]; -} - -QVariant fromNSNumber(const NSNumber *number) -{ - if (!number) - return QVariant(); - if (strcmp([number objCType], @encode(BOOL)) == 0) { - return QVariant::fromValue(!![number boolValue]); - } else if (strcmp([number objCType], @encode(signed char)) == 0) { - return QVariant::fromValue([number charValue]); - } else if (strcmp([number objCType], @encode(unsigned char)) == 0) { - return QVariant::fromValue([number unsignedCharValue]); - } else if (strcmp([number objCType], @encode(signed short)) == 0) { - return QVariant::fromValue([number shortValue]); - } else if (strcmp([number objCType], @encode(unsigned short)) == 0) { - return QVariant::fromValue([number unsignedShortValue]); - } else if (strcmp([number objCType], @encode(signed int)) == 0) { - return QVariant::fromValue([number intValue]); - } else if (strcmp([number objCType], @encode(unsigned int)) == 0) { - return QVariant::fromValue([number unsignedIntValue]); - } else if (strcmp([number objCType], @encode(signed long long)) == 0) { - return QVariant::fromValue([number longLongValue]); - } else if (strcmp([number objCType], @encode(unsigned long long)) == 0) { - return QVariant::fromValue([number unsignedLongLongValue]); - } else if (strcmp([number objCType], @encode(float)) == 0) { - return QVariant::fromValue([number floatValue]); - } else if (strcmp([number objCType], @encode(double)) == 0) { - return QVariant::fromValue([number doubleValue]); - } - return QVariant(); -} - -QVariant fromJSValue(id result) -{ - if ([result isKindOfClass:[NSString class]]) - return QString::fromNSString(static_cast(result)); - if ([result isKindOfClass:[NSNumber class]]) - return fromNSNumber(static_cast(result)); - if ([result isKindOfClass:[NSDate class]]) - return QDateTime::fromNSDate(static_cast(result)); - - // JSValue also supports arrays and dictionaries, but we don't handle that yet - return QVariant(); -} - -void QDarwinWebViewPrivate::runJavaScriptPrivate(const QString &script, int callbackId) -{ - [wkWebView evaluateJavaScript:script.toNSString() completionHandler:^(id result, NSError *) { - if (callbackId != -1) - Q_EMIT javaScriptResult(callbackId, fromJSValue(result)); - }]; -} - -QT_END_NAMESPACE diff --git a/src/webview/qwebview_darwin_p.h b/src/webview/qwebview_darwin_p.h deleted file mode 100644 index 2b188e8..0000000 --- a/src/webview/qwebview_darwin_p.h +++ /dev/null @@ -1,121 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: http://www.qt.io/licensing/ -** -** This file is part of the QtWebView module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL3$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see http://www.qt.io/terms-conditions. For further -** information use the contact form at http://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPLv3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or later as published by the Free -** Software Foundation and appearing in the file LICENSE.GPL included in -** the packaging of this file. Please review the following information to -** ensure the GNU General Public License version 2.0 requirements will be -** met: http://www.gnu.org/licenses/gpl-2.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QWEBVIEW_DARWIN_P_H -#define QWEBVIEW_DARWIN_P_H - -// -// W A R N I N G -// ------------- -// -// This file is not part of the Qt API. It exists purely as an -// implementation detail. This header file may change from version to -// version without notice, or even be removed. -// -// We mean it. -// - -#include -#include -#include - -#include "qwebview_p_p.h" - -#if defined(Q_OS_IOS) && defined(__OBJC__) -#include - -@interface QIOSNativeViewSelectedRecognizer : UIGestureRecognizer -{ -@public - QNativeViewController *m_item; -} -- (id)initWithQWindowControllerItem:(QNativeViewController *)item; -@end -#endif - -Q_FORWARD_DECLARE_OBJC_CLASS(WKWebView); - -#ifdef Q_OS_IOS -Q_FORWARD_DECLARE_OBJC_CLASS(UIGestureRecognizer); -#endif - -QT_BEGIN_NAMESPACE - -class QDarwinWebViewPrivate : public QWebViewPrivate -{ - Q_OBJECT -public: - explicit QDarwinWebViewPrivate(QObject *p = 0); - ~QDarwinWebViewPrivate() Q_DECL_OVERRIDE; - - QUrl url() const Q_DECL_OVERRIDE; - void setUrl(const QUrl &url) Q_DECL_OVERRIDE; - bool canGoBack() const Q_DECL_OVERRIDE; - bool canGoForward() const Q_DECL_OVERRIDE; - QString title() const Q_DECL_OVERRIDE; - int loadProgress() const Q_DECL_OVERRIDE; - bool isLoading() const Q_DECL_OVERRIDE; - - void setParentView(QObject *view) Q_DECL_OVERRIDE; - QObject *parentView() const Q_DECL_OVERRIDE; - void setGeometry(const QRect &geometry) Q_DECL_OVERRIDE; - void setVisibility(QWindow::Visibility visibility) Q_DECL_OVERRIDE; - void setVisible(bool visible) Q_DECL_OVERRIDE; - void setFocus(bool focus) Q_DECL_OVERRIDE; - -public Q_SLOTS: - void goBack() Q_DECL_OVERRIDE; - void goForward() Q_DECL_OVERRIDE; - void reload() Q_DECL_OVERRIDE; - void stop() Q_DECL_OVERRIDE; - void loadHtml(const QString &html, const QUrl &baseUrl = QUrl()) Q_DECL_OVERRIDE; - -protected: - void runJavaScriptPrivate(const QString& script, - int callbackId) Q_DECL_OVERRIDE; - -public: - WKWebView *wkWebView; -#ifdef Q_OS_IOS - UIGestureRecognizer *m_recognizer; -#endif - int requestFrameCount; - QPointer m_parentView; -}; - -QT_END_NAMESPACE - -#endif // QWEBVIEW_DARWIN_P_H diff --git a/src/webview/qwebview_p.h b/src/webview/qwebview_p.h index abc8bbf..aa09f03 100644 --- a/src/webview/qwebview_p.h +++ b/src/webview/qwebview_p.h @@ -48,7 +48,7 @@ // We mean it. // -#include "qwebview_p_p.h" +#include "qabstractwebview_p.h" #include "qwebviewinterface_p.h" #include "qnativeviewcontroller_p.h" #include @@ -122,8 +122,7 @@ private: friend class QQuickViewController; friend class QQuickWebView; - Q_DECLARE_PRIVATE(QWebView) - QWebViewPrivate *d_ptr; + QAbstractWebView *d; // provisional data int m_progress; diff --git a/src/webview/qwebview_p_p.h b/src/webview/qwebview_p_p.h deleted file mode 100644 index 45a352b..0000000 --- a/src/webview/qwebview_p_p.h +++ /dev/null @@ -1,83 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2015 The Qt Company Ltd. -** Contact: http://www.qt.io/licensing/ -** -** This file is part of the QtWebView module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL3$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see http://www.qt.io/terms-conditions. For further -** information use the contact form at http://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPLv3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or later as published by the Free -** Software Foundation and appearing in the file LICENSE.GPL included in -** the packaging of this file. Please review the following information to -** ensure the GNU General Public License version 2.0 requirements will be -** met: http://www.gnu.org/licenses/gpl-2.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QWEBVIEW_P_P_H -#define QWEBVIEW_P_P_H - -// -// W A R N I N G -// ------------- -// -// This file is not part of the Qt API. It exists purely as an -// implementation detail. This header file may change from version to -// version without notice, or even be removed. -// -// We mean it. -// - -#include "qwebviewinterface_p.h" -#include "qnativeviewcontroller_p.h" - -QT_BEGIN_NAMESPACE - -class QWebView; -class QWebViewLoadRequestPrivate; - -class Q_WEBVIEW_EXPORT QWebViewPrivate - : public QObject - , public QWebViewInterface - , public QNativeViewController -{ - Q_OBJECT -public: - static QWebViewPrivate *create(QWebView *q); - -Q_SIGNALS: - void titleChanged(const QString &title); - void urlChanged(const QUrl &url); - void loadingChanged(const QWebViewLoadRequestPrivate &loadRequest); - void loadProgressChanged(int progress); - void javaScriptResult(int id, const QVariant &result); - void requestFocus(bool focus); - -protected: - explicit QWebViewPrivate(QObject *p = 0) : QObject(p) { } -}; - -QT_END_NAMESPACE - -#endif // QWEBVIEW_P_P_H - diff --git a/src/webview/qwebview_webengine.cpp b/src/webview/qwebview_webengine.cpp deleted file mode 100644 index dd2e56d..0000000 --- a/src/webview/qwebview_webengine.cpp +++ /dev/null @@ -1,236 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: http://www.qt.io/licensing/ -** -** This file is part of the QtWebView module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL3$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see http://www.qt.io/terms-conditions. For further -** information use the contact form at http://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPLv3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or later as published by the Free -** Software Foundation and appearing in the file LICENSE.GPL included in -** the packaging of this file. Please review the following information to -** ensure the GNU General Public License version 2.0 requirements will be -** met: http://www.gnu.org/licenses/gpl-2.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "qwebview_webengine_p.h" -#include "qwebview_p.h" -#include "qwebviewloadrequest_p.h" - -#include - -#include -#include -#include -#include -#include - -#include - -#include -#include -#include - -#include -#include - -QT_BEGIN_NAMESPACE - -static QByteArray qmlSource() -{ - return QByteArrayLiteral("import QtWebEngine 1.1\n" - " WebEngineView {\n" - "}\n"); -} - -#ifndef Q_OS_MACOS -QWebViewPrivate *QWebViewPrivate::create(QWebView *q) -{ - return new QWebEngineWebViewPrivate(q); -} -#endif - -QWebEngineWebViewPrivate::QWebEngineWebViewPrivate(QObject *p) - : QWebViewPrivate(p) -{ - m_webEngineView.m_parent = this; -} - -QWebEngineWebViewPrivate::~QWebEngineWebViewPrivate() -{ -} - -QUrl QWebEngineWebViewPrivate::url() const -{ - return m_webEngineView->url(); -} - -void QWebEngineWebViewPrivate::setUrl(const QUrl &url) -{ - m_webEngineView->setUrl(url); -} - -void QWebEngineWebViewPrivate::loadHtml(const QString &html, const QUrl &baseUrl) -{ - m_webEngineView->loadHtml(html, baseUrl); -} - -bool QWebEngineWebViewPrivate::canGoBack() const -{ - return m_webEngineView->canGoBack(); -} - -void QWebEngineWebViewPrivate::goBack() -{ - m_webEngineView->goBack(); -} - -bool QWebEngineWebViewPrivate::canGoForward() const -{ - return m_webEngineView->canGoForward(); -} - -void QWebEngineWebViewPrivate::goForward() -{ - m_webEngineView->goForward(); -} - -void QWebEngineWebViewPrivate::reload() -{ - m_webEngineView->reload(); -} - -QString QWebEngineWebViewPrivate::title() const -{ - return m_webEngineView->title(); -} - -void QWebEngineWebViewPrivate::setGeometry(const QRect &geometry) -{ - m_webEngineView->setSize(geometry.size()); -} - -void QWebEngineWebViewPrivate::setVisibility(QWindow::Visibility visibility) -{ - setVisible(visibility != QWindow::Hidden ? true : false); -} - -void QWebEngineWebViewPrivate::runJavaScriptPrivate(const QString &script, - int callbackId) -{ - m_webEngineView->runJavaScript(script, QQuickWebView::takeCallback(callbackId)); -} - -void QWebEngineWebViewPrivate::setVisible(bool visible) -{ - m_webEngineView->setVisible(visible); -} - -void QWebEngineWebViewPrivate::setFocus(bool focus) -{ - if (focus) - m_webEngineView->forceActiveFocus(); -} - -int QWebEngineWebViewPrivate::loadProgress() const -{ - return m_webEngineView->loadProgress(); -} - -bool QWebEngineWebViewPrivate::isLoading() const -{ - return m_webEngineView->isLoading(); -} - -void QWebEngineWebViewPrivate::setParentView(QObject *parentView) -{ - Q_UNUSED(parentView); -} - -QObject *QWebEngineWebViewPrivate::parentView() const -{ - return m_webEngineView->window(); -} - -void QWebEngineWebViewPrivate::stop() -{ - m_webEngineView->stop(); -} - -void QWebEngineWebViewPrivate::q_urlChanged() -{ - Q_EMIT urlChanged(m_webEngineView->url()); -} - -void QWebEngineWebViewPrivate::q_loadProgressChanged() -{ - Q_EMIT loadProgressChanged(m_webEngineView->loadProgress()); -} - -void QWebEngineWebViewPrivate::q_titleChanged() -{ - Q_EMIT titleChanged(m_webEngineView->title()); -} - -void QWebEngineWebViewPrivate::q_loadingChanged(QQuickWebEngineLoadRequest *loadRequest) -{ - QWebViewLoadRequestPrivate lr(loadRequest->url(), - static_cast(loadRequest->status()), // These "should" match... - loadRequest->errorString()); - - Q_EMIT loadingChanged(lr); -} - -void QWebEngineWebViewPrivate::QQuickWebEngineViewPtr::init() const -{ - Q_ASSERT(!m_webEngineView); - QObject *p = qobject_cast(m_parent); - QQuickItem *parentItem = nullptr; - while (p) { - p = p->parent(); - parentItem = qobject_cast(p); - if (parentItem) - break; - } - - if (!parentItem) - return; - - QQmlEngine *engine = qmlEngine(parentItem); - if (!engine) - return; - - QQmlComponent *component = new QQmlComponent(engine); - component->setData(qmlSource(), QUrl::fromLocalFile(QLatin1String(""))); - QQuickWebEngineView *webEngineView = qobject_cast(component->create()); - Q_ASSERT(webEngineView); - QObject::connect(webEngineView, &QQuickWebEngineView::urlChanged, m_parent, &QWebEngineWebViewPrivate::q_urlChanged); - QObject::connect(webEngineView, &QQuickWebEngineView::loadProgressChanged, m_parent, &QWebEngineWebViewPrivate::q_loadProgressChanged); - QObject::connect(webEngineView, &QQuickWebEngineView::loadingChanged, m_parent, &QWebEngineWebViewPrivate::q_loadingChanged); - QObject::connect(webEngineView, &QQuickWebEngineView::titleChanged, m_parent, &QWebEngineWebViewPrivate::q_titleChanged); - webEngineView->setParentItem(parentItem); - m_webEngineView.reset(webEngineView); -} - -QT_END_NAMESPACE diff --git a/src/webview/qwebview_webengine_p.h b/src/webview/qwebview_webengine_p.h deleted file mode 100644 index 16dd773..0000000 --- a/src/webview/qwebview_webengine_p.h +++ /dev/null @@ -1,121 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: http://www.qt.io/licensing/ -** -** This file is part of the QtWebView module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL3$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see http://www.qt.io/terms-conditions. For further -** information use the contact form at http://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPLv3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or later as published by the Free -** Software Foundation and appearing in the file LICENSE.GPL included in -** the packaging of this file. Please review the following information to -** ensure the GNU General Public License version 2.0 requirements will be -** met: http://www.gnu.org/licenses/gpl-2.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QWEBVIEW_ANDROID_P_H -#define QWEBVIEW_ANDROID_P_H - -// -// W A R N I N G -// ------------- -// -// This file is not part of the Qt API. It exists purely as an -// implementation detail. This header file may change from version to -// version without notice, or even be removed. -// -// We mean it. -// - -#include -#include -#include - -#include - -#include "qwebview_p_p.h" - -QT_BEGIN_NAMESPACE - -class QQuickWebEngineView; -class QQuickWebEngineLoadRequest; - -class QWebEngineWebViewPrivate : public QWebViewPrivate -{ - Q_OBJECT -public: - explicit QWebEngineWebViewPrivate(QObject *p = 0); - ~QWebEngineWebViewPrivate() Q_DECL_OVERRIDE; - - QUrl url() const Q_DECL_OVERRIDE; - void setUrl(const QUrl &url) Q_DECL_OVERRIDE; - bool canGoBack() const Q_DECL_OVERRIDE; - bool canGoForward() const Q_DECL_OVERRIDE; - QString title() const Q_DECL_OVERRIDE; - int loadProgress() const Q_DECL_OVERRIDE; - bool isLoading() const Q_DECL_OVERRIDE; - - void setParentView(QObject *parentView) Q_DECL_OVERRIDE; - QObject *parentView() const Q_DECL_OVERRIDE; - void setGeometry(const QRect &geometry) Q_DECL_OVERRIDE; - void setVisibility(QWindow::Visibility visibility) Q_DECL_OVERRIDE; - void setVisible(bool visible) Q_DECL_OVERRIDE; - void setFocus(bool focus) Q_DECL_OVERRIDE; - -public Q_SLOTS: - void goBack() Q_DECL_OVERRIDE; - void goForward() Q_DECL_OVERRIDE; - void reload() Q_DECL_OVERRIDE; - void stop() Q_DECL_OVERRIDE; - void loadHtml(const QString &html, const QUrl &baseUrl = QUrl()) Q_DECL_OVERRIDE; - -private Q_SLOTS: - void q_urlChanged(); - void q_loadProgressChanged(); - void q_titleChanged(); - void q_loadingChanged(QQuickWebEngineLoadRequest *loadRequest); - -protected: - void runJavaScriptPrivate(const QString& script, - int callbackId) Q_DECL_OVERRIDE; - -private: - struct QQuickWebEngineViewPtr - { - inline QQuickWebEngineView *operator->() const - { - if (!m_webEngineView) - init(); - return m_webEngineView.data(); - } - void init() const; - - QWebEngineWebViewPrivate *m_parent; - mutable QScopedPointer m_webEngineView; - } m_webEngineView; -}; - -QT_END_NAMESPACE - -#endif // QWEBVIEW_ANDROID_P_H diff --git a/src/webview/qwebview_winrt.cpp b/src/webview/qwebview_winrt.cpp deleted file mode 100644 index fc999d2..0000000 --- a/src/webview/qwebview_winrt.cpp +++ /dev/null @@ -1,687 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2015 The Qt Company Ltd. -** Contact: http://www.qt.io/licensing/ -** -** This file is part of the QtWebView module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL3$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see http://www.qt.io/terms-conditions. For further -** information use the contact form at http://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPLv3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or later as published by the Free -** Software Foundation and appearing in the file LICENSE.GPL included in -** the packaging of this file. Please review the following information to -** ensure the GNU General Public License version 2.0 requirements will be -** met: http://www.gnu.org/licenses/gpl-2.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "qwebview_winrt_p.h" -#include "qwebviewloadrequest_p.h" - -#include - -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include - -using namespace Microsoft::WRL; -using namespace Microsoft::WRL::Wrappers; -using namespace ABI::Windows::Foundation; -using namespace ABI::Windows::Foundation::Collections; -using namespace ABI::Windows::Graphics::Display; -using namespace ABI::Windows::System; -using namespace ABI::Windows::UI; -using namespace ABI::Windows::UI::Xaml; -using namespace ABI::Windows::UI::Xaml::Controls; -using namespace ABI::Windows::UI::Xaml::Markup; -using namespace ABI::Windows::Web; - -class HStringListIterator : public RuntimeClass, IIterator> -{ -public: - HStringListIterator(HSTRING *data, int size) : data(data), size(size), pos(0) - { - } - - HRESULT __stdcall get_Current(HSTRING *current) override - { - *current = pos >= size ? nullptr : data[pos]; - return S_OK; - } - - HRESULT __stdcall get_HasCurrent(boolean *hasCurrent) override - { - *hasCurrent = pos < size; - return S_OK; - } - - HRESULT __stdcall MoveNext(boolean *hasCurrent) override - { - *hasCurrent = ++pos < size; - return S_OK; - } - - HRESULT __stdcall GetMany(unsigned capacity, HSTRING *value, unsigned *actual) - { - unsigned i = 0; - for (; i < qMin(capacity, unsigned(size)); ++i) - value[i] = data[pos + i]; - *actual = i; - pos += i; - return S_OK; - } - -private: - HSTRING *data; - int size; - int pos; -}; - -class HStringList : public RuntimeClass, IIterable> -{ -public: - HStringList(const QList &stringList) - { - d.resize(stringList.size()); - for (int i = 0; i < stringList.size(); ++i) { - const QString qString = stringList.at(i).trimmed(); - HStringReference hString(reinterpret_cast(qString.utf16()), qString.length()); - hString.CopyTo(&d[i++]); - } - } - - ~HStringList() - { - for (const HSTRING &hString : qAsConst(d)) - WindowsDeleteString(hString); - } - - HRESULT __stdcall First(IIterator **first) override - { - ComPtr it = Make(d.data(), d.size()); - return it.Get()->QueryInterface(IID_PPV_ARGS(first)); - } - -private: - QVector d; -}; - -static QUrl qurlFromUri(IUriRuntimeClass *uri) -{ - HRESULT hr; - HString uriString; - hr = uri->get_AbsoluteUri(uriString.GetAddressOf()); - Q_ASSERT_SUCCEEDED(hr); - quint32 uriStringLength; - const wchar_t *uriStringBuffer = uriString.GetRawBuffer(&uriStringLength); - return QUrl(QString::fromWCharArray(uriStringBuffer, uriStringLength)); -} - -static QString webErrorStatusString(WebErrorStatus status) -{ - switch (status) { - case WebErrorStatus_Unknown: - return QStringLiteral("Unknown"); - case WebErrorStatus_CertificateCommonNameIsIncorrect: - return QStringLiteral("CertificateCommonNameIsIncorrect"); - case WebErrorStatus_CertificateExpired: - return QStringLiteral("CertificateExpired"); - case WebErrorStatus_CertificateContainsErrors: - return QStringLiteral("CertificateContainsErrors"); - case WebErrorStatus_CertificateRevoked: - return QStringLiteral("CertificateRevoked"); - case WebErrorStatus_CertificateIsInvalid: - return QStringLiteral("CertificateIsInvalid"); - case WebErrorStatus_ServerUnreachable: - return QStringLiteral("ServerUnreachable"); - case WebErrorStatus_Timeout: - return QStringLiteral("Timeout"); - case WebErrorStatus_ErrorHttpInvalidServerResponse: - return QStringLiteral("ErrorHttpInvalidServerResponse"); - case WebErrorStatus_ConnectionAborted: - return QStringLiteral("ConnectionAborted"); - case WebErrorStatus_ConnectionReset: - return QStringLiteral("ConnectionReset"); - case WebErrorStatus_Disconnected: - return QStringLiteral("Disconnected"); - case WebErrorStatus_HttpToHttpsOnRedirection: - return QStringLiteral("HttpToHttpsOnRedirection"); - case WebErrorStatus_HttpsToHttpOnRedirection: - return QStringLiteral("HttpsToHttpOnRedirection"); - case WebErrorStatus_CannotConnect: - return QStringLiteral("CannotConnect"); - case WebErrorStatus_HostNameNotResolved: - return QStringLiteral("HostNameNotResolved"); - case WebErrorStatus_OperationCanceled: - return QStringLiteral("OperationCanceled"); - case WebErrorStatus_RedirectFailed: - return QStringLiteral("RedirectFailed"); - case WebErrorStatus_UnexpectedStatusCode: - return QStringLiteral("UnexpectedStatusCode"); - case WebErrorStatus_UnexpectedRedirection: - return QStringLiteral("UnexpectedRedirection"); - case WebErrorStatus_UnexpectedClientError: - return QStringLiteral("UnexpectedClientError"); - case WebErrorStatus_UnexpectedServerError: - return QStringLiteral("UnexpectedServerError"); - case WebErrorStatus_MultipleChoices: - return QStringLiteral("MultipleChoices"); - case WebErrorStatus_MovedPermanently: - return QStringLiteral("MovedPermanently"); - case WebErrorStatus_Found: - return QStringLiteral("Found"); - case WebErrorStatus_SeeOther: - return QStringLiteral("SeeOther"); - case WebErrorStatus_NotModified: - return QStringLiteral("NotModified"); - case WebErrorStatus_UseProxy: - return QStringLiteral("UseProxy"); - case WebErrorStatus_TemporaryRedirect: - return QStringLiteral("TemporaryRedirect"); - case WebErrorStatus_BadRequest: - return QStringLiteral("BadRequest"); - case WebErrorStatus_Unauthorized: - return QStringLiteral("Unauthorized"); - case WebErrorStatus_PaymentRequired: - return QStringLiteral("PaymentRequired"); - case WebErrorStatus_Forbidden: - return QStringLiteral("Forbidden"); - case WebErrorStatus_NotFound: - return QStringLiteral("NotFound"); - case WebErrorStatus_MethodNotAllowed: - return QStringLiteral("MethodNotAllowed"); - case WebErrorStatus_NotAcceptable: - return QStringLiteral("NotAcceptable"); - case WebErrorStatus_ProxyAuthenticationRequired: - return QStringLiteral("ProxyAuthenticationRequired"); - case WebErrorStatus_RequestTimeout: - return QStringLiteral("RequestTimeout"); - case WebErrorStatus_Conflict: - return QStringLiteral("Conflict"); - case WebErrorStatus_Gone: - return QStringLiteral("Gone"); - case WebErrorStatus_LengthRequired: - return QStringLiteral("LengthRequired"); - case WebErrorStatus_PreconditionFailed: - return QStringLiteral("PreconditionFailed"); - case WebErrorStatus_RequestEntityTooLarge: - return QStringLiteral("RequestEntityTooLarge"); - case WebErrorStatus_RequestUriTooLong: - return QStringLiteral("RequestUriTooLong"); - case WebErrorStatus_UnsupportedMediaType: - return QStringLiteral("UnsupportedMediaType"); - case WebErrorStatus_RequestedRangeNotSatisfiable: - return QStringLiteral("RequestedRangeNotSatisfiable"); - case WebErrorStatus_ExpectationFailed: - return QStringLiteral("ExpectationFailed"); - case WebErrorStatus_InternalServerError: - return QStringLiteral("InternalServerError"); - case WebErrorStatus_NotImplemented: - return QStringLiteral("NotImplemented"); - case WebErrorStatus_BadGateway: - return QStringLiteral("BadGateway"); - case WebErrorStatus_ServiceUnavailable: - return QStringLiteral("ServiceUnavailable"); - case WebErrorStatus_GatewayTimeout: - return QStringLiteral("GatewayTimeout"); - case WebErrorStatus_HttpVersionNotSupported: - return QStringLiteral("HttpVersionNotSupported"); - default: - break; - } - return QString(); -} - -QWebViewPrivate *QWebViewPrivate::create(QWebView *q) -{ - return new QWinRTWebViewPrivate(q); -} - -struct WinRTWebView -{ - ComPtr base; - ComPtr ext; - ComPtr host; - - ComPtr canvas; - ComPtr uriFactory; - ComPtr displayInformation; - ComPtr launcherStatics; - - QPointer window; - QHash *, int> callbacks; - - EventRegistrationToken navigationStartingToken; - EventRegistrationToken navigationCompletedToken; - bool isLoading : 1; -}; - -#define LSTRING(str) L#str -static const wchar_t webviewXaml[] = LSTRING( - -); - -QWinRTWebViewPrivate::QWinRTWebViewPrivate(QObject *parent) - : QWebViewPrivate(parent), d(new WinRTWebView) -{ - d->isLoading = false; - - QEventDispatcherWinRT::runOnXamlThread([this]() { - HRESULT hr; - ComPtr xamlReader; - hr = RoGetActivationFactory(HString::MakeReference(RuntimeClass_Windows_UI_Xaml_Markup_XamlReader).Get(), - IID_PPV_ARGS(&xamlReader)); - Q_ASSERT_SUCCEEDED(hr); - - // Directly instantiating a WebView works, but it throws an exception - // when navigating. Using a XamlReader appears to set it up properly. - ComPtr element; - hr = xamlReader->Load(HString::MakeReference(webviewXaml).Get(), &element); - Q_ASSERT_SUCCEEDED(hr); - hr = element.As(&d->base); - Q_ASSERT_SUCCEEDED(hr); - hr = d->base.As(&d->ext); - Q_ASSERT_SUCCEEDED(hr); - hr = RoGetActivationFactory(HString::MakeReference(RuntimeClass_Windows_System_Launcher).Get(), - IID_PPV_ARGS(&d->launcherStatics)); - Q_ASSERT_SUCCEEDED(hr); - - hr = d->ext->add_NavigationStarting( - Callback>(this, &QWinRTWebViewPrivate::onNavigationStarted).Get(), - &d->navigationStartingToken); - Q_ASSERT_SUCCEEDED(hr); - hr = d->ext->add_NavigationCompleted( - Callback>(this, &QWinRTWebViewPrivate::onNavigationCompleted).Get(), - &d->navigationCompletedToken); - Q_ASSERT_SUCCEEDED(hr); - - ComPtr displayInformationStatics; - hr = RoGetActivationFactory(HString::MakeReference(RuntimeClass_Windows_Graphics_Display_DisplayInformation).Get(), - IID_PPV_ARGS(&displayInformationStatics)); - Q_ASSERT_SUCCEEDED(hr); - hr = displayInformationStatics->GetForCurrentView(&d->displayInformation); - Q_ASSERT_SUCCEEDED(hr); - return hr; - }); - - HRESULT hr; - hr = RoGetActivationFactory(HString::MakeReference(RuntimeClass_Windows_UI_Xaml_Controls_Canvas).Get(), - IID_PPV_ARGS(&d->canvas)); - Q_ASSERT_SUCCEEDED(hr); - hr = RoGetActivationFactory(HString::MakeReference(RuntimeClass_Windows_Foundation_Uri).Get(), - IID_PPV_ARGS(&d->uriFactory)); - Q_ASSERT_SUCCEEDED(hr); -} - -QWinRTWebViewPrivate::~QWinRTWebViewPrivate() -{ - QEventDispatcherWinRT::runOnXamlThread([this]() { - HRESULT hr; - hr = d->ext->remove_NavigationStarting(d->navigationStartingToken); - Q_ASSERT_SUCCEEDED(hr); - hr = d->ext->remove_NavigationCompleted(d->navigationCompletedToken); - Q_ASSERT_SUCCEEDED(hr); - ComPtr> children; - hr = d->host->get_Children(&children); - Q_ASSERT_SUCCEEDED(hr); - ComPtr uiElement; - hr = d->base.As(&uiElement); - Q_ASSERT_SUCCEEDED(hr); - quint32 index; - boolean found; - hr = children->IndexOf(uiElement.Get(), &index, &found); - Q_ASSERT_SUCCEEDED(hr); - if (found) { - hr = children->RemoveAt(index); - Q_ASSERT_SUCCEEDED(hr); - } - return hr; - }); -} - -QUrl QWinRTWebViewPrivate::url() const -{ - ComPtr uri; - QEventDispatcherWinRT::runOnXamlThread([this, &uri]() { - HRESULT hr; - hr = d->base->get_Source(&uri); - Q_ASSERT_SUCCEEDED(hr); - return hr; - }); - return qurlFromUri(uri.Get()); -} - -void QWinRTWebViewPrivate::setUrl(const QUrl &url) -{ - QEventDispatcherWinRT::runOnXamlThread([this, &url]() { - HRESULT hr; - const QString urlString = url.toString(); - ComPtr uri; - HStringReference uriString(reinterpret_cast(urlString.utf16()), - urlString.length()); - hr = d->uriFactory->CreateUri(uriString.Get(), &uri); - Q_ASSERT_SUCCEEDED(hr); - hr = d->base->Navigate(uri.Get()); - // Directly running into an abort means, that the URI is not supported. Ask the user what to do - if (hr == E_ABORT) { - ComPtr> op; - hr = d->launcherStatics->LaunchUriAsync(uri.Get(), &op); - } - Q_ASSERT_SUCCEEDED(hr); - return hr; - }); -} - -bool QWinRTWebViewPrivate::canGoBack() const -{ - boolean canGoBack; - QEventDispatcherWinRT::runOnXamlThread([this, &canGoBack]() { - HRESULT hr; - hr = d->ext->get_CanGoBack(&canGoBack); - Q_ASSERT_SUCCEEDED(hr); - return hr; - }); - return canGoBack; -} - -bool QWinRTWebViewPrivate::canGoForward() const -{ - boolean canGoForward; - QEventDispatcherWinRT::runOnXamlThread([this, &canGoForward]() { - HRESULT hr; - hr = d->ext->get_CanGoForward(&canGoForward); - Q_ASSERT_SUCCEEDED(hr); - return hr; - }); - return canGoForward; -} - -QString QWinRTWebViewPrivate::title() const -{ - HString title; - QEventDispatcherWinRT::runOnXamlThread([this, &title]() { - HRESULT hr; - hr = d->ext->get_DocumentTitle(title.GetAddressOf()); - Q_ASSERT_SUCCEEDED(hr); - return hr; - }); - quint32 titleLength; - const wchar_t *titleBuffer = title.GetRawBuffer(&titleLength); - return QString::fromWCharArray(titleBuffer, titleLength); -} - -int QWinRTWebViewPrivate::loadProgress() const -{ - return d->isLoading ? 0 : 100; -} - -bool QWinRTWebViewPrivate::isLoading() const -{ - return d->isLoading; -} - -void QWinRTWebViewPrivate::setParentView(QObject *view) -{ - d->window = qobject_cast(view); - if (!d->window) - return; - - ComPtr host = reinterpret_cast(d->window->winId()); - if (!host) - return; - - QEventDispatcherWinRT::runOnXamlThread([this, &host]() { - HRESULT hr; - ComPtr frameworkHost; - hr = host.As(&frameworkHost); - RETURN_HR_IF_FAILED("Failed to cast the window ID to IFrameworkElement"); - ComPtr parent; - hr = frameworkHost->get_Parent(&parent); - RETURN_HR_IF_FAILED("Failed to get the parent object of the window"); - hr = parent.As(&d->host); - RETURN_HR_IF_FAILED("Failed to cast the window container to IPanel"); - ComPtr> children; - hr = d->host->get_Children(&children); - Q_ASSERT_SUCCEEDED(hr); - ComPtr uiElement; - hr = d->base.As(&uiElement); - Q_ASSERT_SUCCEEDED(hr); - hr = children->Append(uiElement.Get()); - Q_ASSERT_SUCCEEDED(hr); - return hr; - }); -} - -QObject *QWinRTWebViewPrivate::parentView() const -{ - return d->window; -} - -void QWinRTWebViewPrivate::setGeometry(const QRect &geometry) -{ - QEventDispatcherWinRT::runOnXamlThread([this, &geometry]() { - HRESULT hr; - double scaleFactor; -#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_PHONE_APP) - ComPtr displayInformation; - hr = d->displayInformation.As(&displayInformation); - Q_ASSERT_SUCCEEDED(hr); - hr = displayInformation->get_RawPixelsPerViewPixel(&scaleFactor); - Q_ASSERT_SUCCEEDED(hr); - scaleFactor = 1.0 / scaleFactor; - Q_ASSERT(d->window); - const QScreen *screen = d->window->screen(); - Q_ASSERT(screen); - const QPoint screenTopLeft = screen->availableGeometry().topLeft(); - const QPointF topLeft = QHighDpi::toNativePixels(QPointF(geometry.topLeft() + screenTopLeft) * scaleFactor, screen); - const QSizeF size = QHighDpi::toNativePixels(QSizeF(geometry.size()) * scaleFactor, screen); -#else - ResolutionScale resolutionScale; - hr = d->displayInformation->get_ResolutionScale(&resolutionScale); - Q_ASSERT_SUCCEEDED(hr); - scaleFactor = 100.0 / double(resolutionScale); - const QPointF topLeft = QPointF(geometry.topLeft()) * scaleFactor; - const QSizeF size = QSizeF(geometry.size()) * scaleFactor; -#endif - ComPtr uiElement; - hr = d->base.As(&uiElement); - Q_ASSERT_SUCCEEDED(hr); - hr = d->canvas->SetLeft(uiElement.Get(), topLeft.x()); - Q_ASSERT_SUCCEEDED(hr); - hr = d->canvas->SetTop(uiElement.Get(), topLeft.y()); - Q_ASSERT_SUCCEEDED(hr); - ComPtr frameworkElement; - hr = d->base.As(&frameworkElement); - Q_ASSERT_SUCCEEDED(hr); - hr = frameworkElement->put_Width(size.width()); - Q_ASSERT_SUCCEEDED(hr); - hr = frameworkElement->put_Height(size.height()); - Q_ASSERT_SUCCEEDED(hr); - return hr; - }); -} - -void QWinRTWebViewPrivate::setVisibility(QWindow::Visibility visibility) -{ - setVisible(visibility != QWindow::Hidden); -} - -void QWinRTWebViewPrivate::setVisible(bool visible) -{ - QEventDispatcherWinRT::runOnXamlThread([this, &visible]() { - HRESULT hr; - ComPtr uiElement; - hr = d->base.As(&uiElement); - Q_ASSERT_SUCCEEDED(hr); - hr = uiElement->put_Visibility(visible ? Visibility_Visible : Visibility_Collapsed); - Q_ASSERT_SUCCEEDED(hr); - return hr; - }); -} - -void QWinRTWebViewPrivate::goBack() -{ - QEventDispatcherWinRT::runOnXamlThread([this]() { - HRESULT hr; - hr = d->ext->GoBack(); - Q_ASSERT_SUCCEEDED(hr); - return hr; - }); -} - -void QWinRTWebViewPrivate::goForward() -{ - QEventDispatcherWinRT::runOnXamlThread([this]() { - HRESULT hr; - hr = d->ext->GoForward(); - Q_ASSERT_SUCCEEDED(hr); - return hr; - }); -} - -void QWinRTWebViewPrivate::reload() -{ - QEventDispatcherWinRT::runOnXamlThread([this]() { - HRESULT hr; - hr = d->ext->Refresh(); - Q_ASSERT_SUCCEEDED(hr); - return hr; - }); -} - -void QWinRTWebViewPrivate::stop() -{ - QEventDispatcherWinRT::runOnXamlThread([this]() { - HRESULT hr; - hr = d->ext->Stop(); - Q_ASSERT_SUCCEEDED(hr); - return hr; - }); -} - -void QWinRTWebViewPrivate::loadHtml(const QString &html, const QUrl &baseUrl) -{ - if (!baseUrl.isEmpty()) - qWarning("Base URLs for loadHtml() are not supported under WinRT."); - - HRESULT hr; - HStringReference htmlText(reinterpret_cast(html.utf16()), html.length()); - hr = d->base->NavigateToString(htmlText.Get()); - Q_ASSERT_SUCCEEDED(hr); -} - -void QWinRTWebViewPrivate::runJavaScriptPrivate(const QString &script, int callbackId) -{ - static QRegularExpression functionTemplate(QStringLiteral("^(.*)\\((.*)\\)[\\s;]*?$")); - QRegularExpressionMatch match = functionTemplate.match(script); - if (!match.hasMatch()) { - qWarning("The WinRT WebView only supports calling global functions, so please make your call" - " in the form myFunction(a, b, c). Also note that only string arguments can be passed."); - return; - } - - const QString method = match.captured(1).trimmed(); - HStringReference methodString(reinterpret_cast(method.utf16()), method.length()); - ComPtr argumentStrings = Make(match.captured(2).split(QLatin1Char(','))); - QEventDispatcherWinRT::runOnXamlThread([this, &methodString, &argumentStrings, &callbackId]() { - HRESULT hr; - ComPtr> op; - hr = d->ext->InvokeScriptAsync(methodString.Get(), argumentStrings.Get(), &op); - Q_ASSERT_SUCCEEDED(hr); - - d->callbacks.insert(op.Get(), callbackId); - hr = op->put_Completed(Callback>([this](IAsyncOperation *op, AsyncStatus status) { - int callbackId = d->callbacks.take(op); - HRESULT hr; - if (status != Completed) { - ComPtr info; - hr = op->QueryInterface(IID_PPV_ARGS(&info)); - Q_ASSERT_SUCCEEDED(hr); - HRESULT errorCode; - hr = info->get_ErrorCode(&errorCode); - Q_ASSERT_SUCCEEDED(hr); - emit javaScriptResult(callbackId, qt_error_string(errorCode)); - return S_OK; - } - HString result; - hr = op->GetResults(result.GetAddressOf()); - Q_ASSERT_SUCCEEDED(hr); - quint32 resultLength; - const wchar_t *resultBuffer = result.GetRawBuffer(&resultLength); - emit javaScriptResult(callbackId, QString::fromWCharArray(resultBuffer, resultLength)); - return S_OK; - }).Get()); - Q_ASSERT_SUCCEEDED(hr); - return hr; - }); -} - -HRESULT QWinRTWebViewPrivate::onNavigationStarted(IWebView *, IWebViewNavigationStartingEventArgs *args) -{ - d->isLoading = true; - HRESULT hr; - ComPtr uri; - hr = args->get_Uri(&uri); - Q_ASSERT_SUCCEEDED(hr); - const QUrl url = qurlFromUri(uri.Get()); - - emit loadingChanged(QWebViewLoadRequestPrivate(url, QWebView::LoadStartedStatus, QString())); - emit loadProgressChanged(0); - return S_OK; -} - -HRESULT QWinRTWebViewPrivate::onNavigationCompleted(IWebView *, IWebViewNavigationCompletedEventArgs *args) -{ - d->isLoading = false; - HRESULT hr; - ComPtr uri; - hr = args->get_Uri(&uri); - Q_ASSERT_SUCCEEDED(hr); - const QUrl url = qurlFromUri(uri.Get()); - - boolean isSuccess; - hr = args->get_IsSuccess(&isSuccess); - Q_ASSERT_SUCCEEDED(hr); - const QWebView::LoadStatus status = isSuccess ? QWebView::LoadSucceededStatus : QWebView::LoadFailedStatus; - - WebErrorStatus errorStatus; - hr = args->get_WebErrorStatus(&errorStatus); - Q_ASSERT_SUCCEEDED(hr); - const QString errorString = webErrorStatusString(errorStatus); - - emit loadingChanged(QWebViewLoadRequestPrivate(url, status, errorString)); - emit titleChanged(title()); - emit loadProgressChanged(100); - return S_OK; -} diff --git a/src/webview/qwebview_winrt_p.h b/src/webview/qwebview_winrt_p.h deleted file mode 100644 index 5dc9f40..0000000 --- a/src/webview/qwebview_winrt_p.h +++ /dev/null @@ -1,109 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2015 The Qt Company Ltd. -** Contact: http://www.qt.io/licensing/ -** -** This file is part of the QtWebView module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL3$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see http://www.qt.io/terms-conditions. For further -** information use the contact form at http://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPLv3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or later as published by the Free -** Software Foundation and appearing in the file LICENSE.GPL included in -** the packaging of this file. Please review the following information to -** ensure the GNU General Public License version 2.0 requirements will be -** met: http://www.gnu.org/licenses/gpl-2.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QWEBVIEW_WINRT_P_H -#define QWEBVIEW_WINRT_P_H - -// -// W A R N I N G -// ------------- -// -// This file is not part of the Qt API. It exists purely as an -// implementation detail. This header file may change from version to -// version without notice, or even be removed. -// -// We mean it. -// - -#include "qwebview_p.h" - -namespace ABI { - namespace Windows { - namespace UI { - namespace Xaml { - namespace Controls { - struct IWebView; - struct IWebViewNavigationStartingEventArgs; - struct IWebViewNavigationCompletedEventArgs; - } - } - } - } -} - -QT_BEGIN_NAMESPACE - -struct WinRTWebView; -class QWinRTWebViewPrivate : public QWebViewPrivate -{ - Q_OBJECT -public: - explicit QWinRTWebViewPrivate(QObject *parent = nullptr); - ~QWinRTWebViewPrivate() Q_DECL_OVERRIDE; - - QUrl url() const Q_DECL_OVERRIDE; - void setUrl(const QUrl &url) Q_DECL_OVERRIDE; - bool canGoBack() const Q_DECL_OVERRIDE; - bool canGoForward() const Q_DECL_OVERRIDE; - QString title() const Q_DECL_OVERRIDE; - int loadProgress() const Q_DECL_OVERRIDE; - bool isLoading() const Q_DECL_OVERRIDE; - - void setParentView(QObject *view) Q_DECL_OVERRIDE; - QObject *parentView() const Q_DECL_OVERRIDE; - void setGeometry(const QRect &geometry) Q_DECL_OVERRIDE; - void setVisibility(QWindow::Visibility visibility) Q_DECL_OVERRIDE; - void setVisible(bool visible) Q_DECL_OVERRIDE; - -public Q_SLOTS: - void goBack() Q_DECL_OVERRIDE; - void goForward() Q_DECL_OVERRIDE; - void reload() Q_DECL_OVERRIDE; - void stop() Q_DECL_OVERRIDE; - void loadHtml(const QString &html, const QUrl &baseUrl = QUrl()) Q_DECL_OVERRIDE; - -protected: - void runJavaScriptPrivate(const QString &script, int callbackId) Q_DECL_OVERRIDE; - -private: - HRESULT onNavigationStarted(ABI::Windows::UI::Xaml::Controls::IWebView *, ABI::Windows::UI::Xaml::Controls::IWebViewNavigationStartingEventArgs *); - HRESULT onNavigationCompleted(ABI::Windows::UI::Xaml::Controls::IWebView *, ABI::Windows::UI::Xaml::Controls::IWebViewNavigationCompletedEventArgs *); - QScopedPointer d; -}; - -QT_END_NAMESPACE - -#endif // QWEBVIEW_WINRT_P_H diff --git a/src/webview/qwebviewfactory.cpp b/src/webview/qwebviewfactory.cpp new file mode 100644 index 0000000..7a22fd1 --- /dev/null +++ b/src/webview/qwebviewfactory.cpp @@ -0,0 +1,130 @@ +/**************************************************************************** +** +** Copyright (C) 2018 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtWebView module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qwebviewfactory_p.h" +#include "qwebviewplugin_p.h" +#include +#include + +QT_BEGIN_NAMESPACE + +Q_GLOBAL_STATIC_WITH_ARGS(QFactoryLoader, loader, (QWebViewPluginInterface_iid, QLatin1String("/webview"))) + +static QString getPluginName() +{ + static const QString name = !qEnvironmentVariableIsEmpty("QT_WEBVIEW_PLUGIN") + ? QString::fromLatin1(qgetenv("QT_WEBVIEW_PLUGIN")) +#ifdef Q_OS_MACOS + : QStringLiteral("webengine"); +#else + : QStringLiteral("native"); +#endif // Q_OS_MACOS + return name; +} + +class QNullWebView : public QAbstractWebView +{ +public: + void setParentView(QObject *view) override { Q_UNUSED(view); } + QObject *parentView() const override { return nullptr; } + void setGeometry(const QRect &geometry) override { Q_UNUSED(geometry); } + void setVisibility(QWindow::Visibility visibility) override { Q_UNUSED(visibility); } + void setVisible(bool visible) override { Q_UNUSED(visible); } + + QUrl url() const override { return QUrl(); } + void setUrl(const QUrl &url) override { Q_UNUSED(url); } + bool canGoBack() const override { return false; } + bool canGoForward() const override { return false; } + QString title() const override { return QString(); } + int loadProgress() const override { return 0; } + bool isLoading() const override { return false; } + void goBack() override { } + void goForward() override { } + void stop() override { } + void reload() override { } + void loadHtml(const QString &html, const QUrl &baseUrl) override + { Q_UNUSED(html); Q_UNUSED(baseUrl); } + void runJavaScriptPrivate(const QString &script, int callbackId) override + { Q_UNUSED(script); Q_UNUSED(callbackId); } +}; + +QAbstractWebView *QWebViewFactory::createWebView() +{ + QAbstractWebView *wv = nullptr; + QWebViewPlugin *plugin = getPlugin(); + if (plugin) + wv = plugin->create(QStringLiteral("webview")); + + if (!wv || !plugin) { + qWarning("No WebView plug-in found!"); + wv = new QNullWebView; + } + + return wv; +} + +bool QWebViewFactory::requiresExtraInitializationSteps() +{ + const QString pluginName = getPluginName(); + const int index = pluginName.isEmpty() ? 0 : qMax(0, loader->indexOf(pluginName)); + + const auto metaDataList = loader->metaData(); + if (metaDataList.isEmpty()) + return false; + + const auto &pluginMetaData = metaDataList.at(index); + const auto iid = pluginMetaData.value(QLatin1String("IID")); + Q_ASSERT(iid == QJsonValue(QLatin1String(QWebViewPluginInterface_iid))); + const auto metaDataObject = pluginMetaData.value(QLatin1String("MetaData")).toObject(); + const auto it = metaDataObject.find(QLatin1String("RequiresInit")); + if (it != pluginMetaData.constEnd()) + return it->isBool() ? it->toBool() : false; + + return false; +} + +QWebViewPlugin *QWebViewFactory::getPlugin() +{ + // Plugin loading logic: + // 1. Get plugin name - plugin name is either user specified or "native" + // - Exception: macOS, which will default to using "webengine" until the native plugin is matured. + // 2. If neither a user specified or "default" plugin exists, then the first available is used. + const QString pluginName = getPluginName(); + const int index = pluginName.isEmpty() ? 0 : qMax(0, loader->indexOf(pluginName)); + return qobject_cast(loader->instance(index)); +} + +QT_END_NAMESPACE diff --git a/src/webview/qwebviewfactory_p.h b/src/webview/qwebviewfactory_p.h new file mode 100644 index 0000000..0914b8a --- /dev/null +++ b/src/webview/qwebviewfactory_p.h @@ -0,0 +1,66 @@ +/**************************************************************************** +** +** Copyright (C) 2018 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtWebView module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QWEBVIEWFACTORY_H +#define QWEBVIEWFACTORY_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include "qabstractwebview_p.h" + +QT_BEGIN_NAMESPACE + +class QWebViewPlugin; + +namespace QWebViewFactory +{ + QWebViewPlugin *getPlugin(); + QAbstractWebView *createWebView(); + bool requiresExtraInitializationSteps(); +}; + +QT_END_NAMESPACE + +#endif // QWEBVIEWFACTORY_H diff --git a/src/webview/qwebviewplugin.cpp b/src/webview/qwebviewplugin.cpp new file mode 100644 index 0000000..9771480 --- /dev/null +++ b/src/webview/qwebviewplugin.cpp @@ -0,0 +1,56 @@ +/**************************************************************************** +** +** Copyright (C) 2018 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtWebView module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qwebviewplugin_p.h" + +QT_BEGIN_NAMESPACE + +QWebViewPlugin::QWebViewPlugin(QObject *parent) : QObject(parent) +{ + +} + +QWebViewPlugin::~QWebViewPlugin() +{ + +} + +void QWebViewPlugin::prepare() const +{ + // Only called for plugins that has "RequiresInit" set to true in their plugin metadata. +} + +QT_END_NAMESPACE diff --git a/src/webview/qwebviewplugin_p.h b/src/webview/qwebviewplugin_p.h new file mode 100644 index 0000000..aeba38f --- /dev/null +++ b/src/webview/qwebviewplugin_p.h @@ -0,0 +1,74 @@ +/**************************************************************************** +** +** Copyright (C) 2018 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtWebView module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QWEBVIEWPLUGIN_H +#define QWEBVIEWPLUGIN_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include "qwebview_global.h" +#include "qabstractwebview_p.h" + +#include + +#define QWebViewPluginInterface_iid "org.qt-project.Qt.QWebViewPluginInterface" + +QT_BEGIN_NAMESPACE + +class Q_WEBVIEW_EXPORT QWebViewPlugin : public QObject +{ + Q_OBJECT +public: + explicit QWebViewPlugin(QObject *parent = 0); + virtual ~QWebViewPlugin(); + + virtual QAbstractWebView *create(const QString &key) const = 0; + + virtual void prepare() const; +}; + +QT_END_NAMESPACE + +#endif // QWEBVIEWPLUGIN_H diff --git a/src/webview/webview-lib.pri b/src/webview/webview-lib.pri deleted file mode 100644 index 6630fd4..0000000 --- a/src/webview/webview-lib.pri +++ /dev/null @@ -1,75 +0,0 @@ -ANDROID_BUNDLED_JAR_DEPENDENCIES = \ - jar/QtAndroidWebView.jar -ANDROID_PERMISSIONS = \ - android.permission.ACCESS_FINE_LOCATION - -INCLUDEPATH += $$PWD - -PUBLIC_HEADERS += \ - qwebview_global.h \ - qtwebviewfunctions.h \ - qtwebviewfunctions_p.h - -SOURCES += \ - qtwebviewfunctions.cpp - -COMMON_HEADERS += \ - qwebview_p.h \ - qwebviewinterface_p.h \ - qquickwebview_p.h \ - qnativeviewcontroller_p.h \ - qwebview_p_p.h \ - qquickviewcontroller_p.h \ - qwebviewloadrequest_p.h \ - qquickwebviewloadrequest_p.h - -COMMON_SOURCES += \ - qwebview.cpp \ - qquickwebview.cpp \ - qquickviewcontroller.cpp \ - qquickwebviewloadrequest.cpp \ - qwebviewloadrequest.cpp - -android { - QT_FOR_PRIVATE += core-private - LIBS_PRIVATE += -ljnigraphics - SOURCES += \ - $$COMMON_SOURCES \ - qwebview_android.cpp - PRIVATE_HEADERS += \ - $$COMMON_HEADERS \ - qwebview_android_p.h - -} else:if(ios|macos) { - SOURCES += \ - $$COMMON_SOURCES - OBJECTIVE_SOURCES += \ - qwebview_darwin.mm - PRIVATE_HEADERS += \ - $$COMMON_HEADERS \ - qwebview_darwin_p.h - LIBS_PRIVATE += -framework Foundation -framework WebKit - macos: LIBS_PRIVATE += -framework AppKit - ios: LIBS_PRIVATE += -framework UIKit - - macos: CONFIG += use_webengine_backend -} else: winrt { - NO_PCH_SOURCES += qwebview_winrt.cpp - SOURCES += $$COMMON_SOURCES - PRIVATE_HEADERS += \ - $$COMMON_HEADERS \ - qwebview_winrt_p.h -} else:qtHaveModule(webengine) { - CONFIG += use_webengine_backend -} - -use_webengine_backend { - QT_PRIVATE += webengine-private - SOURCES *= $$COMMON_SOURCES - SOURCES += qwebview_webengine.cpp - PRIVATE_HEADERS *= $$COMMON_HEADERS - PRIVATE_HEADERS += qwebview_webengine_p.h - DEFINES += QT_WEBVIEW_WEBENGINE_BACKEND -} - -HEADERS += $$PUBLIC_HEADERS $$PRIVATE_HEADERS diff --git a/src/webview/webview.pro b/src/webview/webview.pro index af1286e..a1ba017 100644 --- a/src/webview/webview.pro +++ b/src/webview/webview.pro @@ -1,11 +1,47 @@ +load(qt_build_config) + TARGET = QtWebView -QT = QT_FOR_PRIVATE = quick-private core-private gui-private -include($$PWD/webview-lib.pri) +MODULE_PLUGIN_TYPES = webview + +PUBLIC_HEADERS += \ + qwebview_global.h \ + qtwebviewfunctions.h + +PRIVATE_HEADERS += \ + qwebview_p.h \ + qwebviewinterface_p.h \ + qquickwebview_p.h \ + qnativeviewcontroller_p.h \ + qabstractwebview_p.h \ + qquickviewcontroller_p.h \ + qwebviewloadrequest_p.h \ + qquickwebviewloadrequest_p.h \ + qwebviewplugin_p.h \ + qwebviewfactory_p.h + +SOURCES += \ + qtwebviewfunctions.cpp \ + qwebview.cpp \ + qquickwebview.cpp \ + qquickviewcontroller.cpp \ + qquickwebviewloadrequest.cpp \ + qwebviewloadrequest.cpp \ + qwebviewplugin.cpp \ + qwebviewfactory.cpp QMAKE_DOCS = \ $$PWD/doc/qtwebview.qdocconf +ANDROID_BUNDLED_JAR_DEPENDENCIES = \ + jar/QtAndroidWebView.jar +ANDROID_PERMISSIONS = \ + android.permission.ACCESS_FINE_LOCATION +ANDROID_LIB_DEPENDENCIES = \ + plugins/webview/libqtwebview_android.so + +HEADERS += $$PUBLIC_HEADERS $$PRIVATE_HEADERS + load(qt_module) -- cgit v1.2.3