diff options
Diffstat (limited to 'src/webenginequick/api')
37 files changed, 9096 insertions, 0 deletions
diff --git a/src/webenginequick/api/qquickwebengineaction.cpp b/src/webenginequick/api/qquickwebengineaction.cpp new file mode 100644 index 000000000..006715c70 --- /dev/null +++ b/src/webenginequick/api/qquickwebengineaction.cpp @@ -0,0 +1,146 @@ +// Copyright (C) 2018 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + + +#include "qquickwebengineaction_p.h" +#include "qquickwebengineaction_p_p.h" +#include "qquickwebengineview_p.h" + +QT_BEGIN_NAMESPACE + +/*! + \qmltype WebEngineAction + \instantiates QQuickWebEngineAction + \inqmlmodule QtWebEngine + \since QtWebEngine 1.8 + + \brief An action that represents a \l WebEngineView::WebAction. + + A WebEngineAction is returned by the \l WebEngineView::action() + method. It provides information about the action, such as + whether it is \l enabled. + + The following code uses the \l WebEngineView::action() method to check if + the copy action is enabled: + + \code + var copyAction = webEngineView.action(WebEngineView.Copy); + if (copyAction.enabled) + console.log("Copy is enabled."); + else + console.log("Copy is disabled."); + \endcode + + A \l ToolButton can be connected to a WebEngineAction as follows: + + \snippet qtwebengine_webengineaction.qml 0 + + A context menu could be implemented like this: + + \snippet qtwebengine_webengineaction.qml 1 +*/ + +QQuickWebEngineActionPrivate::QQuickWebEngineActionPrivate(const QVariant &data, const QString &text, const QString &iconName, bool enabled) + : m_data(data) + , m_text(text) + , m_iconName(iconName) + , m_enabled(enabled) +{ +} + +QQuickWebEngineActionPrivate::~QQuickWebEngineActionPrivate() +{ +} + +void QQuickWebEngineActionPrivate::setEnabled(bool enabled) +{ + Q_Q(QQuickWebEngineAction); + if (m_enabled == enabled) + return; + m_enabled = enabled; + emit q->enabledChanged(); +} + +QVariant QQuickWebEngineActionPrivate::data() const +{ + return m_data; +} + +void QQuickWebEngineActionPrivate::trigger() +{ + Q_Q(QQuickWebEngineAction); + if (QQuickWebEngineView *view = static_cast<QQuickWebEngineView*>(q->parent())) { + view->triggerWebAction(static_cast<QQuickWebEngineView::WebAction>(data().toInt())); + } +} + +QQuickWebEngineAction::QQuickWebEngineAction(const QVariant &data, const QString &text, const QString &iconName, bool enabled, QObject *parent) + : QObject(parent) + , d_ptr(new QQuickWebEngineActionPrivate(data, text, iconName, enabled)) +{ + d_ptr->q_ptr = this; +} + +QQuickWebEngineAction::QQuickWebEngineAction(QObject *parent) + : QObject(parent) + , d_ptr(new QQuickWebEngineActionPrivate(-1, QStringLiteral(""), QStringLiteral(""), false)) +{ + d_ptr->q_ptr = this; +} + +QQuickWebEngineAction::~QQuickWebEngineAction() +{ +} + +/*! + \qmlproperty int WebEngineAction::text + + This property holds a textual description of the action. +*/ +QString QQuickWebEngineAction::text() const +{ + Q_D(const QQuickWebEngineAction); + return d->m_text; +} + +/*! + \qmlproperty string WebEngineAction::iconName + + This property holds the name of the icon for the action. This name + can be used to pick the icon from a theme. +*/ +QString QQuickWebEngineAction::iconName() const +{ + Q_D(const QQuickWebEngineAction); + return d->m_iconName; +} + +/*! + \qmlproperty bool WebEngineAction::enabled + + This property holds whether the action is enabled. +*/ +bool QQuickWebEngineAction::isEnabled() const +{ + Q_D(const QQuickWebEngineAction); + return d->m_enabled; +} + +/*! + \qmlmethod void WebEngineAction::trigger() + + Triggers the action. +*/ +void QQuickWebEngineAction::trigger() +{ + Q_D(QQuickWebEngineAction); + if (!isEnabled()) + return; + + d->trigger(); + emit triggered(); +} + +QT_END_NAMESPACE + +#include "moc_qquickwebengineaction_p.cpp" diff --git a/src/webenginequick/api/qquickwebengineaction_p.h b/src/webenginequick/api/qquickwebengineaction_p.h new file mode 100644 index 000000000..fcada7773 --- /dev/null +++ b/src/webenginequick/api/qquickwebengineaction_p.h @@ -0,0 +1,72 @@ +// Copyright (C) 2018 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + +#ifndef QQUICKWEBENGINEACTION_P_H +#define QQUICKWEBENGINEACTION_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 "qtwebenginequickglobal_p.h" +#include <QtCore/qobject.h> +#include <QtCore/qvariant.h> +#include <QtQml/qqml.h> +#include <QtQml/qqmlregistration.h> + +namespace QtWebEngineCore { + class UIDelegatesManager; +} + +QT_BEGIN_NAMESPACE + +class QQuickWebEngineActionPrivate; + +class Q_WEBENGINEQUICK_EXPORT QQuickWebEngineAction : public QObject +{ + Q_OBJECT + Q_PROPERTY(QString text READ text CONSTANT FINAL) + Q_PROPERTY(QString iconName READ iconName CONSTANT FINAL) + Q_PROPERTY(bool enabled READ isEnabled NOTIFY enabledChanged FINAL) + QML_NAMED_ELEMENT(WebEngineAction) + QML_ADDED_IN_VERSION(1, 8) + QML_EXTRA_VERSION(2, 0) + QML_UNCREATABLE("") + +public: + QQuickWebEngineAction(const QVariant &data, const QString &text, const QString &iconName, bool enabled, QObject *parent); + QQuickWebEngineAction(QObject *parent); + ~QQuickWebEngineAction(); + + QString text() const; + QString iconName() const; + bool isEnabled() const; + +public Q_SLOTS: + Q_INVOKABLE void trigger(); + +Q_SIGNALS: + void triggered(); + void enabledChanged(); + +private: + Q_DECLARE_PRIVATE(QQuickWebEngineAction) + friend class QQuickWebEngineViewPrivate; + friend class QQuickContextMenuBuilder; + + QScopedPointer<QQuickWebEngineActionPrivate> d_ptr; +}; + + +QT_END_NAMESPACE + +QML_DECLARE_TYPE(QQuickWebEngineAction) + +#endif // QQUICKWEBENGINEACTION_P_H diff --git a/src/webenginequick/api/qquickwebengineaction_p_p.h b/src/webenginequick/api/qquickwebengineaction_p_p.h new file mode 100644 index 000000000..7cbd69a79 --- /dev/null +++ b/src/webenginequick/api/qquickwebengineaction_p_p.h @@ -0,0 +1,50 @@ +// Copyright (C) 2018 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + +#ifndef QQUICKWEBENGINEACTION_P_P_H +#define QQUICKWEBENGINEACTION_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 "qtwebenginequickglobal_p.h" +#include <QtCore/qstring.h> +#include <QtCore/qvariant.h> + +QT_BEGIN_NAMESPACE + +class QQuickWebEngineAction; + +class QQuickWebEngineActionPrivate +{ +public: + Q_DECLARE_PUBLIC(QQuickWebEngineAction) + QQuickWebEngineActionPrivate(const QVariant &data, const QString &text, const QString &iconName, bool enabled); + ~QQuickWebEngineActionPrivate(); + + void setEnabled(bool enabled); + + QVariant data() const; + + void trigger(); + + QVariant m_data; + QString m_text; + QString m_iconName; + bool m_enabled; + +private: + QQuickWebEngineAction *q_ptr; +}; + +QT_END_NAMESPACE + +#endif // QQUICKWEBENGINEACTION_P_P_H diff --git a/src/webenginequick/api/qquickwebengineclientcertificateselection.cpp b/src/webenginequick/api/qquickwebengineclientcertificateselection.cpp new file mode 100644 index 000000000..46e531716 --- /dev/null +++ b/src/webenginequick/api/qquickwebengineclientcertificateselection.cpp @@ -0,0 +1,189 @@ +// Copyright (C) 2018 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + +#include "qquickwebengineclientcertificateselection_p.h" + +#include "client_cert_select_controller.h" + +QT_BEGIN_NAMESPACE + +/*! + \qmltype WebEngineClientCertificateOption + //! \instantiates QQuickWebEngineClientCertificateOption + \inqmlmodule QtWebEngine + \since QtWebEngine 1.9 + \brief Represents a client certificate option. + + \sa {WebEngineClientCertificateSelection::certificates} {WebEngineClientCertificateSelection.certificates} +*/ + +QQuickWebEngineClientCertificateOption::QQuickWebEngineClientCertificateOption(QQuickWebEngineClientCertificateSelection *selection, int index) + : QObject(selection), m_selection(selection), m_index(index) +{} + +/*! + \qmlproperty string WebEngineClientCertificateOption::issuer + \brief The issuer of the certificate. +*/ + +QString QQuickWebEngineClientCertificateOption::issuer() const +{ + return m_selection->d_ptr->certificates().at(m_index).issuerDisplayName(); +} + +/*! + \qmlproperty string WebEngineClientCertificateOption::subject + \brief The subject of the certificate. +*/ +QString QQuickWebEngineClientCertificateOption::subject() const +{ + return m_selection->d_ptr->certificates().at(m_index).subjectDisplayName(); +} + +/*! + \qmlproperty datetime WebEngineClientCertificateOption::effectiveDate + \brief The date and time when the certificate becomes valid. +*/ +QDateTime QQuickWebEngineClientCertificateOption::effectiveDate() const +{ + return m_selection->d_ptr->certificates().at(m_index).effectiveDate(); +} + +/*! + \qmlproperty datetime WebEngineClientCertificateOption::expiryDate + \brief The date and time when the certificate becomes invalid. +*/ +QDateTime QQuickWebEngineClientCertificateOption::expiryDate() const +{ + return m_selection->d_ptr->certificates().at(m_index).expiryDate(); +} + +/*! + \qmlproperty bool WebEngineClientCertificateOption::isSelfSigned + \brief Whether the certificate is only self-signed. +*/ +bool QQuickWebEngineClientCertificateOption::isSelfSigned() const +{ + return m_selection->d_ptr->certificates().at(m_index).isSelfSigned(); +} + +/*! + \qmlmethod void WebEngineClientCertificateOption::select() + + Selects this client certificate option. +*/ +void QQuickWebEngineClientCertificateOption::select() +{ + m_selection->select(m_index); +} + +/*! + \qmltype WebEngineClientCertificateSelection + //! \instantiates QQuickWebEngineClientCertificateSelection + \inqmlmodule QtWebEngine + \since QtWebEngine 1.9 + \brief Provides a selection of client certificates. + + When a web site requests an SSL client certificate, and one or more certificates + are found in the system's client certificate store, this type provides access to + the certificates to choose from, as well as a method for selecting one. + + The selection is asynchronous. If no certificate is selected and no copy of the + object is kept alive, loading will continue without a certificate. + + \sa {WebEngineView::selectClientCertificate}{WebEngineView.selectClientCertificate} +*/ + +QQuickWebEngineClientCertificateSelection::QQuickWebEngineClientCertificateSelection( + QSharedPointer<QtWebEngineCore::ClientCertSelectController> selectController) + : QObject(), d_ptr(selectController) +{} + +qsizetype QQuickWebEngineClientCertificateSelection::certificates_count( + QQmlListProperty<QQuickWebEngineClientCertificateOption> *p) +{ + Q_ASSERT(p && p->object); + QQuickWebEngineClientCertificateSelection *d = static_cast<QQuickWebEngineClientCertificateSelection *>(p->object); + return d->m_certificates.size(); +} + +QQuickWebEngineClientCertificateOption *QQuickWebEngineClientCertificateSelection::certificates_at( + QQmlListProperty<QQuickWebEngineClientCertificateOption> *p, qsizetype idx) +{ + Q_ASSERT(p && p->object); + QQuickWebEngineClientCertificateSelection *d = static_cast<QQuickWebEngineClientCertificateSelection *>(p->object); + if (idx < 0 || idx >= d->m_certificates.size()) + return nullptr; + return d->m_certificates[idx]; +} + +/*! + \qmlproperty list<WebEngineClientCertificateOption> WebEngineClientCertificateSelection::certificates + \brief The client certificates available to choose from. +*/ + +QQmlListProperty<QQuickWebEngineClientCertificateOption> QQuickWebEngineClientCertificateSelection::certificates() +{ + if (m_certificates.empty()) { + QList<QSslCertificate> certificates = d_ptr->certificates(); + for (int i = 0; i < certificates.size(); ++i) + m_certificates.push_back(new QQuickWebEngineClientCertificateOption(this, i)); + } + + return QQmlListProperty<QQuickWebEngineClientCertificateOption>( + this, nullptr, + certificates_count, + certificates_at); +} + +/*! + \qmlmethod void WebEngineClientCertificateSelection::select(WebEngineClientCertificateOption certificate) + + Selects the client certificate \a certificate. The certificate must be one + of the offered certificates. + + \sa selectNone() +*/ +void QQuickWebEngineClientCertificateSelection::select(const QQuickWebEngineClientCertificateOption *certificate) +{ + select(certificate->m_index); +} + +/*! + \qmlmethod void WebEngineClientCertificateSelection::select(int index) + + Selects the client certificate at the index \a index in the list of offered certificates. + + \sa selectNone() +*/ +void QQuickWebEngineClientCertificateSelection::select(int index) +{ + d_ptr->select(index); +} + +/*! + \qmlmethod void WebEngineClientCertificateSelection::selectNone() + + Continues without using any of the offered certificates. This is the same + action as taken when destroying the last copy of this object if no + selection has been made. + + \sa select() +*/ +void QQuickWebEngineClientCertificateSelection::selectNone() +{ + d_ptr->selectNone(); +} + +/*! + \qmlproperty url WebEngineClientCertificateSelection::host + \brief The host and port of the server requesting the client certificate. +*/ +QUrl QQuickWebEngineClientCertificateSelection::host() const +{ + return d_ptr->hostAndPort(); +} + +QT_END_NAMESPACE + +#include "moc_qquickwebengineclientcertificateselection_p.cpp" diff --git a/src/webenginequick/api/qquickwebengineclientcertificateselection_p.h b/src/webenginequick/api/qquickwebengineclientcertificateselection_p.h new file mode 100644 index 000000000..2e0450f8e --- /dev/null +++ b/src/webenginequick/api/qquickwebengineclientcertificateselection_p.h @@ -0,0 +1,104 @@ +// Copyright (C) 2018 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + +#ifndef QQUICKWEBENGINECERTSELECTION_P_H +#define QQUICKWEBENGINECERTSELECTION_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 <QtWebEngineQuick/private/qtwebenginequickglobal_p.h> + +#include <QtCore/qdatetime.h> +#include <QtCore/qlist.h> +#include <QtCore/qobject.h> +#include <QtCore/qsharedpointer.h> +#include <QtCore/qurl.h> +#include <QtQml/qqmllist.h> +#include <QtQml/qqmlregistration.h> + +namespace QtWebEngineCore { +class ClientCertSelectController; +} + +QT_BEGIN_NAMESPACE + +class QQuickWebEngineClientCertificateSelection; + +class Q_WEBENGINEQUICK_EXPORT QQuickWebEngineClientCertificateOption : public QObject { + Q_OBJECT + Q_PROPERTY(QString issuer READ issuer CONSTANT FINAL) + Q_PROPERTY(QString subject READ subject CONSTANT FINAL) + Q_PROPERTY(QDateTime effectiveDate READ effectiveDate CONSTANT FINAL) + Q_PROPERTY(QDateTime expiryDate READ expiryDate CONSTANT FINAL) + Q_PROPERTY(bool isSelfSigned READ isSelfSigned CONSTANT FINAL) + QML_NAMED_ELEMENT(WebEngineClientCertificateOption) + QML_ADDED_IN_VERSION(1, 9) + QML_EXTRA_VERSION(2, 0) + QML_UNCREATABLE("") + +public: + QString issuer() const; + QString subject() const; + QDateTime effectiveDate() const; + QDateTime expiryDate() const; + bool isSelfSigned() const; + + Q_INVOKABLE void select(); + +private: + friend class QQuickWebEngineClientCertificateSelection; + QQuickWebEngineClientCertificateOption(QQuickWebEngineClientCertificateSelection *selection, int index); + + QQuickWebEngineClientCertificateSelection *m_selection; + int m_index; +}; + +class Q_WEBENGINEQUICK_EXPORT QQuickWebEngineClientCertificateSelection : public QObject { + Q_OBJECT + Q_PROPERTY(QUrl host READ host CONSTANT FINAL) + Q_PROPERTY(QQmlListProperty<QQuickWebEngineClientCertificateOption> certificates READ certificates CONSTANT FINAL) + QML_NAMED_ELEMENT(WebEngineClientCertificateSelection) + QML_ADDED_IN_VERSION(1, 9) + QML_EXTRA_VERSION(2, 0) + QML_UNCREATABLE("") + +public: + QQuickWebEngineClientCertificateSelection() = default; + + QUrl host() const; + + Q_INVOKABLE void select(int idx); + Q_INVOKABLE void select(const QQuickWebEngineClientCertificateOption *certificate); + Q_INVOKABLE void selectNone(); + QQmlListProperty<QQuickWebEngineClientCertificateOption> certificates(); + +private: + friend class QQuickWebEngineViewPrivate; + friend class QQuickWebEngineClientCertificateOption; + + static qsizetype certificates_count(QQmlListProperty<QQuickWebEngineClientCertificateOption> *p); + static QQuickWebEngineClientCertificateOption *certificates_at(QQmlListProperty<QQuickWebEngineClientCertificateOption> *p, qsizetype idx); + + explicit QQuickWebEngineClientCertificateSelection( + QSharedPointer<QtWebEngineCore::ClientCertSelectController>); + + mutable QList<QQuickWebEngineClientCertificateOption *> m_certificates; + QSharedPointer<QtWebEngineCore::ClientCertSelectController> d_ptr; +}; + +QT_END_NAMESPACE + +Q_DECLARE_METATYPE(QQuickWebEngineClientCertificateOption *) +Q_DECLARE_METATYPE(QQmlListProperty<QQuickWebEngineClientCertificateOption>) +Q_DECLARE_METATYPE(QQuickWebEngineClientCertificateSelection *) + +#endif // QQUICKWEBENGINECERTSELECTION_P_H diff --git a/src/webenginequick/api/qquickwebenginedialogrequests.cpp b/src/webenginequick/api/qquickwebenginedialogrequests.cpp new file mode 100644 index 000000000..d49f17397 --- /dev/null +++ b/src/webenginequick/api/qquickwebenginedialogrequests.cpp @@ -0,0 +1,817 @@ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + +#include "qquickwebenginedialogrequests_p.h" +#include "authentication_dialog_controller.h" +#include "javascript_dialog_controller.h" +#include "color_chooser_controller.h" +#include "file_picker_controller.h" +#include "web_contents_adapter_client.h" + +#include <QCursor> +#include <QQuickItem> + +QT_BEGIN_NAMESPACE + +using namespace QtWebEngineCore; + +ASSERT_ENUMS_MATCH(WebContentsAdapterClient::AlertDialog, + QQuickWebEngineJavaScriptDialogRequest::DialogTypeAlert) +ASSERT_ENUMS_MATCH(WebContentsAdapterClient::ConfirmDialog, + QQuickWebEngineJavaScriptDialogRequest::DialogTypeConfirm) +ASSERT_ENUMS_MATCH(WebContentsAdapterClient::PromptDialog, + QQuickWebEngineJavaScriptDialogRequest::DialogTypePrompt) +ASSERT_ENUMS_MATCH(WebContentsAdapterClient::UnloadDialog, + QQuickWebEngineJavaScriptDialogRequest::DialogTypeBeforeUnload) + +ASSERT_ENUMS_MATCH(FilePickerController::Open, + QQuickWebEngineFileDialogRequest::FileModeOpen) +ASSERT_ENUMS_MATCH(FilePickerController::OpenMultiple, + QQuickWebEngineFileDialogRequest::FileModeOpenMultiple) +ASSERT_ENUMS_MATCH(FilePickerController::UploadFolder, + QQuickWebEngineFileDialogRequest::FileModeUploadFolder) +ASSERT_ENUMS_MATCH(FilePickerController::Save, + QQuickWebEngineFileDialogRequest::FileModeSave) + +/*! + \qmltype AuthenticationDialogRequest + //! \instantiates QQuickWebEngineAuthenticationDialogRequest + \inqmlmodule QtWebEngine + \since QtWebEngine 1.4 + + \brief A request for providing authentication credentials required + by proxies or HTTP servers. + + An AuthenticationDialogRequest is passed as an argument of the + WebEngineView::authenticationDialogRequested signal. It is generated + when basic HTTP or proxy authentication is required. The type + of authentication can be checked with the \l type property. + + The \l accepted property of the request indicates whether the request + is handled by the user code or the default dialog should be displayed. + If you set the \l accepted property to \c true, make sure to call + either \l dialogAccept() or \l dialogReject() afterwards. + + The following code uses a custom dialog to handle the request: + \code + + WebEngineView { + // ... + onAuthenticationDialogRequested: function(request) { + request.accepted = true; + myDialog.request = request // keep the reference to the request + myDialog.accept.connect(request.dialogAccept); + myDialog.reject.connect(request.dialogReject); + myDialog.visible = true; + } + // ... + } + + \endcode +*/ + +QQuickWebEngineAuthenticationDialogRequest::QQuickWebEngineAuthenticationDialogRequest( + QSharedPointer<AuthenticationDialogController> controller, + QObject *parent): + QObject(parent) + , m_controller(controller.toWeakRef()) + , m_url(controller->url()) + , m_realm(controller->realm()) + , m_type(controller->isProxy() ? AuthenticationTypeProxy + : AuthenticationTypeHTTP) + , m_host(controller->host()) + , m_accepted(false) +{ + +} + +QQuickWebEngineAuthenticationDialogRequest::~QQuickWebEngineAuthenticationDialogRequest() +{ +} + +/*! + \qmlproperty url AuthenticationDialogRequest::url + \readonly + + The URL of the HTTP request for which authentication was requested. + In case of proxy authentication, this is a request URL which is proxied + via host. + + \sa proxyHost +*/ + +QUrl QQuickWebEngineAuthenticationDialogRequest::url() const +{ + return m_url; +} + +/*! + \qmlproperty string AuthenticationDialogRequest::realm + \readonly + + The HTTP authentication realm attribute value of the \c WWW-Authenticate + header. Empty if \l type is AuthenticationTypeProxy. +*/ + +QString QQuickWebEngineAuthenticationDialogRequest::realm() const +{ + return m_realm; +} + +/*! + \qmlproperty string AuthenticationDialogRequest::proxyHost + \readonly + + The hostname of the authentication proxy. + Empty if \l type is AuthenticationTypeHTTP. +*/ + +QString QQuickWebEngineAuthenticationDialogRequest::proxyHost() const +{ + return m_host; +} + +/*! + \qmlproperty enumeration AuthenticationDialogRequest::type + \readonly + + The type of the authentication request. + + \value WebEngineAuthenticationDialogRequest.AuthenticationTypeHTTP + HTTP authentication. + \value WebEngineAuthenticationDialogRequest.AuthenticationTypeProxy + Proxy authentication. +*/ + +QQuickWebEngineAuthenticationDialogRequest::AuthenticationType +QQuickWebEngineAuthenticationDialogRequest::type() const +{ + return m_type; +} + +/*! + \qmlproperty bool AuthenticationDialogRequest::accepted + + Indicates whether the authentication dialog request has been + accepted by the signal handler. + + If the property is \c false after any signal handlers + for WebEngineView::authenticationDialogRequested have been executed, + a default authentication dialog will be shown. + To prevent this, set \c{request.accepted} to \c true. + + The default is \c false. +*/ + +bool QQuickWebEngineAuthenticationDialogRequest::isAccepted() const +{ + return m_accepted; +} + +void QQuickWebEngineAuthenticationDialogRequest::setAccepted(bool accepted) +{ + m_accepted = accepted; +} + +/*! + \qmlmethod void AuthenticationDialogRequest::dialogAccept(string username, string password) + + This function notifies the engine that the user accepted the dialog, + providing the \a username and the \a password required for authentication. +*/ + +void QQuickWebEngineAuthenticationDialogRequest::dialogAccept(const QString &user, + const QString &password) +{ + m_accepted = true; + QSharedPointer<AuthenticationDialogController> controller + = m_controller.toStrongRef(); + if (controller) + controller->accept(user,password); +} + +/*! + \qmlmethod void AuthenticationDialogRequest::dialogReject() + + This function notifies the engine that the user rejected the dialog and the + authentication shall not proceed. +*/ + +void QQuickWebEngineAuthenticationDialogRequest::dialogReject() +{ + m_accepted = true; + QSharedPointer<AuthenticationDialogController> controller + = m_controller.toStrongRef(); + if (controller) + controller->reject(); +} + +/////////////////////////////////////////////////////////////////////////////// + +/*! + \qmltype JavaScriptDialogRequest + //! \instantiates QQuickWebEngineJavaScriptDialogRequest + \inqmlmodule QtWebEngine + \since QtWebEngine 1.4 + + \brief A request for showing an alert, a confirmation, or a prompt dialog + from within JavaScript to the user. + + A JavaScriptDialogRequest is passed as an argument of the + WebEngineView::javaScriptDialogRequested signal. The request is emitted + if JavaScript on the page calls HTML5's + \l{https://www.w3.org/TR/html5/webappapis.html#simple-dialogs}{Simple Dialogs} + API, or in response to HTML5's + \l {https://www.w3.org/TR/html5/browsers.html#beforeunloadevent}{BeforeUnloadEvent}. + The type of a particular dialog can be checked with the \l type property. + + The \l accepted property of the request indicates whether the request + is handled by the user code or the default dialog should be displayed. + If you set the \l accepted property to \c true, make sure to call either + \l dialogAccept() or \l dialogReject() afterwards. The JavaScript call + causing the request will be blocked until then. + + The following code uses a custom dialog to handle the request: + + \code + WebEngineView { + // ... + onJavaScriptDialogRequested: function(request) { + request.accepted = true; + myDialog.request = request // keep the reference to the request + myDialog.accept.connect(request.dialogAccept); + myDialog.reject.connect(request.dialogReject); + myDialog.visible = true; + } + // ... + } + \endcode +*/ + +QQuickWebEngineJavaScriptDialogRequest::QQuickWebEngineJavaScriptDialogRequest( + QSharedPointer<JavaScriptDialogController> controller, QObject *parent): + QObject(parent) + , m_controller(controller.toWeakRef()) + , m_message(controller->message()) + , m_defaultPrompt(controller->defaultPrompt()) + , m_title(controller->title()) + , m_type(static_cast<QQuickWebEngineJavaScriptDialogRequest::DialogType>(controller->type())) + , m_securityOrigin(controller->securityOrigin()) + , m_accepted(false) +{ +} + +QQuickWebEngineJavaScriptDialogRequest::~QQuickWebEngineJavaScriptDialogRequest() +{ + +} + +/*! + \qmlproperty string JavaScriptDialogRequest::message + \readonly + + The message to be shown to the user. +*/ + +QString QQuickWebEngineJavaScriptDialogRequest::message() const +{ + return m_message; +} + +/*! + \qmlproperty string JavaScriptDialogRequest::defaultText + \readonly + + The default prompt text, if the requested dialog is a prompt. +*/ + + +QString QQuickWebEngineJavaScriptDialogRequest::defaultText() const +{ + return m_defaultPrompt; +} + +/*! + \qmlproperty string JavaScriptDialogRequest::title + \readonly + + A default title for the dialog. +*/ + +QString QQuickWebEngineJavaScriptDialogRequest::title() const +{ + return m_title; +} + +/*! + \qmlproperty enumeration JavaScriptDialogRequest::type + \readonly + + Returns the type of the requested dialog box. For more information, see + HTML5's + \l{https://www.w3.org/TR/html5/webappapis.html#simple-dialogs}{Simple Dialogs}. + + \value JavaScriptDialogRequest.DialogTypeAlert + A JavaScript alert dialog. + \value JavaScriptDialogRequest.DialogTypeConfirm + A JavaScript confirmation dialog. + \value JavaScriptDialogRequest.DialogTypePrompt + A JavaScript prompt dialog. + \value JavaScriptDialogRequest.DialogTypeBeforeUnload + The users should be asked if they want to leave the page. +*/ + +QQuickWebEngineJavaScriptDialogRequest::DialogType QQuickWebEngineJavaScriptDialogRequest::type() const +{ + return m_type; +} + +/*! + \qmlproperty url JavaScriptDialogRequest::securityOrigin + \readonly + + The URL of the security origin. +*/ + +QUrl QQuickWebEngineJavaScriptDialogRequest::securityOrigin() const +{ + return m_securityOrigin; +} + +/*! + \qmlproperty bool JavaScriptDialogRequest::accepted + + Indicates whether the JavaScript dialog request has been + accepted by the signal handler. + + If the property is \c false after any signal handlers + for WebEngineView::javaScriptDialogRequested have been executed, + a default dialog will be shown. + To prevent this, set \c{request.accepted} to \c true. + + The default is \c false. +*/ + +bool QQuickWebEngineJavaScriptDialogRequest::isAccepted() const +{ + return m_accepted; +} + +void QQuickWebEngineJavaScriptDialogRequest::setAccepted(bool accepted) +{ + m_accepted = accepted; +} + +/*! + \qmlmethod void JavaScriptDialogRequest::dialogAccept() + + This function notifies the engine that the user accepted the dialog. +*/ + +/*! + \qmlmethod void JavaScriptDialogRequest::dialogAccept(string text) + + This function notifies the engine that the user accepted the dialog, + providing the \a text in case of a prompt message box. +*/ + +void QQuickWebEngineJavaScriptDialogRequest::dialogAccept(const QString& text) +{ + m_accepted = true; + QSharedPointer<JavaScriptDialogController> controller + = m_controller.toStrongRef(); + if (controller) { + controller->textProvided(text); + controller->accept(); + } +} + +/*! + \qmlmethod void JavaScriptDialogRequest::dialogReject() + + This function notifies the engine that the user rejected the dialog. +*/ + +void QQuickWebEngineJavaScriptDialogRequest::dialogReject() +{ + m_accepted = true; + QSharedPointer<JavaScriptDialogController> controller + = m_controller.toStrongRef(); + if (controller) + controller->reject(); +} + +/////////////////////////////////////////////////////////////////////////////// + +/*! + \qmltype ColorDialogRequest + //! \instantiates QQuickWebEngineColorDialogRequest + \inqmlmodule QtWebEngine + \since QtWebEngine 1.4 + + \brief A request for selecting a color by the user. + + A ColorDialogRequest is passed as an argument of the + WebEngineView::colorDialogRequested signal. It is generated when + a color picker dialog is requested. See + \l { https://www.w3.org/TR/html5/forms.html#color-state-(type=color)} + {HTML5 Color State}. + + The \l accepted property of the request indicates whether the request + is handled by the user code or the default dialog should be displayed. + If you set the \l accepted property to \c true, make sure to call either + \l dialogAccept() or \l dialogReject() afterwards. + + The following code uses a custom dialog to handle the request: + + \code + WebEngineView { + // ... + onColorDialogRequested: function(request) { + request.accepted = true; + myDialog.request = request // keep the reference to the request + myDialog.accept.connect(request.dialogAccept); + myDialog.reject.connect(request.dialogReject); + myDialog.visible = true; + } + // ... + } + \endcode +*/ + +QQuickWebEngineColorDialogRequest::QQuickWebEngineColorDialogRequest( + QSharedPointer<ColorChooserController> controller, QObject *parent): + QObject(parent) + , m_controller(controller.toWeakRef()) + , m_color(controller->initialColor()) + , m_accepted(false) +{ + +} + +QQuickWebEngineColorDialogRequest::~QQuickWebEngineColorDialogRequest() +{ + +} + +/*! + \qmlproperty color ColorDialogRequest::color + \readonly + + The default color to be selected in the dialog. +*/ + +QColor QQuickWebEngineColorDialogRequest::color() const +{ + return m_color; +} + +/*! + \qmlproperty bool ColorDialogRequest::accepted + + Indicates whether the color picker dialog request has been + accepted by the signal handler. + + If the property is \c false after any signal handlers + for WebEngineView::colorDialogRequested have been executed, + a default color picker dialog will be shown. + To prevent this, set \c{request.accepted} to \c true. + + The default is \c false. +*/ + +bool QQuickWebEngineColorDialogRequest::isAccepted() const +{ + return m_accepted; +} + +void QQuickWebEngineColorDialogRequest::setAccepted(bool accepted) +{ + m_accepted = accepted; +} + + +/*! + \qmlmethod void ColorDialogRequest::dialogAccept(color color) + + This function notifies the engine that the user accepted the dialog, + providing the \a color. +*/ + +void QQuickWebEngineColorDialogRequest::dialogAccept(const QColor &color) +{ + m_accepted = true; + QSharedPointer<ColorChooserController> controller = m_controller.toStrongRef(); + if (controller) + controller->accept(color); +} + +/*! + \qmlmethod void ColorDialogRequest::dialogReject() + + This function notifies the engine that the user rejected the dialog. +*/ + +void QQuickWebEngineColorDialogRequest::dialogReject() +{ + m_accepted = true; + QSharedPointer<ColorChooserController> controller = m_controller.toStrongRef(); + if (controller) + controller->reject(); +} + +/////////////////////////////////////////////////////////////////////////////// + +/*! + \qmltype FileDialogRequest + //! \instantiates QQuickWebEngineFileDialogRequest + \inqmlmodule QtWebEngine + \since QtWebEngine 1.4 + + \brief A request for letting the user choose a (new or existing) file or + directory. + + A FileDialogRequest is passed as an argument of the + WebEngineView::fileDialogRequested signal. It is generated + when the file dialog is requested by the input element. + See \l {https://www.w3.org/TR/html5/forms.html#file-upload-state-(type=file)}{File Upload state}. + + The \l accepted property of the request indicates whether the request + is handled by the user code or the default dialog should be displayed. + If you set the \l accepted property to \c true, make sure to call either + \l dialogAccept() or \l dialogReject() afterwards. + + The following code uses a custom dialog to handle the request: + + \code + WebEngineView { + // ... + onFileDialogRequested: function(request) { + request.accepted = true; + myDialog.request = request // keep the reference to the request + myDialog.accept.connect(request.dialogAccept); + myDialog.reject.connect(request.dialogReject); + myDialog.visible = true; + } + // ... + } + \endcode +*/ + +QQuickWebEngineFileDialogRequest::QQuickWebEngineFileDialogRequest( + QSharedPointer<FilePickerController> controller, QObject *parent): + QObject(parent) + , m_controller(controller.toWeakRef()) + , m_filename(controller->defaultFileName()) + , m_acceptedMimeTypes(controller->acceptedMimeTypes()) + , m_mode(static_cast<QQuickWebEngineFileDialogRequest::FileMode>(controller->mode())) + , m_accepted(false) +{ + +} + +QQuickWebEngineFileDialogRequest::~QQuickWebEngineFileDialogRequest() +{ + +} + +/*! + \qmlproperty stringlist FileDialogRequest::acceptedMimeTypes + \readonly + + A list of MIME types specified in the input element. The selection + should be restricted to only these types of files. +*/ + +QStringList QQuickWebEngineFileDialogRequest::acceptedMimeTypes() const +{ + return m_acceptedMimeTypes; +} + +/*! + \qmlproperty string FileDialogRequest::defaultFileName + \readonly + + The default name of the file to be selected in the dialog. +*/ + +QString QQuickWebEngineFileDialogRequest::defaultFileName() const +{ + return m_filename; +} + +/*! + \qmlproperty enumeration FileDialogRequest::mode + \readonly + + The mode of the file dialog. + + \value FileDialogRequest.FileModeOpen + Allows users to specify a single existing file. + \value FileDialogRequest.FileModeOpenMultiple + Allows users to specify multiple existing files. + \value FileDialogRequest.FileModeUploadFolder + Allows users to specify a single existing folder for upload. + \value FileDialogRequest.FileModeSave + Allows users to specify a non-existing file. If an existing file + is selected, the users should be informed that the file is going + to be overwritten. +*/ + +QQuickWebEngineFileDialogRequest::FileMode QQuickWebEngineFileDialogRequest::mode() const +{ + return m_mode; +} + +/*! + \qmlproperty bool FileDialogRequest::accepted + + Indicates whether the file picker dialog request has been + handled by the signal handler. + + If the property is \c false after any signal handlers + for WebEngineView::fileDialogRequested have been executed, + a default file picker dialog will be shown. + To prevent this, set \c{request.accepted} to \c true. + + The default is \c false. +*/ + +bool QQuickWebEngineFileDialogRequest::isAccepted() const +{ + return m_accepted; +} + +void QQuickWebEngineFileDialogRequest::setAccepted(bool accepted) +{ + m_accepted = accepted; +} + +/*! + \qmlmethod void FileDialogRequest::dialogAccept(stringlist files) + + This function needs to be called when the user accepted the dialog with + \a files. +*/ + +void QQuickWebEngineFileDialogRequest::dialogAccept(const QStringList &files) +{ + m_accepted = true; + QSharedPointer<FilePickerController> controller = m_controller.toStrongRef(); + if (controller) + controller->accepted(files); +} + +/*! + \qmlmethod void FileDialogRequest::dialogReject() + + This function needs to be called when the user did not accepted the dialog. +*/ + +void QQuickWebEngineFileDialogRequest::dialogReject() +{ + m_accepted = true; + QSharedPointer<FilePickerController> controller = m_controller.toStrongRef(); + if (controller) + controller->rejected(); +} + +/////////////////////////////////////////////////////////////////////////////// + +/*! + \qmltype TooltipRequest + //! \instantiates QQuickWebEngineTooltipRequest + \inqmlmodule QtWebEngine + \since QtWebEngine 1.10 + + \brief A request for showing a tooltip to the user. + + A TooltipRequest is a request object that is passed as a + parameter of the WebEngineView::tooltipRequested signal. Use the + \c onTooltipRequested signal handler to handle requests for + custom tooltip menus at specific positions. + + The \l accepted property of the request indicates whether the request + is handled by the user code or the default tooltip should + be displayed. + + The following code uses a custom tooltip to handle the request: + + \code + WebEngineView { + // ... + onTooltipRequested: function(request) { + if (request.type == TooltipRequest.Show) { + tooltip.visible = true; + tooltip.x = request.x; + tooltip.y = request.y; + tooltip.text = request.text; + } else { + tooltip.visible = false; + } + request.accepted = true; + } + // ... + } + \endcode +*/ + +QQuickWebEngineTooltipRequest::QQuickWebEngineTooltipRequest( + const QString &text, QObject *parent): + QObject(parent) + , m_text(text) + , m_type(text.isEmpty() ? RequestType::Hide : RequestType::Show) + , m_accepted(false) +{ + Q_ASSERT(parent); + if (QQuickItem *view = qobject_cast<QQuickItem *>(parent)) + m_position = view->mapFromGlobal(view->cursor().pos()).toPoint(); +} + +QQuickWebEngineTooltipRequest::~QQuickWebEngineTooltipRequest() +{ + +} + +/*! + \qmlproperty int TooltipRequest::x + \readonly + + The x coordinate of the top-left corner of the requested tooltip. +*/ + +int QQuickWebEngineTooltipRequest::x() const +{ + return m_position.x(); +} + +/*! + \qmlproperty int TooltipRequest::y + \readonly + + The y coordinate of the top-left corner of the requested tooltip. +*/ + +int QQuickWebEngineTooltipRequest::y() const +{ + return m_position.y(); +} + +/*! + \qmlproperty bool TooltipRequest::text + \readonly + + The text of the tooltip. It contains an empty string when the + tooltip should be hidden. +*/ + + +QString QQuickWebEngineTooltipRequest::text() const +{ + return m_text; +} + +/*! + \qmlproperty enumeration TooltipRequest::type + \readonly + + The type of the tooltip request. + + \value TooltipRequest.Show + The tooltip should be shown. + \value TooltipRequest.Hide + The tooltip should be hidden. +*/ + +QQuickWebEngineTooltipRequest::RequestType QQuickWebEngineTooltipRequest::type() const +{ + return m_type; +} + +/*! + \qmlproperty bool TooltipRequest::accepted + + Indicates whether the tooltip request has been accepted + by the signal handler. + + If the property is \c false after any signal handlers + for WebEngineView::tooltipRequested have been executed, + a default tooltip will be shown. + To prevent this, set \c {request.accepted} to \c true. + + The default is \c false. +*/ + +bool QQuickWebEngineTooltipRequest::isAccepted() const +{ + return m_accepted; +} + +void QQuickWebEngineTooltipRequest::setAccepted(bool accepted) +{ + m_accepted = accepted; +} + +QT_END_NAMESPACE + +#include "moc_qquickwebenginedialogrequests_p.cpp" diff --git a/src/webenginequick/api/qquickwebenginedialogrequests_p.h b/src/webenginequick/api/qquickwebenginedialogrequests_p.h new file mode 100644 index 000000000..d33a14df4 --- /dev/null +++ b/src/webenginequick/api/qquickwebenginedialogrequests_p.h @@ -0,0 +1,248 @@ +// Copyright (C) 2022 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + +#ifndef QQUICKWEBENGINDIALOGREQUESTS_P_H +#define QQUICKWEBENGINDIALOGREQUESTS_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 <QtWebEngineQuick/private/qtwebenginequickglobal_p.h> +#include <QtCore/qobject.h> +#include <QtCore/qpoint.h> +#include <QtCore/qsharedpointer.h> +#include <QtCore/qurl.h> +#include <QtGui/qcolor.h> +#include <QtQml/qqmlregistration.h> + +namespace QtWebEngineCore { + class AuthenticationDialogController; + class ColorChooserController; + class FilePickerController; + class JavaScriptDialogController; +} + +QT_BEGIN_NAMESPACE + +class Q_WEBENGINEQUICK_EXPORT QQuickWebEngineAuthenticationDialogRequest : public QObject { + Q_OBJECT +public: + + enum AuthenticationType { + AuthenticationTypeHTTP, + AuthenticationTypeProxy + }; + + Q_ENUM(AuthenticationType) + + Q_PROPERTY(QUrl url READ url CONSTANT FINAL) + Q_PROPERTY(QString realm READ realm CONSTANT FINAL) + Q_PROPERTY(QString proxyHost READ proxyHost CONSTANT FINAL) + Q_PROPERTY(AuthenticationType type READ type CONSTANT FINAL) + Q_PROPERTY(bool accepted READ isAccepted WRITE setAccepted FINAL) + QML_NAMED_ELEMENT(AuthenticationDialogRequest) + QML_ADDED_IN_VERSION(1, 4) + QML_EXTRA_VERSION(2, 0) + QML_UNCREATABLE("") + + ~QQuickWebEngineAuthenticationDialogRequest(); + + QUrl url() const; + QString realm() const; + QString proxyHost() const; + AuthenticationType type() const; + bool isAccepted() const; + void setAccepted(bool accepted); + +public slots: + void dialogAccept(const QString &user, const QString &password); + void dialogReject(); + +private: + QQuickWebEngineAuthenticationDialogRequest(QSharedPointer<QtWebEngineCore::AuthenticationDialogController> controller, + QObject *parent = nullptr); + QWeakPointer<QtWebEngineCore::AuthenticationDialogController> m_controller; + QUrl m_url; + QString m_realm; + AuthenticationType m_type; + QString m_host; + bool m_accepted; + friend class QQuickWebEngineViewPrivate; + Q_DISABLE_COPY(QQuickWebEngineAuthenticationDialogRequest) +}; + +class Q_WEBENGINEQUICK_EXPORT QQuickWebEngineJavaScriptDialogRequest : public QObject { + Q_OBJECT +public: + + enum DialogType { + DialogTypeAlert, + DialogTypeConfirm, + DialogTypePrompt, + DialogTypeBeforeUnload, + }; + Q_ENUM(DialogType) + + Q_PROPERTY(QString message READ message CONSTANT FINAL) + Q_PROPERTY(QString defaultText READ defaultText CONSTANT FINAL) + Q_PROPERTY(QString title READ title CONSTANT FINAL) + Q_PROPERTY(DialogType type READ type CONSTANT FINAL) + Q_PROPERTY(QUrl securityOrigin READ securityOrigin CONSTANT FINAL) + Q_PROPERTY(bool accepted READ isAccepted WRITE setAccepted FINAL) + QML_NAMED_ELEMENT(JavaScriptDialogRequest) + QML_ADDED_IN_VERSION(1, 4) + QML_EXTRA_VERSION(2, 0) + QML_UNCREATABLE("") + + ~QQuickWebEngineJavaScriptDialogRequest(); + + QString message() const; + QString defaultText() const; + QString title() const; + DialogType type() const; + QUrl securityOrigin() const; + bool isAccepted() const; + void setAccepted(bool accepted); + +public slots: + void dialogAccept(const QString& text = QString()); + void dialogReject(); + +private: + QQuickWebEngineJavaScriptDialogRequest(QSharedPointer<QtWebEngineCore::JavaScriptDialogController> controller, + QObject *parent = nullptr); + QWeakPointer<QtWebEngineCore::JavaScriptDialogController> m_controller; + QString m_message; + QString m_defaultPrompt; + QString m_title; + DialogType m_type; + QUrl m_securityOrigin; + bool m_accepted; + friend class QQuickWebEngineViewPrivate; + Q_DISABLE_COPY(QQuickWebEngineJavaScriptDialogRequest) +}; + +class Q_WEBENGINEQUICK_EXPORT QQuickWebEngineColorDialogRequest : public QObject { + Q_OBJECT +public: + + Q_PROPERTY(QColor color READ color CONSTANT FINAL) + Q_PROPERTY(bool accepted READ isAccepted WRITE setAccepted FINAL) + QML_NAMED_ELEMENT(ColorDialogRequest) + QML_ADDED_IN_VERSION(1, 4) + QML_EXTRA_VERSION(2, 0) + QML_UNCREATABLE("") + + ~QQuickWebEngineColorDialogRequest(); + + QColor color() const; + bool isAccepted() const; + void setAccepted(bool accepted); + +public slots: + void dialogAccept(const QColor &color); + void dialogReject(); + +private: + QQuickWebEngineColorDialogRequest(QSharedPointer<QtWebEngineCore::ColorChooserController> controller, + QObject *parent = nullptr); + QWeakPointer<QtWebEngineCore::ColorChooserController> m_controller; + QColor m_color; + bool m_accepted; + friend class QQuickWebEngineViewPrivate; + Q_DISABLE_COPY(QQuickWebEngineColorDialogRequest) +}; + +class Q_WEBENGINEQUICK_EXPORT QQuickWebEngineFileDialogRequest : public QObject { + Q_OBJECT +public: + + enum FileMode { + FileModeOpen, + FileModeOpenMultiple, + FileModeUploadFolder, + FileModeSave + }; + Q_ENUM(FileMode) + + Q_PROPERTY(QString defaultFileName READ defaultFileName CONSTANT FINAL) + Q_PROPERTY(QStringList acceptedMimeTypes READ acceptedMimeTypes CONSTANT FINAL) + Q_PROPERTY(FileMode mode READ mode CONSTANT FINAL) + Q_PROPERTY(bool accepted READ isAccepted WRITE setAccepted FINAL) + QML_NAMED_ELEMENT(FileDialogRequest) + QML_ADDED_IN_VERSION(1, 4) + QML_EXTRA_VERSION(2, 0) + QML_UNCREATABLE("") + + ~QQuickWebEngineFileDialogRequest(); + + QStringList acceptedMimeTypes() const; + QString defaultFileName() const; + FileMode mode() const; + bool isAccepted() const; + void setAccepted(bool accepted); + +public slots: + void dialogAccept(const QStringList &files); + void dialogReject(); + +private: + QQuickWebEngineFileDialogRequest(QSharedPointer<QtWebEngineCore::FilePickerController> controller, + QObject *parent = nullptr); + QWeakPointer<QtWebEngineCore::FilePickerController> m_controller; + QString m_filename; + QStringList m_acceptedMimeTypes; + FileMode m_mode; + bool m_accepted; + friend class QQuickWebEngineViewPrivate; + Q_DISABLE_COPY(QQuickWebEngineFileDialogRequest) +}; + +class Q_WEBENGINEQUICK_EXPORT QQuickWebEngineTooltipRequest : public QObject { + Q_OBJECT +public: + enum RequestType { + Show, + Hide, + }; + Q_ENUM(RequestType) + Q_PROPERTY(int x READ x CONSTANT FINAL) + Q_PROPERTY(int y READ y CONSTANT FINAL) + Q_PROPERTY(QString text READ text CONSTANT FINAL) + Q_PROPERTY(RequestType type READ type CONSTANT FINAL) + Q_PROPERTY(bool accepted READ isAccepted WRITE setAccepted FINAL) + QML_NAMED_ELEMENT(TooltipRequest) + QML_ADDED_IN_VERSION(1, 10) + QML_EXTRA_VERSION(2, 0) + QML_UNCREATABLE("") + + ~QQuickWebEngineTooltipRequest(); + int x() const; + int y() const; + QString text() const; + RequestType type() const; + bool isAccepted() const; + void setAccepted(bool accepted); + +private: + QQuickWebEngineTooltipRequest(const QString &text = QString(), + QObject *parent = nullptr); + QPoint m_position; + QString m_text; + RequestType m_type; + bool m_accepted; + friend class QQuickWebEngineViewPrivate; + Q_DISABLE_COPY(QQuickWebEngineTooltipRequest) +}; + +QT_END_NAMESPACE + +#endif // QQUICKWEBENGINDIALOGREQUESTS_P_H diff --git a/src/webenginequick/api/qquickwebenginedownloadrequest.cpp b/src/webenginequick/api/qquickwebenginedownloadrequest.cpp new file mode 100644 index 000000000..f745ba3b3 --- /dev/null +++ b/src/webenginequick/api/qquickwebenginedownloadrequest.cpp @@ -0,0 +1,32 @@ +// Copyright (C) 2021 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + +#include "qquickwebenginedownloadrequest_p.h" +#include "QtWebEngineCore/private/qwebenginedownloadrequest_p.h" + +#include "web_contents_adapter_client.h" + +QT_BEGIN_NAMESPACE + +/*! + \internal +*/ +QQuickWebEngineDownloadRequest::QQuickWebEngineDownloadRequest(QWebEngineDownloadRequestPrivate *p, QObject *parent) + : QWebEngineDownloadRequest(p, parent) +{ +} + +/*! + \internal + Returns the WebEngineView the download was requested on. If the download was not triggered by content in a WebEngineView, + \c nullptr is returned. +*/ +QQuickWebEngineView *QQuickWebEngineDownloadRequest::view() const +{ + Q_ASSERT(d_ptr->adapterClient->clientType() == QtWebEngineCore::WebContentsAdapterClient::QmlClient); + return const_cast<QQuickWebEngineView *>(static_cast<const QQuickWebEngineView *>(d_ptr->adapterClient->holdingQObject())); +} + +QT_END_NAMESPACE + +#include "moc_qquickwebenginedownloadrequest_p.cpp" diff --git a/src/webenginequick/api/qquickwebenginedownloadrequest_p.h b/src/webenginequick/api/qquickwebenginedownloadrequest_p.h new file mode 100644 index 000000000..42a0d88ba --- /dev/null +++ b/src/webenginequick/api/qquickwebenginedownloadrequest_p.h @@ -0,0 +1,46 @@ +// Copyright (C) 2021 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + +#ifndef QQUICKWEBENGINEDOWNLOADREQUEST_P_H +#define QQUICKWEBENGINEDOWNLOADREQUEST_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 <QtWebEngineQuick/private/qtwebenginequickglobal_p.h> +#include <QtWebEngineQuick/private/qquickwebengineview_p.h> +#include <QtWebEngineCore/qwebenginedownloadrequest.h> +#include <QtQml/qqmlregistration.h> + +QT_BEGIN_NAMESPACE + +class QQuickWebEngineProfilePrivate; + +class Q_WEBENGINEQUICK_EXPORT QQuickWebEngineDownloadRequest : public QWebEngineDownloadRequest +{ + Q_OBJECT +public: + Q_PROPERTY(QQuickWebEngineView *view READ view CONSTANT FINAL) + QML_NAMED_ELEMENT(WebEngineDownloadRequest) + QML_ADDED_IN_VERSION(1, 1) + QML_EXTRA_VERSION(2, 0) + QML_UNCREATABLE("") + + QQuickWebEngineView *view() const; +private: + Q_DISABLE_COPY(QQuickWebEngineDownloadRequest) + friend class QQuickWebEngineProfilePrivate; + QQuickWebEngineDownloadRequest(QWebEngineDownloadRequestPrivate *, QObject *parent = nullptr); +}; + +QT_END_NAMESPACE + +#endif // QQUICKWEBENGINEDOWNLOADREQUEST_P_H diff --git a/src/webenginequick/api/qquickwebenginefaviconprovider.cpp b/src/webenginequick/api/qquickwebenginefaviconprovider.cpp new file mode 100644 index 000000000..00c7f1949 --- /dev/null +++ b/src/webenginequick/api/qquickwebenginefaviconprovider.cpp @@ -0,0 +1,291 @@ +// Copyright (C) 2021 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + +#include "qquickwebenginefaviconprovider_p_p.h" + +#include "qquickwebengineprofile.h" +#include "qquickwebenginesettings_p.h" +#include "qquickwebengineview_p_p.h" + +#include "profile_adapter.h" +#include "web_contents_adapter.h" + +#include <QtCore/qmimedatabase.h> +#include <QtGui/qicon.h> +#include <QtGui/qpixmap.h> +#include <QThread> + +QT_BEGIN_NAMESPACE + +static inline unsigned area(const QSize &size) +{ + return size.width() * size.height(); +} + +static QSize largestSize(const QList<QSize> &availableSizes) +{ + QSize result; + for (const QSize &size : availableSizes) { + if (area(size) > area(result)) + result = size; + } + + return result; +} + +static QSize fitSize(const QList<QSize> &availableSizes, const QSize &requestedSize) +{ + Q_ASSERT(availableSizes.size()); + QSize result = largestSize(availableSizes); + if (availableSizes.size() == 1 || area(requestedSize) >= area(result)) + return result; + + for (const QSize &size : availableSizes) { + if (area(size) == area(requestedSize)) + return size; + + if (area(requestedSize) < area(size) && area(size) < area(result)) + result = size; + } + + return result; +} + +static QPixmap extractPixmap(const QIcon &icon, const QSize &requestedSize) +{ + Q_ASSERT(!icon.isNull()); + + // If source size is not specified, use the largest icon + if (!requestedSize.isValid()) + return icon.pixmap(largestSize(icon.availableSizes()), 1.0).copy(); + + const QSize &size = fitSize(icon.availableSizes(), requestedSize); + const QPixmap &iconPixmap = icon.pixmap(size, 1.0); + return iconPixmap.scaled(requestedSize, Qt::KeepAspectRatio, Qt::SmoothTransformation).copy(); +} + +static bool isIconURL(const QUrl &url) +{ + QMimeType mimeType = QMimeDatabase().mimeTypeForFile(url.path(), QMimeDatabase::MatchExtension); + + // Check file extension. + if (mimeType.name().startsWith(QLatin1String("image"))) + return true; + + // Check if it is an image data: URL. + if (url.scheme() == QLatin1String("data") && url.path().startsWith(QLatin1String("image"))) + return true; + + return false; +} + +FaviconImageRequester::FaviconImageRequester(const QUrl &imageSource, const QSize &requestedSize) + : m_imageSource(imageSource), m_requestedSize(requestedSize) +{ +} + +void FaviconImageRequester::start() +{ + if (!tryNextView()) { + // There is no non-otr view to access icon database. + Q_EMIT done(QPixmap()); + } +} + +void FaviconImageRequester::iconRequestDone(const QIcon &icon) +{ + if (icon.isNull()) { + if (!tryNextView()) { + // Ran out of views. + Q_EMIT done(QPixmap()); + } + return; + } + + Q_EMIT done(extractPixmap(icon, m_requestedSize)); +} + +bool FaviconImageRequester::tryNextView() +{ + if (auto view = getNextViewForProcessing()) { + requestFaviconFromDatabase(view); + return true; + } + + return false; +} + +void FaviconImageRequester::requestFaviconFromDatabase(QPointer<QQuickWebEngineView> view) +{ + QtWebEngineCore::ProfileAdapter *profileAdapter = view->d_ptr->profileAdapter(); + bool touchIconsEnabled = view->profile()->settings()->touchIconsEnabled(); + if (isIconURL(m_imageSource)) { + profileAdapter->requestIconForIconURL( + m_imageSource, qMax(m_requestedSize.width(), m_requestedSize.height()), + touchIconsEnabled, [this](const QIcon &icon, const QUrl &) { + QMetaObject::invokeMethod(this, "iconRequestDone", Qt::QueuedConnection, + Q_ARG(const QIcon &, icon)); + }); + } else { + profileAdapter->requestIconForPageURL( + m_imageSource, qMax(m_requestedSize.width(), m_requestedSize.height()), + touchIconsEnabled, [this](const QIcon &icon, const QUrl &, const QUrl &) { + QMetaObject::invokeMethod(this, "iconRequestDone", Qt::QueuedConnection, + Q_ARG(const QIcon &, icon)); + }); + } +} + +QPointer<QQuickWebEngineView> FaviconImageRequester::getNextViewForProcessing() +{ + Q_ASSERT(QThread::currentThread() == QCoreApplication::instance()->thread()); + + for (QPointer<QQuickWebEngineView> view : FaviconProviderHelper::instance()->views()) { + if (view.isNull()) + continue; + if (view->profile()->isOffTheRecord()) + continue; + if (m_processedViews.contains(view)) + continue; + m_processedViews.append(view); + return view; + } + return nullptr; +} + +FaviconProviderHelper::FaviconProviderHelper() +{ + moveToThread(qApp->thread()); +} + +FaviconProviderHelper *FaviconProviderHelper::instance() +{ + static FaviconProviderHelper instance; + return &instance; +} + +void FaviconProviderHelper::attach(QPointer<QQuickWebEngineView> view) +{ + if (!m_views.contains(view)) + m_views.append(view); +} + +void FaviconProviderHelper::detach(QPointer<QQuickWebEngineView> view) +{ + m_views.removeAll(view); +} + +void FaviconProviderHelper::handleImageRequest(QPointer<FaviconImageResponse> faviconResponse) +{ + Q_ASSERT(QThread::currentThread() == QCoreApplication::instance()->thread()); + + if (faviconResponse.isNull()) + return; + + if (m_views.isEmpty()) { + QMetaObject::invokeMethod(faviconResponse, "handleDone", Qt::QueuedConnection, + Q_ARG(QPixmap, QPixmap())); + return; + } + + auto view = findViewByImageSource(faviconResponse->imageSource()); + if (view) { + QIcon icon = view->d_ptr->adapter->icon(); + if (!icon.isNull()) { + QMetaObject::invokeMethod( + faviconResponse, "handleDone", Qt::QueuedConnection, + Q_ARG(QPixmap, extractPixmap(icon, faviconResponse->requestedSize()))); + return; + } + } + startFaviconRequest(faviconResponse); +} + +QPointer<QQuickWebEngineView> FaviconProviderHelper::findViewByImageSource(const QUrl &imageSource) const +{ + for (QPointer<QQuickWebEngineView> view : m_views) { + if (view.isNull()) + continue; + + if (isIconURL(imageSource)) { + if (view->icon() == QQuickWebEngineFaviconProvider::faviconProviderUrl(imageSource)) { + return view; + } + } else if (view->url() == imageSource) { + return view; + } + } + + return nullptr; +} + +void FaviconProviderHelper::startFaviconRequest(QPointer<FaviconImageResponse> faviconResponse) +{ + FaviconImageRequester *requester = new FaviconImageRequester(faviconResponse->imageSource(), + faviconResponse->requestedSize()); + + connect(requester, &FaviconImageRequester::done, [requester, faviconResponse](QPixmap pixmap) { + QMetaObject::invokeMethod(faviconResponse, "handleDone", Qt::QueuedConnection, + Q_ARG(QPixmap, pixmap)); + requester->deleteLater(); + }); + + requester->start(); +} + +FaviconImageResponse::FaviconImageResponse(const QUrl &imageSource, const QSize &requestedSize) + : m_imageSource(imageSource), m_requestedSize(requestedSize) +{ +} + +void FaviconImageResponse::handleDone(QPixmap pixmap) +{ + m_image = pixmap.toImage(); + Q_EMIT finished(); +} + +QQuickTextureFactory *FaviconImageResponse::textureFactory() const +{ + return QQuickTextureFactory::textureFactoryForImage(m_image); +} + +QString QQuickWebEngineFaviconProvider::identifier() +{ + return QStringLiteral("favicon"); +} + +QUrl QQuickWebEngineFaviconProvider::faviconProviderUrl(const QUrl &url) +{ + if (url.isEmpty()) + return url; + + QUrl providerUrl; + providerUrl.setScheme(QStringLiteral("image")); + providerUrl.setHost(identifier()); + providerUrl.setPath( + QStringLiteral("/%1").arg(url.toString(QUrl::RemoveQuery | QUrl::RemoveFragment))); + if (url.hasQuery()) + providerUrl.setQuery(url.query(QUrl::FullyDecoded)); + if (url.hasFragment()) + providerUrl.setFragment(url.fragment(QUrl::FullyDecoded)); + + return providerUrl; +} + +QQuickWebEngineFaviconProvider::QQuickWebEngineFaviconProvider() +{ + connect(this, &QQuickWebEngineFaviconProvider::imageResponseRequested, + FaviconProviderHelper::instance(), &FaviconProviderHelper::handleImageRequest); +} + +QQuickImageResponse * +QQuickWebEngineFaviconProvider::requestImageResponse(const QString &id, const QSize &requestedSize) +{ + FaviconImageResponse *response = new FaviconImageResponse(QUrl(id), requestedSize); + emit imageResponseRequested(response); + return response; +} + +QT_END_NAMESPACE + +#include "moc_qquickwebenginefaviconprovider_p_p.cpp" diff --git a/src/webenginequick/api/qquickwebenginefaviconprovider_p_p.h b/src/webenginequick/api/qquickwebenginefaviconprovider_p_p.h new file mode 100644 index 000000000..f1d948413 --- /dev/null +++ b/src/webenginequick/api/qquickwebenginefaviconprovider_p_p.h @@ -0,0 +1,109 @@ +// Copyright (C) 2021 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + +#ifndef QQUICKWEBENGINEFAVICONPROVIDER_P_P_H +#define QQUICKWEBENGINEFAVICONPROVIDER_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 <QtWebEngineQuick/private/qtwebenginequickglobal_p.h> +#include <QtCore/qlist.h> +#include <QtGui/qimage.h> +#include <QtQuick/qquickimageprovider.h> + +QT_BEGIN_NAMESPACE + +class QQuickWebEngineView; + +class FaviconImageResponse : public QQuickImageResponse +{ + Q_OBJECT + +public: + FaviconImageResponse(const QUrl &imageSource, const QSize &requestedSize); + + QQuickTextureFactory *textureFactory() const override; + const QUrl &imageSource() const { return m_imageSource; } + const QSize &requestedSize() const { return m_requestedSize; } + +public slots: + void handleDone(QPixmap pixmap); + +private: + QImage m_image; + QUrl m_imageSource; + QSize m_requestedSize; +}; + +class FaviconImageRequester : public QObject +{ + Q_OBJECT + +public: + FaviconImageRequester(const QUrl &imageSource, const QSize &requestedSize); + void start(); + +public slots: + void iconRequestDone(const QIcon &icon); + +signals: + void done(QPixmap pixmap); + +private: + bool tryNextView(); + void requestFaviconFromDatabase(QPointer<QQuickWebEngineView> view); + QPointer<QQuickWebEngineView> getNextViewForProcessing(); + + QUrl m_imageSource; + QSize m_requestedSize; + QList<QPointer<QQuickWebEngineView>> m_processedViews; +}; + +class Q_WEBENGINEQUICK_EXPORT QQuickWebEngineFaviconProvider : public QQuickAsyncImageProvider +{ + Q_OBJECT + +public: + static QString identifier(); + static QUrl faviconProviderUrl(const QUrl &); + + QQuickWebEngineFaviconProvider(); + QQuickImageResponse *requestImageResponse(const QString &id, + const QSize &requestedSize) override; + +signals: + void imageResponseRequested(QPointer<FaviconImageResponse> faviconResponse); +}; + +class Q_WEBENGINEQUICK_EXPORT FaviconProviderHelper : public QObject +{ + Q_OBJECT + +public: + static FaviconProviderHelper *instance(); + void attach(QPointer<QQuickWebEngineView> view); + void detach(QPointer<QQuickWebEngineView> view); + const QList<QPointer<QQuickWebEngineView>> &views() const { return m_views; } + +public slots: + void handleImageRequest(QPointer<FaviconImageResponse> faviconResponse); + +private: + FaviconProviderHelper(); + void startFaviconRequest(QPointer<FaviconImageResponse> faviconResponse); + QPointer<QQuickWebEngineView> findViewByImageSource(const QUrl &imageSource) const; + QList<QPointer<QQuickWebEngineView>> m_views; +}; + +QT_END_NAMESPACE + +#endif // QQUICKWEBENGINEFAVICONPROVIDER_P_P_H diff --git a/src/webenginequick/api/qquickwebengineforeigntypes_p.h b/src/webenginequick/api/qquickwebengineforeigntypes_p.h new file mode 100644 index 000000000..2d205254e --- /dev/null +++ b/src/webenginequick/api/qquickwebengineforeigntypes_p.h @@ -0,0 +1,236 @@ +// Copyright (C) 2021 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + + +#ifndef QQUICKWEBENGINEFOREIGNTYPES_H +#define QQUICKWEBENGINEFOREIGNTYPES_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 <QtQml/qqml.h> +#include <QtWebEngineCore/qwebenginedownloadrequest.h> +#include <QtWebEngineCore/qwebenginenavigationrequest.h> +#include <QtWebEngineCore/qwebenginescript.h> +#include <QtWebEngineCore/qwebenginenewwindowrequest.h> +#include <QtWebEngineCore/qwebengineloadinginfo.h> +#include <QtWebEngineCore/qwebenginehistory.h> +#include <QtWebEngineCore/qwebenginequotarequest.h> +#include <QtWebEngineCore/qwebenginenotification.h> +#include <QtWebEngineCore/qwebenginefindtextresult.h> +#include <QtWebEngineCore/qwebenginecertificateerror.h> +#include <QtWebEngineCore/qwebenginefullscreenrequest.h> +#include <QtWebEngineCore/qwebenginecontextmenurequest.h> +#include <QtWebEngineCore/qwebengineregisterprotocolhandlerrequest.h> +#include <QtWebEngineCore/qwebenginefilesystemaccessrequest.h> +#include <QtWebEngineCore/qwebenginewebauthuxrequest.h> + +QT_BEGIN_NAMESPACE + +// To prevent the same type from being exported twice into qmltypes +// (for value type and for the enums) +struct QWebEngineLoadingInfoDerived : public QWebEngineLoadingInfo +{ + Q_GADGET +}; + +namespace ForeignWebEngineLoadingInfoNamespace +{ + Q_NAMESPACE + QML_FOREIGN_NAMESPACE(QWebEngineLoadingInfoDerived) + QML_NAMED_ELEMENT(WebEngineLoadingInfo) + QML_ADDED_IN_VERSION(1, 1) + QML_EXTRA_VERSION(2, 0) +} + +struct ForeignWebEngineLoadingInfo +{ + Q_GADGET + QML_FOREIGN(QWebEngineLoadingInfo) + QML_NAMED_ELEMENT(webEngineLoadingInfo) + QML_ADDED_IN_VERSION(1, 1) + QML_EXTRA_VERSION(2, 0) + QML_UNCREATABLE("") +}; + +// To prevent the same type from being exported twice into qmltypes +// (for value type and for the enums) +struct QWebEngineCertificateErrorDerived : public QWebEngineCertificateError +{ + Q_GADGET +}; + +namespace ForeignWebEngineCertificateErrorNamespace +{ + Q_NAMESPACE + QML_FOREIGN_NAMESPACE(QWebEngineCertificateErrorDerived) + QML_NAMED_ELEMENT(WebEngineCertificateError) + QML_ADDED_IN_VERSION(1, 1) + QML_EXTRA_VERSION(2, 0) +} + +struct ForeignWebEngineCertificateError +{ + Q_GADGET + QML_FOREIGN(QWebEngineCertificateError) + QML_NAMED_ELEMENT(webEngineCertificateError) + QML_ADDED_IN_VERSION(1, 1) + QML_EXTRA_VERSION(2, 0) + QML_UNCREATABLE("") +}; + +struct ForeignWebEngineNavigationRequest +{ + Q_GADGET + QML_FOREIGN(QWebEngineNavigationRequest) + QML_NAMED_ELEMENT(WebEngineNavigationRequest) + QML_ADDED_IN_VERSION(1, 0) + QML_EXTRA_VERSION(2, 0) + QML_UNCREATABLE("") +}; + +namespace ForeignWebEngineScriptNamespace +{ + Q_NAMESPACE + QML_FOREIGN_NAMESPACE(QWebEngineScript) + QML_NAMED_ELEMENT(WebEngineScript) + QML_ADDED_IN_VERSION(1, 1) + QML_EXTRA_VERSION(2, 0) +} + +struct ForeignWebEngineScript +{ + Q_GADGET + QML_FOREIGN(QWebEngineScript) + QML_NAMED_ELEMENT(webEngineScript) + QML_ADDED_IN_VERSION(1, 1) + QML_EXTRA_VERSION(2, 0) + QML_UNCREATABLE("") +}; + +struct ForeignWebEngineHistory +{ + Q_GADGET + QML_FOREIGN(QWebEngineHistory) + QML_NAMED_ELEMENT(WebEngineHistory) + QML_ADDED_IN_VERSION(1, 1) + QML_EXTRA_VERSION(2, 0) + QML_UNCREATABLE("") +}; + +struct ForeignWebEngineHistoryModel +{ + Q_GADGET + QML_FOREIGN(QWebEngineHistoryModel) + QML_NAMED_ELEMENT(WebEngineHistoryModel) + QML_ADDED_IN_VERSION(1, 1) + QML_EXTRA_VERSION(2, 0) + QML_UNCREATABLE("") +}; + +struct ForeignWebEngineFullScreenRequest +{ + Q_GADGET + QML_FOREIGN(QWebEngineFullScreenRequest) + QML_NAMED_ELEMENT(fullScreenRequest) + QML_ADDED_IN_VERSION(1, 1) + QML_EXTRA_VERSION(2, 0) + QML_UNCREATABLE("") +}; + +struct ForeignWebEngineContextMenuRequest +{ + Q_GADGET + QML_FOREIGN(QWebEngineContextMenuRequest) + QML_NAMED_ELEMENT(ContextMenuRequest) + QML_ADDED_IN_VERSION(1, 7) + QML_EXTRA_VERSION(2, 0) + QML_UNCREATABLE("") +}; + +#if QT_DEPRECATED_SINCE(6, 5) +struct ForeignWebEngineQuotaRequest +{ + Q_GADGET + QML_FOREIGN(QWebEngineQuotaRequest) + QML_NAMED_ELEMENT(webEngineQuotaRequest) + QML_ADDED_IN_VERSION(1, 7) + QML_EXTRA_VERSION(2, 0) + QML_UNCREATABLE("") +}; +#endif + +struct ForeignWebEngineRegisterProtocolHandlerRequest +{ + Q_GADGET + QML_FOREIGN(QWebEngineRegisterProtocolHandlerRequest) + QML_NAMED_ELEMENT(registerProtocolHandlerRequest) + QML_ADDED_IN_VERSION(1, 7) + QML_EXTRA_VERSION(2, 0) + QML_UNCREATABLE("") +}; + +struct ForeignWebEngineNotification +{ + Q_GADGET + QML_FOREIGN(QWebEngineNotification) + QML_NAMED_ELEMENT(WebEngineNotification) + QML_ADDED_IN_VERSION(1, 9) + QML_EXTRA_VERSION(2, 0) + QML_UNCREATABLE("") +}; + +struct ForeignWebEngineFindTextResult +{ + Q_GADGET + QML_FOREIGN(QWebEngineFindTextResult) + QML_NAMED_ELEMENT(findTextResult) + QML_ADDED_IN_VERSION(1, 10) + QML_EXTRA_VERSION(2, 0) + QML_UNCREATABLE("") +}; + +struct ForeginWebEngineFileSystemAccessRequest +{ + Q_GADGET + QML_FOREIGN(QWebEngineFileSystemAccessRequest) + QML_NAMED_ELEMENT(webEngineFileSystemAccessRequest) + QML_ADDED_IN_VERSION(6, 4) + QML_UNCREATABLE("") +}; + +// To prevent the same type from being exported twice into qmltypes +// (for value type and for the enums) +struct QWebEngineFileSystemAccessRequestDerived : public QWebEngineFileSystemAccessRequest +{ + Q_GADGET +}; + +namespace ForeginWebEngineFileSystemAccessRequestNamespace +{ + Q_NAMESPACE + QML_FOREIGN_NAMESPACE(QWebEngineFileSystemAccessRequestDerived) + QML_NAMED_ELEMENT(WebEngineFileSystemAccessRequest) + QML_ADDED_IN_VERSION(6, 4) +}; + +struct ForeignWebEngineWebAuthUxRequest +{ + Q_GADGET + QML_FOREIGN(QWebEngineWebAuthUxRequest) + QML_NAMED_ELEMENT(WebEngineWebAuthUxRequest) + QML_ADDED_IN_VERSION(6, 7) + QML_UNCREATABLE("") +}; + +QT_END_NAMESPACE + +#endif // QQUICKWEBENGINEFOREIGNTYPES_H diff --git a/src/webenginequick/api/qquickwebenginenewwindowrequest.cpp b/src/webenginequick/api/qquickwebenginenewwindowrequest.cpp new file mode 100644 index 000000000..ecacb1e8f --- /dev/null +++ b/src/webenginequick/api/qquickwebenginenewwindowrequest.cpp @@ -0,0 +1,43 @@ +// Copyright (C) 2021 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + +#include "qquickwebenginenewwindowrequest_p.h" +#include "qquickwebengineview_p.h" + +#include "web_contents_adapter_client.h" + +QT_BEGIN_NAMESPACE + +/*! + \internal +*/ +QQuickWebEngineNewWindowRequest::QQuickWebEngineNewWindowRequest(DestinationType dest, const QRect &rect, const QUrl &url, + bool user, + QSharedPointer<QtWebEngineCore::WebContentsAdapter> adapter, + QObject *parent) + : QWebEngineNewWindowRequest(dest, rect, url, user, adapter, parent) +{ +} + +/*! + \qmlmethod WebEngineNewWindowRequest::openIn(WebEngineView view) + Opens the requested page in the new web engine view \a view. State and history of the + view and the page possibly loaded in it will be lost. + \sa WebEngineView::newWindowRequested +*/ + +/*! + \internal +*/ +void QQuickWebEngineNewWindowRequest::openIn(QQuickWebEngineView *view) +{ + if (!view) { + qWarning("Trying to open a WebEngineNewWindowRequest in an invalid WebEngineView."); + return; + } + view->acceptAsNewWindow(this); +} + +QT_END_NAMESPACE + +#include "moc_qquickwebenginenewwindowrequest_p.cpp" diff --git a/src/webenginequick/api/qquickwebenginenewwindowrequest_p.h b/src/webenginequick/api/qquickwebenginenewwindowrequest_p.h new file mode 100644 index 000000000..f170fa0c6 --- /dev/null +++ b/src/webenginequick/api/qquickwebenginenewwindowrequest_p.h @@ -0,0 +1,48 @@ +// Copyright (C) 2021 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + +#ifndef QQUICKWEBENGINENEWVIEWREQUEST_P_H +#define QQUICKWEBENGINENEWVIEWREQUEST_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 <QtWebEngineQuick/private/qtwebenginequickglobal_p.h> +#include <QtWebEngineCore/qwebenginenewwindowrequest.h> +#include <QtQml/qqmlregistration.h> + +QT_BEGIN_NAMESPACE + +class QQuickWebEngineView; + +class Q_WEBENGINEQUICK_EXPORT QQuickWebEngineNewWindowRequest : public QWebEngineNewWindowRequest +{ + Q_OBJECT +public: + QML_NAMED_ELEMENT(WebEngineNewWindowRequest) + QML_ADDED_IN_VERSION(1, 1) + QML_EXTRA_VERSION(2, 0) + QML_UNCREATABLE("") + + Q_INVOKABLE void openIn(QQuickWebEngineView *); + +private: + QQuickWebEngineNewWindowRequest(DestinationType, const QRect &, const QUrl &, bool, + QSharedPointer<QtWebEngineCore::WebContentsAdapter>, + QObject * = nullptr); + + friend class QQuickWebEngineView; + friend class QQuickWebEngineViewPrivate; +}; + +QT_END_NAMESPACE + +#endif // QQUICKWEBENGINENEWVIEWREQUEST_P_H diff --git a/src/webenginequick/api/qquickwebengineprofile.cpp b/src/webenginequick/api/qquickwebengineprofile.cpp new file mode 100644 index 000000000..edca5e99c --- /dev/null +++ b/src/webenginequick/api/qquickwebengineprofile.cpp @@ -0,0 +1,1053 @@ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + +#include "qquickwebengineprofile.h" +#include "qquickwebengineprofile_p.h" +#include "qquickwebenginedownloadrequest_p.h" +#include "qquickwebenginesettings_p.h" +#include "qquickwebenginescriptcollection_p.h" +#include "qquickwebenginescriptcollection_p_p.h" +#include "qquickwebengineview_p_p.h" + +#include "profile_adapter.h" +#include "web_engine_settings.h" + +#include <QtWebEngineCore/qwebenginescriptcollection.h> +#include <QtWebEngineCore/private/qwebenginescriptcollection_p.h> +#include <QtWebEngineCore/qwebengineclienthints.h> +#include <QtWebEngineCore/qwebenginecookiestore.h> +#include <QtWebEngineCore/qwebenginenotification.h> +#include <QtWebEngineCore/private/qwebenginedownloadrequest_p.h> +#include <QtWebEngineCore/qwebengineurlscheme.h> + +#include <QtCore/qdir.h> +#include <QtCore/qfileinfo.h> +#include <QtQml/qqmlcontext.h> +#include <QtQml/qqmlengine.h> + +using QtWebEngineCore::ProfileAdapter; + +QT_BEGIN_NAMESPACE + +/*! + \class QQuickWebEngineProfile + \brief The QQuickWebEngineProfile class provides a web engine profile shared by multiple pages. + \since 5.6 + + \inmodule QtWebEngineQuick + + A web engine profile contains settings, scripts, persistent cookie policy, and the list of + visited links shared by all web engine pages that belong to the profile. + + Information about visited links is stored together with persistent cookies + and other persistent data in a storage determined by the storageName + property. Persistent data is stored in a subdirectory determined by the + persistentStoragePath property and the cache in a subdirectory determined by + the cachePath property. The httpCacheType property describes the type of the + cache: \e in-memory or \e on-disk. If only the storageName property is set, + the other values are generated automatically based on it. If you specify + any of the values manually, you should do it before creating any pages that + belong to the profile. + + Profiles can be used to isolate pages from each other. A typical use case is a dedicated + \e {off-the-record profile} for a \e {private browsing} mode. An off-the-record profile forces + cookies, the HTTP cache, and other normally persistent data to be stored only in memory. The + offTheRecord property holds whether a profile is off-the-record. + + The default profile can be accessed by defaultProfile(). It is a built-in profile that all + web pages not specifically created with another profile belong to. + + A WebEngineProfile instance can be created and accessed from C++ through the + QQuickWebEngineProfile class, which exposes further functionality in C++. This allows Qt Quick + applications to intercept URL requests (QQuickWebEngineProfile::setRequestInterceptor), or + register custom URL schemes (QQuickWebEngineProfile::installUrlSchemeHandler). + + Spellchecking HTML form fields can be enabled per profile by setting the \l spellCheckEnabled + property and the current languages used for spellchecking can be set by using the + \l spellCheckLanguages property. +*/ + +/*! + \enum QQuickWebEngineProfile::HttpCacheType + + This enum describes the HTTP cache type: + + \value MemoryHttpCache Use an in-memory cache. This is the default if + \c off-the-record is set. + \value DiskHttpCache Use a disk cache. This is the default if \c off-the-record + is not set. Falls back to \c MemoryHttpCache if \c off-the-record is set. + \value NoCache Disable both in-memory and disk caching. (Added in Qt 5.7) +*/ + +/*! + \enum QQuickWebEngineProfile::PersistentCookiesPolicy + + This enum describes policy for cookie persistency: + + \value NoPersistentCookies + Both session and persistent cookies are stored in memory. This is the only setting + possible if \c off-the-record is set or no persistent data path is available. + \value AllowPersistentCookies + Cookies marked persistent are saved to and restored from disk, whereas session cookies + are only stored to disk for crash recovery. This is the default setting. + \value ForcePersistentCookies + Both session and persistent cookies are saved to and restored from disk. +*/ + +/*! + \fn QQuickWebEngineProfile::downloadRequested(QQuickWebEngineDownloadRequest *download) + + This signal is emitted whenever a download has been triggered. + The \a download argument holds the state of the download. + The download has to be explicitly accepted with + \c{QWebEngineDownloadRequest::accept()} or it will be + cancelled by default. + The download item is parented by the profile. If it is not accepted, it + will be deleted immediately after the signal emission. + This signal cannot be used with a queued connection. + + \note To use from C++ static_cast \a download to QWebEngineDownloadRequest +*/ + +/*! + \fn QQuickWebEngineProfile::downloadFinished(QQuickWebEngineDownloadRequest *download) + + This signal is emitted whenever downloading stops, because it finished successfully, was + cancelled, or was interrupted (for example, because connectivity was lost). + The \a download argument holds the state of the finished download instance. + + \note To use from C++ static_cast \a download to QWebEngineDownloadRequest +*/ + +/*! + \fn QQuickWebEngineProfile::presentNotification(QWebEngineNotification *notification) + + This signal is emitted whenever there is a newly created user notification. + The \a notification argument holds the \l {QWebEngineNotification} instance + to query data and interact with. + + \sa WebEngineProfile::presentNotification +*/ + +/*! + \fn QQuickWebEngineProfile::clearHttpCacheCompleted() + \since 6.7 + + This signal is emitted when the clearHttpCache() operation is completed. + + \sa clearHttpCache() +*/ + +QQuickWebEngineProfilePrivate::QQuickWebEngineProfilePrivate(ProfileAdapter *profileAdapter) + : m_settings(new QQuickWebEngineSettings()) + , m_clientHints(new QWebEngineClientHints(profileAdapter)) + , m_profileAdapter(profileAdapter) +{ + profileAdapter->addClient(this); + // Fullscreen API was implemented before the supported setting, so we must + // make it default true to avoid change in default API behavior. + m_settings->d_ptr->setAttribute(QWebEngineSettings::FullScreenSupportEnabled, true); +} + +QQuickWebEngineProfilePrivate::~QQuickWebEngineProfilePrivate() +{ + if (m_profileAdapter) { + // In the case the user sets this profile as the parent of the interceptor + // it can be deleted before the browser-context still referencing it is. + m_profileAdapter->setRequestInterceptor(nullptr); + m_profileAdapter->removeClient(this); + } + + if (m_profileAdapter != QtWebEngineCore::ProfileAdapter::defaultProfileAdapter()) + delete m_profileAdapter; + else if (m_profileAdapter) + m_profileAdapter->releaseAllWebContentsAdapterClients(); +} + +void QQuickWebEngineProfilePrivate::addWebContentsAdapterClient(QtWebEngineCore::WebContentsAdapterClient *adapter) +{ + Q_ASSERT(m_profileAdapter); + m_profileAdapter->addWebContentsAdapterClient(adapter); +} + +void QQuickWebEngineProfilePrivate::removeWebContentsAdapterClient(QtWebEngineCore::WebContentsAdapterClient*adapter) +{ + Q_ASSERT(m_profileAdapter); + m_profileAdapter->removeWebContentsAdapterClient(adapter); +} + +QtWebEngineCore::ProfileAdapter *QQuickWebEngineProfilePrivate::profileAdapter() const +{ + return m_profileAdapter; +} + +QQuickWebEngineSettings *QQuickWebEngineProfilePrivate::settings() const +{ + return m_settings.data(); +} + +QtWebEngineCore::WebEngineSettings *QQuickWebEngineProfilePrivate::coreSettings() const +{ + return QtWebEngineCore::WebEngineSettings::get(m_settings->d_ptr.data()); +} + +void QQuickWebEngineProfilePrivate::cancelDownload(quint32 downloadId) +{ + if (m_profileAdapter) + m_profileAdapter->cancelDownload(downloadId); +} + +void QQuickWebEngineProfilePrivate::downloadDestroyed(quint32 downloadId) +{ + m_ongoingDownloads.remove(downloadId); + if (m_profileAdapter) + m_profileAdapter->removeDownload(downloadId); +} + +void QQuickWebEngineProfilePrivate::cleanDownloads() +{ + for (auto download : m_ongoingDownloads.values()) { + if (!download) + continue; + + if (!download->isFinished()) + download->cancel(); + + if (m_profileAdapter) + m_profileAdapter->removeDownload(download->id()); + } + m_ongoingDownloads.clear(); +} + +void QQuickWebEngineProfilePrivate::downloadRequested(DownloadItemInfo &info) +{ + Q_Q(QQuickWebEngineProfile); + + Q_ASSERT(!m_ongoingDownloads.contains(info.id)); + QWebEngineDownloadRequestPrivate *itemPrivate = + new QWebEngineDownloadRequestPrivate(m_profileAdapter); + itemPrivate->downloadId = info.id; + itemPrivate->downloadState = info.accepted ? QWebEngineDownloadRequest::DownloadInProgress + : QWebEngineDownloadRequest::DownloadRequested; + itemPrivate->startTime = info.startTime; + itemPrivate->downloadUrl = info.url; + itemPrivate->totalBytes = info.totalBytes; + itemPrivate->mimeType = info.mimeType; + itemPrivate->downloadDirectory = QFileInfo(info.path).path(); + itemPrivate->downloadFileName = QFileInfo(info.path).fileName(); + itemPrivate->suggestedFileName = info.suggestedFileName; + itemPrivate->savePageFormat = static_cast<QWebEngineDownloadRequest::SavePageFormat>( + info.savePageFormat); + itemPrivate->isSavePageDownload = info.isSavePageDownload; + if (info.page && info.page->clientType() == QtWebEngineCore::WebContentsAdapterClient::QmlClient) + itemPrivate->adapterClient = info.page; + else + itemPrivate->adapterClient = nullptr; + + QQuickWebEngineDownloadRequest *download = new QQuickWebEngineDownloadRequest(itemPrivate, q); + + m_ongoingDownloads.insert(info.id, download); + QObject::connect(download, &QObject::destroyed, q, [id = info.id, this] () { downloadDestroyed(id); }); + + QQmlEngine::setObjectOwnership(download, QQmlEngine::JavaScriptOwnership); + Q_EMIT q->downloadRequested(download); + + QWebEngineDownloadRequest::DownloadState state = download->state(); + info.path = QDir(download->downloadDirectory()).filePath(download->downloadFileName()); + info.savePageFormat = itemPrivate->savePageFormat; + info.accepted = state != QWebEngineDownloadRequest::DownloadCancelled + && state != QWebEngineDownloadRequest::DownloadRequested; + + if (state == QWebEngineDownloadRequest::DownloadRequested) { + // Delete unaccepted downloads. + info.accepted = false; + delete download; + } +} + +void QQuickWebEngineProfilePrivate::downloadUpdated(const DownloadItemInfo &info) +{ + if (!m_ongoingDownloads.contains(info.id)) + return; + + Q_Q(QQuickWebEngineProfile); + + QQuickWebEngineDownloadRequest* download = m_ongoingDownloads.value(info.id).data(); + + if (!download) { + downloadDestroyed(info.id); + return; + } + + download->d_ptr->update(info); + + if (info.state != ProfileAdapterClient::DownloadInProgress) { + Q_EMIT q->downloadFinished(download); + } +} + +void QQuickWebEngineProfilePrivate::showNotification(QSharedPointer<QtWebEngineCore::UserNotificationController> &controller) +{ + Q_Q(QQuickWebEngineProfile); + auto notification = new QWebEngineNotification(controller); + QQmlEngine::setObjectOwnership(notification, QQmlEngine::JavaScriptOwnership); + Q_EMIT q->presentNotification(notification); +} + +void QQuickWebEngineProfilePrivate::clearHttpCacheCompleted() +{ + Q_Q(QQuickWebEngineProfile); + Q_EMIT q->clearHttpCacheCompleted(); +} + +QQuickWebEngineScriptCollection *QQuickWebEngineProfilePrivate::getUserScripts() +{ + Q_Q(QQuickWebEngineProfile); + if (!m_scriptCollection) + m_scriptCollection.reset( + new QQuickWebEngineScriptCollection( + new QQuickWebEngineScriptCollectionPrivate( + new QWebEngineScriptCollectionPrivate( + m_profileAdapter->userResourceController())))); + + if (!m_scriptCollection->qmlEngine()) + m_scriptCollection->setQmlEngine(qmlEngine(q)); + + return m_scriptCollection.data(); +} +/*! + \qmltype WebEngineProfile + \instantiates QQuickWebEngineProfile + \inqmlmodule QtWebEngine + \since QtWebEngine 1.1 + \brief Contains settings, scripts, and visited links common to multiple web engine views. + + WebEngineProfile contains settings, scripts, and the list of visited links shared by all + views that belong to the profile. + + Information about visited links is stored together with persistent cookies + and other persistent data in a storage determined by the storageName + property. Persistent data is stored in a subdirectory determined by the + persistentStoragePath property and the cache in a subdirectory determined by + the cachePath property. The httpCacheType property describes the type of the + cache: \e in-memory or \e on-disk. If only the storageName property is set, + the other values are generated automatically based on it. If you specify + any of the values manually, you should do it before creating any pages that + belong to the profile. + + Profiles can be used to isolate pages from each other. A typical use case is + a dedicated \e {off-the-record profile} for a \e {private browsing} mode. An + off-the-record profile forces cookies, the HTTP cache, and other normally + persistent data to be stored only in memory. The offTheRecord property holds + whether a profile is off-the-record. + + Each web engine view has an associated profile. Views that do not have a specific profile set + share a common default one. +*/ + +/*! + \qmlsignal WebEngineProfile::downloadRequested(WebEngineDownloadRequest download) + + This signal is emitted whenever a download has been triggered. + The \a download argument holds the state of the download. + The download has to be explicitly accepted with WebEngineDownloadRequest::accept() or the + download will be cancelled by default. +*/ + +/*! + \qmlsignal WebEngineProfile::downloadFinished(WebEngineDownloadRequest download) + + This signal is emitted whenever downloading stops, because it finished successfully, was + cancelled, or was interrupted (for example, because connectivity was lost). + The \a download argument holds the state of the finished download instance. +*/ + +/*! + \qmlsignal WebEngineProfile::presentNotification(WebEngineNotification notification) + \since QtWebEngine 1.9 + + This signal is emitted whenever there is a newly created user notification. + The \a notification argument holds the \l {WebEngineNotification} instance + to query data and interact with. +*/ + +/*! + \qmlsignal WebEngineProfile::clearHttpCacheCompleted() + \since QtWebEngine 6.7 + + This signal is emitted when the clearHttpCache() operation is completed. + + \sa clearHttpCache() +*/ + +/*! + Constructs a new profile with the parent \a parent. +*/ +QQuickWebEngineProfile::QQuickWebEngineProfile(QObject *parent) + : QObject(parent), + d_ptr(new QQuickWebEngineProfilePrivate(new QtWebEngineCore::ProfileAdapter())) +{ + d_ptr->q_ptr = this; +} + +QQuickWebEngineProfile::QQuickWebEngineProfile(QQuickWebEngineProfilePrivate *privatePtr, QObject *parent) + : QObject(parent) + , d_ptr(privatePtr) +{ + d_ptr->q_ptr = this; +} + +/*! + \internal +*/ +QQuickWebEngineProfile::~QQuickWebEngineProfile() +{ + d_ptr->cleanDownloads(); +} + +/*! + \qmlproperty string WebEngineProfile::storageName + + The storage name that is used to create separate subdirectories for each profile that uses + the disk for storing persistent data and cache. + + \sa WebEngineProfile::persistentStoragePath, WebEngineProfile::cachePath +*/ + +/*! + \property QQuickWebEngineProfile::storageName + + The storage name that is used to create separate subdirectories for each profile that uses + the disk for storing persistent data and cache. + + \sa persistentStoragePath, cachePath +*/ + +QString QQuickWebEngineProfile::storageName() const +{ + const Q_D(QQuickWebEngineProfile); + return d->profileAdapter()->storageName(); +} + +void QQuickWebEngineProfile::setStorageName(const QString &name) +{ + Q_D(QQuickWebEngineProfile); + if (d->profileAdapter()->storageName() == name) + return; + ProfileAdapter::HttpCacheType oldCacheType = d->profileAdapter()->httpCacheType(); + ProfileAdapter::PersistentCookiesPolicy oldPolicy = d->profileAdapter()->persistentCookiesPolicy(); + d->profileAdapter()->setStorageName(name); + emit storageNameChanged(); + emit persistentStoragePathChanged(); + emit cachePathChanged(); + if (d->profileAdapter()->httpCacheType() != oldCacheType) + emit httpCacheTypeChanged(); + if (d->profileAdapter()->persistentCookiesPolicy() != oldPolicy) + emit persistentCookiesPolicyChanged(); +} + +/*! + \qmlproperty bool WebEngineProfile::offTheRecord + + Whether the web engine profile is \e off-the-record. + An off-the-record profile forces cookies, the HTTP cache, and other normally persistent data + to be stored only in memory. Profile is off-the-record by default. +*/ + + +/*! + \property QQuickWebEngineProfile::offTheRecord + + Whether the web engine profile is \e off-the-record. + An off-the-record profile forces cookies, the HTTP cache, and other normally persistent data + to be stored only in memory. Profile is off-the-record by default. +*/ + +bool QQuickWebEngineProfile::isOffTheRecord() const +{ + const Q_D(QQuickWebEngineProfile); + return d->profileAdapter()->isOffTheRecord(); +} + +void QQuickWebEngineProfile::setOffTheRecord(bool offTheRecord) +{ + Q_D(QQuickWebEngineProfile); + if (d->profileAdapter()->isOffTheRecord() == offTheRecord) + return; + ProfileAdapter::HttpCacheType oldCacheType = d->profileAdapter()->httpCacheType(); + ProfileAdapter::PersistentCookiesPolicy oldPolicy = d->profileAdapter()->persistentCookiesPolicy(); + d->profileAdapter()->setOffTheRecord(offTheRecord); + emit offTheRecordChanged(); + if (d->profileAdapter()->httpCacheType() != oldCacheType) + emit httpCacheTypeChanged(); + if (d->profileAdapter()->persistentCookiesPolicy() != oldPolicy) + emit persistentCookiesPolicyChanged(); +} + +/*! + \qmlproperty string WebEngineProfile::persistentStoragePath + + The path to the location where the persistent data for the browser and web content are + stored. Persistent data includes persistent cookies, HTML5 local storage, and visited links. + + By default, the storage is located below + QStandardPaths::writableLocation(QStandardPaths::AppDataLocation) in a directory named using + storageName. +*/ + +/*! + \property QQuickWebEngineProfile::persistentStoragePath + + The path to the location where the persistent data for the browser and web content are + stored. Persistent data includes persistent cookies, HTML5 local storage, and visited links. + + By default, the storage is located below + QStandardPaths::writableLocation(QStandardPaths::AppDataLocation) in a directory named using + storageName. +*/ + +QString QQuickWebEngineProfile::persistentStoragePath() const +{ + const Q_D(QQuickWebEngineProfile); + return d->profileAdapter()->dataPath(); +} + +void QQuickWebEngineProfile::setPersistentStoragePath(const QString &path) +{ + Q_D(QQuickWebEngineProfile); + if (persistentStoragePath() == path) + return; + d->profileAdapter()->setDataPath(path); + emit persistentStoragePathChanged(); +} + +/*! + \qmlproperty string WebEngineProfile::cachePath + + The path to the location where the profile's caches are stored, in particular the HTTP cache. + + By default, the caches are stored + below QStandardPaths::writableLocation(QStandardPaths::CacheLocation) in a directory named using + storageName. +*/ + +/*! + \property QQuickWebEngineProfile::cachePath + + The path to the location where the profile's caches are stored, in particular the HTTP cache. + + By default, the caches are stored + below QStandardPaths::writableLocation(QStandardPaths::CacheLocation) in a directory named using + storageName. +*/ + +QString QQuickWebEngineProfile::cachePath() const +{ + const Q_D(QQuickWebEngineProfile); + return d->profileAdapter()->cachePath(); +} + +void QQuickWebEngineProfile::setCachePath(const QString &path) +{ + Q_D(QQuickWebEngineProfile); + if (cachePath() == path) + return; + d->profileAdapter()->setCachePath(path); + emit cachePathChanged(); +} + +/*! + \qmlproperty string WebEngineProfile::httpUserAgent + + The user-agent string sent with HTTP to identify the browser. + + \note On Windows 8.1 and newer, the default user agent will always report + "Windows NT 6.2" (Windows 8), unless the application does contain a manifest + that declares newer Windows versions as supported. +*/ + +/*! + \property QQuickWebEngineProfile::httpUserAgent + + The user-agent string sent with HTTP to identify the browser. +*/ + +QString QQuickWebEngineProfile::httpUserAgent() const +{ + const Q_D(QQuickWebEngineProfile); + return d->profileAdapter()->httpUserAgent(); +} + +void QQuickWebEngineProfile::setHttpUserAgent(const QString &userAgent) +{ + Q_D(QQuickWebEngineProfile); + if (d->profileAdapter()->httpUserAgent() == userAgent) + return; + d->profileAdapter()->setHttpUserAgent(userAgent); + emit httpUserAgentChanged(); +} + + +/*! + \qmlproperty enumeration WebEngineProfile::httpCacheType + + This enumeration describes the type of the HTTP cache: + + \value WebEngineProfile.MemoryHttpCache + Uses an in-memory cache. This is the only setting possible if offTheRecord is set or + no storageName is available, which is the default. + \value WebEngineProfile.DiskHttpCache + Uses a disk cache. This is the default value for non off-the-record profile with storageName. + \value WebEngineProfile.NoCache + Disables caching. (Added in 5.7) +*/ + +/*! + \property QQuickWebEngineProfile::httpCacheType + + This enumeration describes the type of the HTTP cache. + + If the profile is off-the-record or has no storageName set, MemoryHttpCache is returned. +*/ + +QQuickWebEngineProfile::HttpCacheType QQuickWebEngineProfile::httpCacheType() const +{ + const Q_D(QQuickWebEngineProfile); + return QQuickWebEngineProfile::HttpCacheType(d->profileAdapter()->httpCacheType()); +} + +void QQuickWebEngineProfile::setHttpCacheType(QQuickWebEngineProfile::HttpCacheType httpCacheType) +{ + Q_D(QQuickWebEngineProfile); + ProfileAdapter::HttpCacheType oldCacheType = d->profileAdapter()->httpCacheType(); + d->profileAdapter()->setHttpCacheType(ProfileAdapter::HttpCacheType(httpCacheType)); + if (d->profileAdapter()->httpCacheType() != oldCacheType) + emit httpCacheTypeChanged(); +} + +/*! + \qmlproperty enumeration WebEngineProfile::persistentCookiesPolicy + + This enumeration describes the policy of cookie persistency: + + \value WebEngineProfile.NoPersistentCookies + Both session and persistent cookies are stored in memory. This is the only setting + possible if offTheRecord is set or no storageName is available, which is the default. + \value WebEngineProfile.AllowPersistentCookies + Cookies marked persistent are saved to and restored from disk, whereas session cookies + are only stored to disk for crash recovery. + This is the default value for non off-the-record profile with storageName. + \value WebEngineProfile.ForcePersistentCookies + Both session and persistent cookies are saved to and restored from disk. +*/ + +/*! + \property QQuickWebEngineProfile::persistentCookiesPolicy + + This enumeration describes the policy of cookie persistency. + If the profile is off-the-record, NoPersistentCookies is returned. +*/ + +QQuickWebEngineProfile::PersistentCookiesPolicy QQuickWebEngineProfile::persistentCookiesPolicy() const +{ + const Q_D(QQuickWebEngineProfile); + return QQuickWebEngineProfile::PersistentCookiesPolicy(d->profileAdapter()->persistentCookiesPolicy()); +} + +void QQuickWebEngineProfile::setPersistentCookiesPolicy(QQuickWebEngineProfile::PersistentCookiesPolicy newPersistentCookiesPolicy) +{ + Q_D(QQuickWebEngineProfile); + ProfileAdapter::PersistentCookiesPolicy oldPolicy = d->profileAdapter()->persistentCookiesPolicy(); + d->profileAdapter()->setPersistentCookiesPolicy(ProfileAdapter::PersistentCookiesPolicy(newPersistentCookiesPolicy)); + if (d->profileAdapter()->persistentCookiesPolicy() != oldPolicy) + emit persistentCookiesPolicyChanged(); +} + +/*! + \qmlproperty int WebEngineProfile::httpCacheMaximumSize + + The maximum size of the HTTP cache. If \c 0, the size will be controlled automatically by + QtWebEngine. The default value is \c 0. + + \sa httpCacheType +*/ + +/*! + \property QQuickWebEngineProfile::httpCacheMaximumSize + + The maximum size of the HTTP cache. If \c 0, the size will be controlled automatically by + QtWebEngine. The default value is \c 0. + + \sa httpCacheType +*/ + +int QQuickWebEngineProfile::httpCacheMaximumSize() const +{ + const Q_D(QQuickWebEngineProfile); + return d->profileAdapter()->httpCacheMaxSize(); +} + +void QQuickWebEngineProfile::setHttpCacheMaximumSize(int maximumSize) +{ + Q_D(QQuickWebEngineProfile); + if (d->profileAdapter()->httpCacheMaxSize() == maximumSize) + return; + d->profileAdapter()->setHttpCacheMaxSize(maximumSize); + emit httpCacheMaximumSizeChanged(); +} + +/*! + \qmlproperty string WebEngineProfile::httpAcceptLanguage + + The value of the Accept-Language HTTP request-header field. + + \since QtWebEngine 1.2 +*/ + +/*! + \property QQuickWebEngineProfile::httpAcceptLanguage + + The value of the Accept-Language HTTP request-header field. +*/ + +QString QQuickWebEngineProfile::httpAcceptLanguage() const +{ + Q_D(const QQuickWebEngineProfile); + return d->profileAdapter()->httpAcceptLanguage(); +} + +void QQuickWebEngineProfile::setHttpAcceptLanguage(const QString &httpAcceptLanguage) +{ + Q_D(QQuickWebEngineProfile); + if (d->profileAdapter()->httpAcceptLanguage() == httpAcceptLanguage) + return; + d->profileAdapter()->setHttpAcceptLanguage(httpAcceptLanguage); + emit httpAcceptLanguageChanged(); +} + +/*! + Returns the default profile. + + The default profile is off-the-record. + + \sa storageName() +*/ +QQuickWebEngineProfile *QQuickWebEngineProfile::defaultProfile() +{ + static QQuickWebEngineProfile *profile = new QQuickWebEngineProfile( + new QQuickWebEngineProfilePrivate(ProfileAdapter::createDefaultProfileAdapter()), + ProfileAdapter::globalQObjectRoot()); + return profile; +} + +/*! + \property QQuickWebEngineProfile::spellCheckLanguages + \brief The languages used by the spell checker. + + \since QtWebEngine 1.4 +*/ + +/*! + \qmlproperty list<string> WebEngineProfile::spellCheckLanguages + + This property holds the list of languages used by the spell checker. + Each language should match the name of the \c .bdic dictionary. + For example, the language \c en-US will load the \c en-US.bdic + dictionary file. + + See the \l {Spellchecker}{Spellchecker feature documentation} for how + dictionary files are searched. + + For more information about how to compile \c .bdic dictionaries, see the + \l{WebEngine Widgets Spellchecker Example}{Spellchecker Example}. + + \since QtWebEngine 1.4 +*/ +void QQuickWebEngineProfile::setSpellCheckLanguages(const QStringList &languages) +{ + Q_D(QQuickWebEngineProfile); + if (languages != d->profileAdapter()->spellCheckLanguages()) { + d->profileAdapter()->setSpellCheckLanguages(languages); + emit spellCheckLanguagesChanged(); + } +} + +/*! + \since 5.8 + + Returns the list of languages used by the spell checker. +*/ +QStringList QQuickWebEngineProfile::spellCheckLanguages() const +{ + const Q_D(QQuickWebEngineProfile); + return d->profileAdapter()->spellCheckLanguages(); +} + +/*! + \property QQuickWebEngineProfile::spellCheckEnabled + \brief whether the web engine spell checker is enabled. + + \since QtWebEngine 1.4 +*/ + +/*! + \qmlproperty bool WebEngineProfile::spellCheckEnabled + + This property holds whether the web engine spell checker is enabled. + + \since QtWebEngine 1.4 +*/ +void QQuickWebEngineProfile::setSpellCheckEnabled(bool enable) +{ + Q_D(QQuickWebEngineProfile); + if (enable != isSpellCheckEnabled()) { + d->profileAdapter()->setSpellCheckEnabled(enable); + emit spellCheckEnabledChanged(); + } +} + +bool QQuickWebEngineProfile::isSpellCheckEnabled() const +{ + const Q_D(QQuickWebEngineProfile); + return d->profileAdapter()->isSpellCheckEnabled(); +} + +/*! + \qmlproperty string WebEngineProfile::downloadPath + \since QtWebEngine 1.9 + + The path to the location where the downloaded files are stored. + + Overrides the default path used for download location. + + If set to an empty string, the default path is restored. + + \note By default, the download path is QStandardPaths::DownloadLocation. +*/ + +/*! + \property QQuickWebEngineProfile::downloadPath + \since QtWebEngine 1.9 + + The path to the location where the downloaded files are stored. + + Overrides the default path used for download location, setting it to \a path. + + If set to an empty string, the default path is restored. + + \note By default, the download path is QStandardPaths::DownloadLocation. +*/ + +void QQuickWebEngineProfile::setDownloadPath(const QString &path) +{ + Q_D(QQuickWebEngineProfile); + if (downloadPath() == path) + return; + d->profileAdapter()->setDownloadPath(path); + emit downloadPathChanged(); +} + +QString QQuickWebEngineProfile::downloadPath() const +{ + const Q_D(QQuickWebEngineProfile); + return d->profileAdapter()->downloadPath(); +} + +/*! + \qmlproperty bool WebEngineProfile::isPushServiceEnabled + \since QtWebEngine 6.5 + + Whether the push messaging service is enabled. + \note By default the push messaging service is disabled. + \note \QWE uses the \l {https://firebase.google.com}{Firebase Cloud Messaging (FCM)} as a browser push service. + Therefore, all push messages will go through the Google push service and its respective servers. +*/ + +/*! + \property QQuickWebEngineProfile::isPushServiceEnabled + \since QtWebEngine 6.5 + + Whether the push messaging service is enabled. + \note By default the push messaging service is disabled. + \note \QWE uses the \l {https://firebase.google.com}{Firebase Cloud Messaging (FCM)} as a browser push service. + Therefore, all push messages will go through the Google push service and its respective servers. +*/ + +bool QQuickWebEngineProfile::isPushServiceEnabled() const +{ + const Q_D(QQuickWebEngineProfile); + return d->profileAdapter()->pushServiceEnabled(); +} + +void QQuickWebEngineProfile::setPushServiceEnabled(bool enabled) +{ + Q_D(QQuickWebEngineProfile); + if (isPushServiceEnabled() == enabled) + return; + d->profileAdapter()->setPushServiceEnabled(enabled); + emit pushServiceEnabledChanged(); +} + +/*! + + Returns the cookie store for this profile. +*/ +QWebEngineCookieStore *QQuickWebEngineProfile::cookieStore() const +{ + const Q_D(QQuickWebEngineProfile); + return d->profileAdapter()->cookieStore(); +} + +/*! + \qmlmethod void WebEngineProfile::clearHttpCache() + \since QtWebEngine 1.3 + + Removes the profile's cache entries. + + \note Make sure that you do not start new navigation or any operation on the profile while + the clear operation is in progress. The clearHttpCacheCompleted() signal notifies about the + completion. + + \sa WebEngineProfile::cachePath clearHttpCacheCompleted() +*/ + +/*! + \since 5.7 + + Removes the profile's cache entries. + + \note Make sure that you do not start new navigation or any operation on the profile while + the clear operation is in progress. The clearHttpCacheCompleted() signal notifies about the + completion. + + \sa WebEngineProfile::clearHttpCache() clearHttpCacheCompleted() +*/ +void QQuickWebEngineProfile::clearHttpCache() +{ + Q_D(QQuickWebEngineProfile); + d->profileAdapter()->clearHttpCache(); +} + +/*! + Registers a request interceptor singleton \a interceptor to intercept URL requests. + + The profile does not take ownership of the pointer. + + \sa QWebEngineUrlRequestInfo QWebEngineUrlRequestInterceptor +*/ +void QQuickWebEngineProfile::setUrlRequestInterceptor(QWebEngineUrlRequestInterceptor *interceptor) +{ + Q_D(QQuickWebEngineProfile); + d->profileAdapter()->setRequestInterceptor(interceptor); +} + + +/*! + Returns the custom URL scheme handler register for the URL scheme \a scheme. +*/ +const QWebEngineUrlSchemeHandler *QQuickWebEngineProfile::urlSchemeHandler(const QByteArray &scheme) const +{ + const Q_D(QQuickWebEngineProfile); + return d->profileAdapter()->urlSchemeHandler(scheme); +} + +/*! + Registers a handler \a handler for custom URL scheme \a scheme in the profile. + + It is necessary to first register the scheme with \l + QWebEngineUrlScheme::registerScheme at application startup. +*/ +void QQuickWebEngineProfile::installUrlSchemeHandler(const QByteArray &scheme, QWebEngineUrlSchemeHandler *handler) +{ + Q_D(QQuickWebEngineProfile); + d->profileAdapter()->installUrlSchemeHandler(scheme, handler); +} + +/*! + Removes the custom URL scheme handler \a handler from the profile. + + \sa removeUrlScheme() +*/ +void QQuickWebEngineProfile::removeUrlSchemeHandler(QWebEngineUrlSchemeHandler *handler) +{ + Q_D(QQuickWebEngineProfile); + d->profileAdapter()->removeUrlSchemeHandler(handler); +} + +/*! + Removes the custom URL scheme \a scheme from the profile. + + \sa removeUrlSchemeHandler() +*/ +void QQuickWebEngineProfile::removeUrlScheme(const QByteArray &scheme) +{ + Q_D(QQuickWebEngineProfile); + d->profileAdapter()->removeUrlScheme(scheme); +} + +/*! + Removes all custom URL scheme handlers installed in the profile. +*/ +void QQuickWebEngineProfile::removeAllUrlSchemeHandlers() +{ + Q_D(QQuickWebEngineProfile); + d->profileAdapter()->removeAllUrlSchemeHandlers(); +} + +QQuickWebEngineSettings *QQuickWebEngineProfile::settings() const +{ + const Q_D(QQuickWebEngineProfile); + return d->settings(); +} + +/*! + \qmlproperty WebEngineScriptCollection WebEngineProfile::userScripts + \since 1.5 + + Returns the collection of WebEngineScript objects that are injected into + all pages that share this profile. +*/ + +QQuickWebEngineScriptCollection *QQuickWebEngineProfile::userScripts() const +{ + return d_ptr->getUserScripts(); +} + +/*! + \since 5.13 + + Returns the profile's client certificate store. +*/ +QWebEngineClientCertificateStore *QQuickWebEngineProfile::clientCertificateStore() +{ +#if QT_CONFIG(ssl) + Q_D(QQuickWebEngineProfile); + return d->profileAdapter()->clientCertificateStore(); +#else + return nullptr; +#endif +} + +/*! + Return the Client Hints settings associated with this browsing context. + + \since 6.8 + \sa QWebEngineClientHints +*/ +QWebEngineClientHints *QQuickWebEngineProfile::clientHints() const +{ + Q_D(const QQuickWebEngineProfile); + return d->m_clientHints.data(); +} + +void QQuickWebEngineProfile::ensureQmlContext(const QObject *object) +{ + if (!qmlContext(this)) { + auto engine = qmlEngine(object); + QQmlEngine::setContextForObject(this, new QQmlContext(engine, engine)); + } +} + +QT_END_NAMESPACE + +#include "moc_qquickwebengineprofile.cpp" diff --git a/src/webenginequick/api/qquickwebengineprofile.h b/src/webenginequick/api/qquickwebengineprofile.h new file mode 100644 index 000000000..cbeb91147 --- /dev/null +++ b/src/webenginequick/api/qquickwebengineprofile.h @@ -0,0 +1,156 @@ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + +#ifndef QQUICKWEBENGINEPROFILE_H +#define QQUICKWEBENGINEPROFILE_H + +#include <QtWebEngineQuick/qtwebenginequickglobal.h> +#include <QtCore/qobject.h> +#include <QtCore/qscopedpointer.h> +#include <QtCore/qstring.h> +#include <QtQml/qqmlregistration.h> + +QT_BEGIN_NAMESPACE + +class QQuickWebEngineDownloadRequest; +class QQuickWebEngineSettings; +class QWebEngineClientCertificateStore; +class QWebEngineClientHints; +class QWebEngineCookieStore; +class QWebEngineNotification; +class QWebEngineUrlRequestInterceptor; +class QWebEngineUrlSchemeHandler; +class QQuickWebEngineScriptCollection; +class QQuickWebEngineProfilePrivate; + +class Q_WEBENGINEQUICK_EXPORT QQuickWebEngineProfile : public QObject { + Q_OBJECT + Q_PROPERTY(QString storageName READ storageName WRITE setStorageName NOTIFY storageNameChanged FINAL) + Q_PROPERTY(bool offTheRecord READ isOffTheRecord WRITE setOffTheRecord NOTIFY offTheRecordChanged FINAL) + Q_PROPERTY(QString persistentStoragePath READ persistentStoragePath WRITE setPersistentStoragePath NOTIFY persistentStoragePathChanged FINAL) + Q_PROPERTY(QString cachePath READ cachePath WRITE setCachePath NOTIFY cachePathChanged FINAL) + Q_PROPERTY(QString httpUserAgent READ httpUserAgent WRITE setHttpUserAgent NOTIFY httpUserAgentChanged FINAL) + Q_PROPERTY(HttpCacheType httpCacheType READ httpCacheType WRITE setHttpCacheType NOTIFY httpCacheTypeChanged FINAL) + Q_PROPERTY(QString httpAcceptLanguage READ httpAcceptLanguage WRITE setHttpAcceptLanguage NOTIFY httpAcceptLanguageChanged FINAL REVISION(1,1)) + Q_PROPERTY(PersistentCookiesPolicy persistentCookiesPolicy READ persistentCookiesPolicy WRITE setPersistentCookiesPolicy NOTIFY persistentCookiesPolicyChanged FINAL) + Q_PROPERTY(int httpCacheMaximumSize READ httpCacheMaximumSize WRITE setHttpCacheMaximumSize NOTIFY httpCacheMaximumSizeChanged FINAL) + Q_PROPERTY(QStringList spellCheckLanguages READ spellCheckLanguages WRITE setSpellCheckLanguages NOTIFY spellCheckLanguagesChanged FINAL REVISION(1,3)) + Q_PROPERTY(bool spellCheckEnabled READ isSpellCheckEnabled WRITE setSpellCheckEnabled NOTIFY spellCheckEnabledChanged FINAL REVISION(1,3)) + Q_PROPERTY(QQuickWebEngineScriptCollection *userScripts READ userScripts) + Q_PROPERTY(QString downloadPath READ downloadPath WRITE setDownloadPath NOTIFY downloadPathChanged FINAL REVISION(1,5)) + Q_PROPERTY(bool isPushServiceEnabled READ isPushServiceEnabled WRITE setPushServiceEnabled NOTIFY pushServiceEnabledChanged FINAL REVISION(6,5)) + QML_NAMED_ELEMENT(WebEngineProfile) + QML_ADDED_IN_VERSION(1, 1) + QML_EXTRA_VERSION(2, 0) + +public: + QQuickWebEngineProfile(QObject *parent = nullptr); + ~QQuickWebEngineProfile(); + + enum HttpCacheType { + MemoryHttpCache, + DiskHttpCache, + NoCache + }; + Q_ENUM(HttpCacheType) + + enum PersistentCookiesPolicy { + NoPersistentCookies, + AllowPersistentCookies, + ForcePersistentCookies + }; + Q_ENUM(PersistentCookiesPolicy) + + QString storageName() const; + void setStorageName(const QString &name); + + bool isOffTheRecord() const; + void setOffTheRecord(bool offTheRecord); + + QString persistentStoragePath() const; + void setPersistentStoragePath(const QString &path); + + QString cachePath() const; + void setCachePath(const QString &path); + + QString httpUserAgent() const; + void setHttpUserAgent(const QString &userAgent); + + HttpCacheType httpCacheType() const; + void setHttpCacheType(QQuickWebEngineProfile::HttpCacheType); + + PersistentCookiesPolicy persistentCookiesPolicy() const; + void setPersistentCookiesPolicy(QQuickWebEngineProfile::PersistentCookiesPolicy); + + int httpCacheMaximumSize() const; + void setHttpCacheMaximumSize(int maxSize); + + QString httpAcceptLanguage() const; + void setHttpAcceptLanguage(const QString &httpAcceptLanguage); + + QWebEngineCookieStore *cookieStore() const; + + void setUrlRequestInterceptor(QWebEngineUrlRequestInterceptor *interceptor); + + const QWebEngineUrlSchemeHandler *urlSchemeHandler(const QByteArray &) const; + void installUrlSchemeHandler(const QByteArray &scheme, QWebEngineUrlSchemeHandler *); + void removeUrlScheme(const QByteArray &scheme); + void removeUrlSchemeHandler(QWebEngineUrlSchemeHandler *); + void removeAllUrlSchemeHandlers(); + + Q_REVISION(1,2) Q_INVOKABLE void clearHttpCache(); + + void setSpellCheckLanguages(const QStringList &languages); + QStringList spellCheckLanguages() const; + void setSpellCheckEnabled(bool enabled); + bool isSpellCheckEnabled() const; + + QQuickWebEngineScriptCollection *userScripts() const; + + QString downloadPath() const; + void setDownloadPath(const QString &path); + + bool isPushServiceEnabled() const; + void setPushServiceEnabled(bool enable); + + QWebEngineClientCertificateStore *clientCertificateStore(); + QWebEngineClientHints *clientHints() const; + + static QQuickWebEngineProfile *defaultProfile(); + +Q_SIGNALS: + void storageNameChanged(); + void offTheRecordChanged(); + void persistentStoragePathChanged(); + void cachePathChanged(); + void httpUserAgentChanged(); + void httpCacheTypeChanged(); + void persistentCookiesPolicyChanged(); + void httpCacheMaximumSizeChanged(); + Q_REVISION(1,1) void httpAcceptLanguageChanged(); + Q_REVISION(1,3) void spellCheckLanguagesChanged(); + Q_REVISION(1,3) void spellCheckEnabledChanged(); + Q_REVISION(1,5) void downloadPathChanged(); + Q_REVISION(6,5) void pushServiceEnabledChanged(); + Q_REVISION(6,7) void clearHttpCacheCompleted(); + void downloadRequested(QQuickWebEngineDownloadRequest *download); + void downloadFinished(QQuickWebEngineDownloadRequest *download); + + Q_REVISION(1,5) void presentNotification(QWebEngineNotification *notification); + +private: + Q_DECLARE_PRIVATE(QQuickWebEngineProfile) + QQuickWebEngineProfile(QQuickWebEngineProfilePrivate *, QObject *parent = nullptr); + QQuickWebEngineSettings *settings() const; + void ensureQmlContext(const QObject *object); + + friend class FaviconImageRequester; + friend class QQuickWebEngineSingleton; + friend class QQuickWebEngineViewPrivate; + friend class QQuickWebEngineView; + QScopedPointer<QQuickWebEngineProfilePrivate> d_ptr; +}; + +QT_END_NAMESPACE + +#endif // QQUICKWEBENGINEPROFILE_H diff --git a/src/webenginequick/api/qquickwebengineprofile_p.h b/src/webenginequick/api/qquickwebengineprofile_p.h new file mode 100644 index 000000000..477936f98 --- /dev/null +++ b/src/webenginequick/api/qquickwebengineprofile_p.h @@ -0,0 +1,72 @@ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + +#ifndef QQUICKWEBENGINEPROFILE_P_H +#define QQUICKWEBENGINEPROFILE_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 "profile_adapter_client.h" +#include "qquickwebengineprofile.h" + +#include <QtCore/qmap.h> +#include <QtCore/qpointer.h> +#include <QtCore/qsharedpointer.h> + +namespace QtWebEngineCore { +class ProfileAdapter; +} + +QT_BEGIN_NAMESPACE + +class QWebEngineClientHints; +class QQuickWebEngineDownloadRequest; +class QQuickWebEngineSettings; +class QQuickWebEngineScriptCollection; + +class QQuickWebEngineProfilePrivate : public QtWebEngineCore::ProfileAdapterClient { +public: + Q_DECLARE_PUBLIC(QQuickWebEngineProfile) + QQuickWebEngineProfilePrivate(QtWebEngineCore::ProfileAdapter *profileAdapter); + ~QQuickWebEngineProfilePrivate(); + void addWebContentsAdapterClient(QtWebEngineCore::WebContentsAdapterClient *adapter) override; + void removeWebContentsAdapterClient(QtWebEngineCore::WebContentsAdapterClient *adapter) override; + + QtWebEngineCore::ProfileAdapter* profileAdapter() const; + QQuickWebEngineSettings *settings() const; + QtWebEngineCore::WebEngineSettings *coreSettings() const override; + + void cancelDownload(quint32 downloadId); + void downloadDestroyed(quint32 downloadId); + + void cleanDownloads(); + + void downloadRequested(DownloadItemInfo &info) override; + void downloadUpdated(const DownloadItemInfo &info) override; + + void showNotification(QSharedPointer<QtWebEngineCore::UserNotificationController> &controller) override; + void clearHttpCacheCompleted() override; + +private: + QQuickWebEngineProfile *q_ptr; + QScopedPointer<QQuickWebEngineSettings> m_settings; + QScopedPointer<QWebEngineClientHints> m_clientHints; + QPointer<QtWebEngineCore::ProfileAdapter> m_profileAdapter; + QMap<quint32, QPointer<QQuickWebEngineDownloadRequest> > m_ongoingDownloads; + + QScopedPointer<QQuickWebEngineScriptCollection> m_scriptCollection; + QQuickWebEngineScriptCollection *getUserScripts(); +}; + +QT_END_NAMESPACE + +#endif // QQUICKWEBENGINEPROFILE_P_H diff --git a/src/webenginequick/api/qquickwebenginescriptcollection.cpp b/src/webenginequick/api/qquickwebenginescriptcollection.cpp new file mode 100644 index 000000000..a58d97832 --- /dev/null +++ b/src/webenginequick/api/qquickwebenginescriptcollection.cpp @@ -0,0 +1,244 @@ +// Copyright (C) 2020 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + +#include "qquickwebenginescriptcollection_p.h" +#include "qquickwebenginescriptcollection_p_p.h" +#include "qwebenginescriptcollection.h" +#include <QtWebEngineCore/private/qwebenginescriptcollection_p.h> +#include <QtQml/qqmlinfo.h> +#include <QtQml/private/qqmlengine_p.h> +#include <QtQml/private/qv4scopedvalue_p.h> +#include <QtQml/private/qv4arrayobject_p.h> + +/*! + \qmltype WebEngineScriptCollection + \brief Manages a collection of user scripts. + \since QtWebEngine 6.2 + + \inqmlmodule QtWebEngine + + WebEngineScriptCollection handles a user scripts collection, which + is injected in the JavaScript engine during the loading of web content. + + Use \l{WebEngineView::userScripts}{WebEgineView.userScripts} and + \l{WebEngineProfile::userScripts}{WebEngineProfile.userScripts} to access + the collection of scripts associated with a single page or number of pages + sharing the same profile. + + The collection of user script objects in QML can be created for a set of + user script objects by simple assignment to + \l{WebEngineScriptCollection::collection}{WebEngineScriptCollection.collection} + property or by WebEngineScriptCollection methods. + + \note The new user script can be instantiated with JavaScript dictionaries when using + \e collection property. + + See the following code snippets demonstrating the usage: + + \list + \li \e collection property with JavaScript dictionaries + \code + var scriptFoo = { name: "Foo", + sourceUrl: Qt.resolvedUrl("foo.js"), + injectionPoint: WebEngineScript.DocumentReady } + + webEngineView.userScripts.collection = [ scriptFoo, scriptBar ]; + \endcode + \li \e collection property with user script object as value type + \code + var script = WebEngine.script() + script.name = "FOO" + webEngineView.userScripts.collection = [ script ] + \endcode + \li user script collection \e insert method can be used only with value type + or list of value types + \code + var script = WebEngine.script() + script.name = "FOO" + webEngineView.userScripts.insert(script) + + var list = [ script ] + webEngineView.userScripts.insert(list) + \endcode + \endlist + \sa WebEngineScript WebEngineScriptCollection + +*/ + +QWebEngineScript parseScript(const QJSValue &value, bool *ok) +{ + QWebEngineScript s; + if (ok) + *ok = false; + + if (value.isObject()) { + + if (value.hasProperty(QStringLiteral("name"))) + s.setName(value.property(QStringLiteral("name")).toString()); + + if (value.hasProperty(QStringLiteral("sourceUrl"))) + s.setSourceUrl(value.property(QStringLiteral("sourceUrl")).toString()); + + if (value.hasProperty(QStringLiteral("injectionPoint"))) + s.setInjectionPoint(QWebEngineScript::InjectionPoint( + value.property(QStringLiteral("injectionPoint")).toUInt())); + + if (value.hasProperty(QStringLiteral("sourceCode"))) + s.setSourceCode(value.property(QStringLiteral("sourceCode")).toString()); + + if (value.hasProperty(QStringLiteral("worldId"))) + s.setWorldId(QWebEngineScript::ScriptWorldId( + value.property(QStringLiteral("worldId")).toUInt())); + + if (value.hasProperty(QStringLiteral("runOnSubframes"))) + s.setRunsOnSubFrames(value.property(QStringLiteral("runOnSubframes")).toBool()); + + if (ok) + *ok = true; + } + return s; +} + +QQuickWebEngineScriptCollectionPrivate::QQuickWebEngineScriptCollectionPrivate(QWebEngineScriptCollectionPrivate *p) + : QWebEngineScriptCollection(p) +{ + +} + +QQuickWebEngineScriptCollectionPrivate::~QQuickWebEngineScriptCollectionPrivate() +{ +} + +QQuickWebEngineScriptCollection::QQuickWebEngineScriptCollection(QQuickWebEngineScriptCollectionPrivate *p) + : d(p) +{ +} + +QQuickWebEngineScriptCollection::~QQuickWebEngineScriptCollection() { } + +/*! + \qmlmethod void WebEngineScriptCollection::contains(WebEngineScript script) + \since QtWebEngine 6.2 + Checks if the specified \a script is in the collection. + \sa find() +*/ + +bool QQuickWebEngineScriptCollection::contains(const QWebEngineScript &value) const +{ + return d->contains(value); +} + +/*! + \qmlmethod list<WebEngineScript> WebEngineScriptCollection::find(string name) + \since QtWebEngine 6.2 + Returns a list of all user script objects with the given \a name. + \sa find() +*/ +QList<QWebEngineScript> QQuickWebEngineScriptCollection::find(const QString &name) const +{ + return d->find(name); +} + +/*! + \qmlmethod void WebEngineScriptCollection::insert(WebEngineScript script) + \since QtWebEngine 6.2 + Inserts a single \a script into the collection. + \sa find() +*/ +void QQuickWebEngineScriptCollection::insert(const QWebEngineScript &s) +{ + d->insert(s); +} + +/*! + \qmlmethod void WebEngineScriptCollection::insert(list<WebEngineScript> list) + \since QtWebEngine 6.2 + Inserts a \a list of WebEngineScript values into the user script collection. + \sa find() +*/ +void QQuickWebEngineScriptCollection::insert(const QList<QWebEngineScript> &list) +{ + d->insert(list); +} + +/*! + \qmlmethod bool WebEngineScriptCollection::remove(WebEngineScript script) + \since QtWebEngine 6.2 + Returns \c true if a given \a script is removed from the collection. + \sa insert() +*/ +bool QQuickWebEngineScriptCollection::remove(const QWebEngineScript &script) +{ + return d->remove(script); +} + +/*! + \qmlmethod void WebEngineScriptCollection::clear() + \since QtWebEngine 6.2 + Removes all script objects from this collection. +*/ +void QQuickWebEngineScriptCollection::clear() +{ + d->clear(); +} + +/*! + \qmlproperty list<WebEngineScript> WebEngineScriptCollection::collection + \since QtWebEngine 6.2 + + This property holds a JavaScript array of user script objects. The array can + take WebEngineScript basic type or a JavaScript dictionary as values. +*/ +QJSValue QQuickWebEngineScriptCollection::collection() const +{ + if (!d->m_qmlEngine) { + qmlWarning(this) << "Scripts collection doesn't have QML engine set! Undefined value is returned."; + return QJSValue(); + } + + const QList<QWebEngineScript> &list = d->toList(); + QV4::ExecutionEngine *v4 = QQmlEnginePrivate::getV4Engine(d->m_qmlEngine); + QV4::Scope scope(v4); + QV4::Scoped<QV4::ArrayObject> scriptArray(scope, v4->newArrayObject(list.size())); + int i = 0; + for (const auto &val : list) { + QV4::ScopedValue sv(scope, v4->fromVariant(QVariant::fromValue(val))); + scriptArray->put(i++, sv); + } + return QJSValuePrivate::fromReturnedValue(scriptArray.asReturnedValue()); +} + +void QQuickWebEngineScriptCollection::setCollection(const QJSValue &scripts) +{ + if (!scripts.isArray()) + return; + + QList<QWebEngineScript> scriptList; + quint32 length = scripts.property(QStringLiteral("length")).toUInt(); + for (quint32 i = 0; i < length; ++i) { + bool ok; + QWebEngineScript s = parseScript(scripts.property(i), &ok); + if (!ok) { + qmlWarning(this) << "Unsupported script type"; + return; + } + scriptList.append(s); + } + if (scriptList != d->toList()) { + clear(); + insert(scriptList); + Q_EMIT collectionChanged(); + } +} + +QQmlEngine* QQuickWebEngineScriptCollection::qmlEngine() +{ + return d->m_qmlEngine; +} + +void QQuickWebEngineScriptCollection::setQmlEngine(QQmlEngine *engine) +{ + Q_ASSERT(engine); + d->m_qmlEngine = engine; +} +#include "moc_qquickwebenginescriptcollection_p.cpp" diff --git a/src/webenginequick/api/qquickwebenginescriptcollection_p.h b/src/webenginequick/api/qquickwebenginescriptcollection_p.h new file mode 100644 index 000000000..fbcc8dde7 --- /dev/null +++ b/src/webenginequick/api/qquickwebenginescriptcollection_p.h @@ -0,0 +1,63 @@ +// Copyright (C) 2020 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + +#ifndef QQUICKWEBENGINESCRIPTCOLLECTION_H +#define QQUICKWEBENGINESCRIPTCOLLECTION_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 <QtCore/qlist.h> +#include <QtCore/qobject.h> +#include <QtCore/qscopedpointer.h> +#include <QtQml/qjsvalue.h> +#include <QtWebEngineCore/qwebenginescript.h> +#include <QtWebEngineQuick/private/qtwebenginequickglobal_p.h> + +QT_BEGIN_NAMESPACE +class QQmlEngine; +class QQuickWebEngineScriptCollectionPrivate; + +class Q_WEBENGINEQUICK_EXPORT QQuickWebEngineScriptCollection : public QObject +{ + Q_OBJECT +public: + Q_PROPERTY(QJSValue collection READ collection WRITE setCollection NOTIFY collectionChanged) + ~QQuickWebEngineScriptCollection(); + + Q_INVOKABLE bool contains(const QWebEngineScript &value) const; + Q_INVOKABLE QList<QWebEngineScript> find(const QString &name) const; + Q_INVOKABLE void insert(const QWebEngineScript &); + Q_INVOKABLE void insert(const QList<QWebEngineScript> &list); + Q_INVOKABLE bool remove(const QWebEngineScript &); + Q_INVOKABLE void clear(); + + QJSValue collection() const; + void setCollection(const QJSValue &scripts); + +Q_SIGNALS: + void collectionChanged(); + +private: + Q_DISABLE_COPY(QQuickWebEngineScriptCollection) + QQuickWebEngineScriptCollection(QQuickWebEngineScriptCollectionPrivate *d); + QScopedPointer<QQuickWebEngineScriptCollectionPrivate> d; + friend class QQuickWebEngineProfilePrivate; + friend class QQuickWebEngineViewPrivate; + QQmlEngine* qmlEngine(); + void setQmlEngine(QQmlEngine *engine); +}; + +QT_END_NAMESPACE + +Q_DECLARE_METATYPE(QQuickWebEngineScriptCollection *) + +#endif // QWEBENGINESCRIPTCOLLECTION_H diff --git a/src/webenginequick/api/qquickwebenginescriptcollection_p_p.h b/src/webenginequick/api/qquickwebenginescriptcollection_p_p.h new file mode 100644 index 000000000..54a9bc16d --- /dev/null +++ b/src/webenginequick/api/qquickwebenginescriptcollection_p_p.h @@ -0,0 +1,38 @@ +// Copyright (C) 2022 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + +#ifndef QQUICKWEBENGINESCRIPTCOLLECTIONPRIVATE_H +#define QQUICKWEBENGINESCRIPTCOLLECTIONPRIVATE_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 <QtWebEngineCore/qwebenginescriptcollection.h> + +#include <QPointer> + +QT_BEGIN_NAMESPACE + +class QQmlEngine; + +class QQuickWebEngineScriptCollectionPrivate : public QWebEngineScriptCollection +{ +public: + QQuickWebEngineScriptCollectionPrivate(QWebEngineScriptCollectionPrivate *d); + ~QQuickWebEngineScriptCollectionPrivate(); + + Q_DISABLE_COPY(QQuickWebEngineScriptCollectionPrivate) + QPointer<QQmlEngine> m_qmlEngine; +}; + +QT_END_NAMESPACE + +#endif diff --git a/src/webenginequick/api/qquickwebenginesettings.cpp b/src/webenginequick/api/qquickwebenginesettings.cpp new file mode 100644 index 000000000..31ed7a661 --- /dev/null +++ b/src/webenginequick/api/qquickwebenginesettings.cpp @@ -0,0 +1,854 @@ +// Copyright (C) 2022 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + +#include "qquickwebengineprofile.h" +#include "qquickwebenginesettings_p.h" + +#include "web_engine_settings.h" + +QT_BEGIN_NAMESPACE + +QQuickWebEngineSettings::QQuickWebEngineSettings(QQuickWebEngineSettings *parentSettings) + : d_ptr(new QWebEngineSettings(parentSettings ? parentSettings->d_ptr.data() : nullptr)) +{ } + +/*! + \qmltype WebEngineSettings + //! \instantiates QQuickWebEngineSettings + \inqmlmodule QtWebEngine + \since QtWebEngine 1.1 + \brief Allows configuration of browser properties and attributes. + + The WebEngineSettings type can be used to configure browser properties and generic + attributes, such as JavaScript support, focus behavior, and access to remote content. This type + is uncreatable, but the default settings for all web engine views can be accessed by using + the \l [QML] {WebEngine::settings}{WebEngine.settings} property. + + Each web engine view can have individual settings that can be accessed by using the + \l{WebEngineView::settings}{WebEngineView.settings} property. +*/ + + +QQuickWebEngineSettings::~QQuickWebEngineSettings() +{ } + +/*! + \qmlproperty bool WebEngineSettings::autoLoadImages + + Automatically loads images on web pages. + + Enabled by default. +*/ +bool QQuickWebEngineSettings::autoLoadImages() const +{ + return d_ptr->testAttribute(QWebEngineSettings::AutoLoadImages); +} + +/*! + \qmlproperty bool WebEngineSettings::javascriptEnabled + + Enables the running of JavaScript programs. + + Enabled by default. +*/ +bool QQuickWebEngineSettings::javascriptEnabled() const +{ + return d_ptr->testAttribute(QWebEngineSettings::JavascriptEnabled); +} + +/*! + \qmlproperty bool WebEngineSettings::javascriptCanOpenWindows + + Allows JavaScript programs to open popup windows without user interaction. + + Enabled by default. +*/ +bool QQuickWebEngineSettings::javascriptCanOpenWindows() const +{ + return d_ptr->testAttribute(QWebEngineSettings::JavascriptCanOpenWindows); +} + +/*! + \qmlproperty bool WebEngineSettings::javascriptCanAccessClipboard + + Allows JavaScript programs to read from or write to the clipboard. + Writing to the clipboard is always allowed if it is specifically requested by the user. + + To enable also the pasting of clipboard content from JavaScript, + use javascriptCanPaste. + + Since unrestricted clipboard access is a potential security concern, it is + recommended that applications leave this disabled and instead respond to + \l{WebEngineView::ClipboardReadWrite}{ClipboardReadWrite} feature permission requests. + + Disabled by default. +*/ +bool QQuickWebEngineSettings::javascriptCanAccessClipboard() const +{ + return d_ptr->testAttribute(QWebEngineSettings::JavascriptCanAccessClipboard); +} + +/*! + \qmlproperty bool WebEngineSettings::linksIncludedInFocusChain + + Includes hyperlinks in the keyboard focus chain. + + Enabled by default. +*/ +bool QQuickWebEngineSettings::linksIncludedInFocusChain() const +{ + return d_ptr->testAttribute(QWebEngineSettings::LinksIncludedInFocusChain); +} + +/*! + \qmlproperty bool WebEngineSettings::localStorageEnabled + + Enables support for the HTML 5 local storage feature. + + Enabled by default. +*/ +bool QQuickWebEngineSettings::localStorageEnabled() const +{ + return d_ptr->testAttribute(QWebEngineSettings::LocalStorageEnabled); +} + +/*! + \qmlproperty bool WebEngineSettings::localContentCanAccessRemoteUrls + + Allows locally loaded documents to access remote URLs. + + Disabled by default. +*/ +bool QQuickWebEngineSettings::localContentCanAccessRemoteUrls() const +{ + return d_ptr->testAttribute(QWebEngineSettings::LocalContentCanAccessRemoteUrls); +} + +/*! + \qmlproperty bool WebEngineSettings::spatialNavigationEnabled + + Enables the Spatial Navigation feature, which means the ability to navigate between focusable + elements, such as hyperlinks and form controls, on a web page by using the Left, Right, Up and + Down arrow keys. + + For example, if a user presses the Right key, heuristics determine whether there is an element + they might be trying to reach towards the right and which element they probably want. + + Disabled by default. + +*/ +bool QQuickWebEngineSettings::spatialNavigationEnabled() const +{ + return d_ptr->testAttribute(QWebEngineSettings::SpatialNavigationEnabled); +} + +/*! + \qmlproperty bool WebEngineSettings::localContentCanAccessFileUrls + + Allows locally loaded documents to access other local URLs. + + Enabled by default. +*/ +bool QQuickWebEngineSettings::localContentCanAccessFileUrls() const +{ + return d_ptr->testAttribute(QWebEngineSettings::LocalContentCanAccessFileUrls); +} + +/*! + \qmlproperty bool WebEngineSettings::hyperlinkAuditingEnabled + + Enables support for the \c ping attribute for hyperlinks. + + Disabled by default. +*/ +bool QQuickWebEngineSettings::hyperlinkAuditingEnabled() const +{ + return d_ptr->testAttribute(QWebEngineSettings::HyperlinkAuditingEnabled); +} + +/*! + \qmlproperty bool WebEngineSettings::errorPageEnabled + + Enables displaying the built-in error pages of Chromium. + + Enabled by default. +*/ +bool QQuickWebEngineSettings::errorPageEnabled() const +{ + return d_ptr->testAttribute(QWebEngineSettings::ErrorPageEnabled); +} + +/*! + \qmlproperty bool WebEngineSettings::pluginsEnabled + + Enables support for Pepper plugins, such as the Flash player. + + Disabled by default. + + \sa {Pepper Plugin API} +*/ +bool QQuickWebEngineSettings::pluginsEnabled() const +{ + return d_ptr->testAttribute(QWebEngineSettings::PluginsEnabled); +} + +/*! + \qmlproperty bool WebEngineSettings::fullscreenSupportEnabled + \since QtWebEngine 1.2 + + Tells the web engine whether fullscreen is supported in this application or not. + + Disabled by default. +*/ +bool QQuickWebEngineSettings::fullScreenSupportEnabled() const +{ + return d_ptr->testAttribute(QWebEngineSettings::FullScreenSupportEnabled); +} + +/*! + \qmlproperty bool WebEngineSettings::screenCaptureEnabled + \since QtWebEngine 1.3 + + Tells the web engine whether screen capture is supported in this application or not. + + Disabled by default. +*/ +bool QQuickWebEngineSettings::screenCaptureEnabled() const +{ + return d_ptr->testAttribute(QWebEngineSettings::ScreenCaptureEnabled); +} + +/*! + \qmlproperty bool WebEngineSettings::webGLEnabled + \since QtWebEngine 1.3 + + Enables support for HTML 5 WebGL. + + Enabled by default if available. +*/ +bool QQuickWebEngineSettings::webGLEnabled() const +{ + return d_ptr->testAttribute(QWebEngineSettings::WebGLEnabled); +} + +/*! + \qmlproperty bool WebEngineSettings::accelerated2dCanvasEnabled + \since QtWebEngine 1.3 + + Specifies whether the HTML 5 2D canvas should be an OpenGL framebuffer. + This makes many painting operations faster, but slows down pixel access. + + Enabled by default if available. +*/ +bool QQuickWebEngineSettings::accelerated2dCanvasEnabled() const +{ + return d_ptr->testAttribute(QWebEngineSettings::Accelerated2dCanvasEnabled); +} + +/*! + \qmlproperty bool WebEngineSettings::autoLoadIconsForPage + \since QtWebEngine 1.3 + + Automatically downloads icons for web pages. + + Enabled by default. +*/ +bool QQuickWebEngineSettings::autoLoadIconsForPage() const +{ + return d_ptr->testAttribute(QWebEngineSettings::AutoLoadIconsForPage); +} + +/*! + \qmlproperty bool WebEngineSettings::touchIconsEnabled + \since QtWebEngine 1.3 + + Enables support for touch icons and precomposed touch icons. + + Disabled by default. +*/ +bool QQuickWebEngineSettings::touchIconsEnabled() const +{ + return d_ptr->testAttribute(QWebEngineSettings::TouchIconsEnabled); +} + +/*! + \qmlproperty bool WebEngineSettings::focusOnNavigationEnabled + \since QtWebEngine 1.4 + + Focus is given to the view whenever a navigation operation occurs + (load, stop, reload, reload and bypass cache, forward, backward, set content, and so on). + + Disabled by default. +*/ +bool QQuickWebEngineSettings::focusOnNavigationEnabled() const +{ + return d_ptr->testAttribute(QWebEngineSettings::FocusOnNavigationEnabled); +} + +/*! + \qmlproperty bool WebEngineSettings::printElementBackgrounds + \since QtWebEngine 1.4 + + Turns on printing of CSS backgrounds when printing a web page. + + Enabled by default. +*/ +bool QQuickWebEngineSettings::printElementBackgrounds() const +{ + return d_ptr->testAttribute(QWebEngineSettings::PrintElementBackgrounds); +} + +/*! + \qmlproperty bool WebEngineSettings::allowRunningInsecureContent + \since QtWebEngine 1.4 + + By default, HTTPS pages cannot run JavaScript, CSS, plugins or + web-sockets from HTTP URLs. This used to be possible and this + provides an override to get the old behavior. + + Disabled by default. +*/ +bool QQuickWebEngineSettings::allowRunningInsecureContent() const +{ + return d_ptr->testAttribute(QWebEngineSettings::AllowRunningInsecureContent); +} + +/*! + \qmlproperty bool WebEngineSettings::allowGeolocationOnInsecureOrigins + \since QtWebEngine 1.5 + + Since Qt 5.7, only secure origins such as HTTPS have been able to request + Geolocation features. This provides an override to allow non secure + origins to access Geolocation again. + + Disabled by default. +*/ +bool QQuickWebEngineSettings::allowGeolocationOnInsecureOrigins() const +{ + return d_ptr->testAttribute(QWebEngineSettings::AllowGeolocationOnInsecureOrigins); +} + +/*! + \qmlproperty bool WebEngineSettings::allowWindowActivationFromJavaScript + \since QtWebEngine 1.6 + Allows the window.focus() method in JavaScript. Disallowed by default. +*/ +bool QQuickWebEngineSettings::allowWindowActivationFromJavaScript() const +{ + return d_ptr->testAttribute(QWebEngineSettings::AllowWindowActivationFromJavaScript); +} + +/*! + \qmlproperty bool WebEngineSettings::showScrollBars + \since QtWebEngine 1.6 + Shows scroll bars. Enabled by default. +*/ +bool QQuickWebEngineSettings::showScrollBars() const +{ + return d_ptr->testAttribute(QWebEngineSettings::ShowScrollBars); +} + +/*! + \qmlproperty bool WebEngineSettings::playbackRequiresUserGesture + \since QtWebEngine 1.7 + Inhibits playback of media content until the user interacts with + the page. + + By default, Qt WebEngine uses Chromium settings, as described in + \l {Autoplay Policy Changes}. To overwrite the default behavior, + this property must be set to \c false. + + \note The behavior is similar to Chrome on Android when enabled, + and similar to Chrome on desktops when disabled. +*/ +bool QQuickWebEngineSettings::playbackRequiresUserGesture() const +{ + return d_ptr->testAttribute(QWebEngineSettings::PlaybackRequiresUserGesture); +} + +/*! + \qmlproperty bool WebEngineSettings::webRTCPublicInterfacesOnly + \since QtWebEngine 1.7 + Limits WebRTC to public IP addresses only. When disabled WebRTC may also use + local network IP addresses, but remote hosts can also see your local network + IP address. + + Disabled by default. +*/ +bool QQuickWebEngineSettings::webRTCPublicInterfacesOnly() const +{ + return d_ptr->testAttribute(QWebEngineSettings::WebRTCPublicInterfacesOnly); +} + +/*! + \qmlproperty bool WebEngineSettings::javascriptCanPaste + \since QtWebEngine 1.7 + + Enables JavaScript \c{execCommand("paste")}. + This also requires enabling javascriptCanAccessClipboard. + + Since unrestricted clipboard access is a potential security concern, it is + recommended that applications leave this disabled and instead respond to + \l{WebEngineView::ClipboardReadWrite}{ClipboardReadWrite} feature permission requests. + + Disabled by default. +*/ +bool QQuickWebEngineSettings::javascriptCanPaste() const +{ + return d_ptr->testAttribute(QWebEngineSettings::JavascriptCanPaste); +} + +/*! + \qmlproperty bool WebEngineSettings::dnsPrefetchEnabled + \since QtWebEngine 1.8 + + Enables speculative prefetching of DNS records for HTML links before + they are activated. + + Disabled by default. +*/ +bool QQuickWebEngineSettings::dnsPrefetchEnabled() const +{ + return d_ptr->testAttribute(QWebEngineSettings::DnsPrefetchEnabled); +} + +/*! + \qmlproperty bool WebEngineSettings::pdfViewerEnabled + \since QtWebEngine 1.9 + + Specifies that PDF documents will be opened in the internal PDF viewer + instead of being downloaded. + + Enabled by default. +*/ +bool QQuickWebEngineSettings::pdfViewerEnabled() const +{ + return d_ptr->testAttribute(QWebEngineSettings::PdfViewerEnabled); +} + +/*! + \qmlproperty bool WebEngineSettings::navigateOnDropEnabled + \since QtWebEngine 6.4 + + Specifies that navigations can be triggered by dropping URLs on + the view. + + Enabled by default. +*/ +bool QQuickWebEngineSettings::navigateOnDropEnabled() const +{ + return d_ptr->testAttribute(QWebEngineSettings::NavigateOnDropEnabled); +} + +/*! + \qmlproperty bool WebEngineSettings::readingFromCanvasEnabled + \since QtWebEngine 6.6 + + Specifies that reading from all canvas elements is enabled. + + This setting will have impact on all HTML5 canvas elements irrespective of origin, and can be disabled + to prevent canvas fingerprinting. + + Enabled by default. + */ +bool QQuickWebEngineSettings::readingFromCanvasEnabled() const +{ + return d_ptr->testAttribute(QWebEngineSettings::ReadingFromCanvasEnabled); +} + +/*! + \qmlproperty bool WebEngineSettings::forceDarkMode + \since QtWebEngine 6.7 + + Automatically render all web contents using a dark theme. + + Disabled by default. + */ +bool QQuickWebEngineSettings::forceDarkMode() const +{ + return d_ptr->testAttribute(QWebEngineSettings::ForceDarkMode); +} + +/*! + \qmlproperty bool WebEngineSettings::scrollAnimatorEnabled + \since QtWebEngine 6.8 + + Enables animated scrolling. + + Disabled by default. + */ +bool QQuickWebEngineSettings::scrollAnimatorEnabled() const +{ + return d_ptr->testAttribute(QWebEngineSettings::ScrollAnimatorEnabled); +} + +/*! + \qmlproperty string WebEngineSettings::defaultTextEncoding + \since QtWebEngine 1.2 + + Sets the default encoding. The value must be a string describing an encoding such as "utf-8" or + "iso-8859-1". + + If left empty, a default value will be used. +*/ +QString QQuickWebEngineSettings::defaultTextEncoding() const +{ + return d_ptr->defaultTextEncoding(); +} + +ASSERT_ENUMS_MATCH(QQuickWebEngineSettings::AllowImageAnimation, + QWebEngineSettings::AllowImageAnimation) +ASSERT_ENUMS_MATCH(QQuickWebEngineSettings::AnimateImageOnce, QWebEngineSettings::AnimateImageOnce) +ASSERT_ENUMS_MATCH(QQuickWebEngineSettings::DisallowImageAnimation, + QWebEngineSettings::DisallowImageAnimation) +/*! + \qmlproperty enumeration WebEngineSettings::imageAnimationPolicy + \since QtWebEngine 6.8 + + Specifies how an image animation should be handled when the image frames + are rendered for animation. + + \value WebEngineSettings.AllowImageAnimation + Allows all image animations when the image frames are rendered. + \value WebEngineSettings.AnimateImageOnce + Animate the image once when the image frames are rendered. + \value WebEngineSettings.DisallowImageAnimation + Disallows all image animations when the image frames are rendered. + + Default value is \c {WebEngineSettings.AllowImageAnimation}. +*/ +QQuickWebEngineSettings::ImageAnimationPolicy QQuickWebEngineSettings::imageAnimationPolicy() const +{ + return static_cast<QQuickWebEngineSettings::ImageAnimationPolicy>( + d_ptr->imageAnimationPolicy()); +} + +ASSERT_ENUMS_MATCH(QQuickWebEngineSettings::DisallowUnknownUrlSchemes, QWebEngineSettings::DisallowUnknownUrlSchemes) +ASSERT_ENUMS_MATCH(QQuickWebEngineSettings::AllowUnknownUrlSchemesFromUserInteraction, QWebEngineSettings::AllowUnknownUrlSchemesFromUserInteraction) +ASSERT_ENUMS_MATCH(QQuickWebEngineSettings::AllowAllUnknownUrlSchemes, QWebEngineSettings::AllowAllUnknownUrlSchemes) + +/*! + \qmlproperty enumeration WebEngineSettings::unknownUrlSchemePolicy + \since QtWebEngine 1.7 + Specifies how navigation requests to URLs with unknown schemes are handled. + + \value WebEngineSettings.DisallowUnknownUrlSchemes + Disallows all navigation requests to URLs with unknown schemes. + \value WebEngineSettings.AllowUnknownUrlSchemesFromUserInteraction + Allows navigation requests to URLs with unknown schemes that are issued from + user-interaction (like a mouse-click), whereas other navigation requests (for example + from JavaScript) are suppressed. + \value WebEngineSettings.AllowAllUnknownUrlSchemes + Allows all navigation requests to URLs with unknown schemes. + + Default value is \c {WebEngineSettings.AllowUnknownUrlSchemesFromUserInteraction}. +*/ +QQuickWebEngineSettings::UnknownUrlSchemePolicy QQuickWebEngineSettings::unknownUrlSchemePolicy() const +{ + return static_cast<QQuickWebEngineSettings::UnknownUrlSchemePolicy>(d_ptr->unknownUrlSchemePolicy()); +} + +void QQuickWebEngineSettings::setAutoLoadImages(bool on) +{ + bool wasOn = d_ptr->testAttribute(QWebEngineSettings::AutoLoadImages); + // Set unconditionally as it sets the override for the current settings while the current setting + // could be from the fallback and is prone to changing later on. + d_ptr->setAttribute(QWebEngineSettings::AutoLoadImages, on); + if (wasOn != on) + Q_EMIT autoLoadImagesChanged(); +} + +void QQuickWebEngineSettings::setJavascriptEnabled(bool on) +{ + bool wasOn = d_ptr->testAttribute(QWebEngineSettings::JavascriptEnabled); + d_ptr->setAttribute(QWebEngineSettings::JavascriptEnabled, on); + if (wasOn != on) + Q_EMIT javascriptEnabledChanged(); +} + +void QQuickWebEngineSettings::setJavascriptCanOpenWindows(bool on) +{ + bool wasOn = d_ptr->testAttribute(QWebEngineSettings::JavascriptCanOpenWindows); + d_ptr->setAttribute(QWebEngineSettings::JavascriptCanOpenWindows, on); + if (wasOn != on) + Q_EMIT javascriptCanOpenWindowsChanged(); +} + +void QQuickWebEngineSettings::setJavascriptCanAccessClipboard(bool on) +{ + bool wasOn = d_ptr->testAttribute(QWebEngineSettings::JavascriptCanAccessClipboard); + d_ptr->setAttribute(QWebEngineSettings::JavascriptCanAccessClipboard, on); + if (wasOn != on) + Q_EMIT javascriptCanAccessClipboardChanged(); +} + +void QQuickWebEngineSettings::setLinksIncludedInFocusChain(bool on) +{ + bool wasOn = d_ptr->testAttribute(QWebEngineSettings::LinksIncludedInFocusChain); + d_ptr->setAttribute(QWebEngineSettings::LinksIncludedInFocusChain, on); + if (wasOn != on) + Q_EMIT linksIncludedInFocusChainChanged(); +} + +void QQuickWebEngineSettings::setLocalStorageEnabled(bool on) +{ + bool wasOn = d_ptr->testAttribute(QWebEngineSettings::LocalStorageEnabled); + d_ptr->setAttribute(QWebEngineSettings::LocalStorageEnabled, on); + if (wasOn != on) + Q_EMIT localStorageEnabledChanged(); +} + +void QQuickWebEngineSettings::setLocalContentCanAccessRemoteUrls(bool on) +{ + bool wasOn = d_ptr->testAttribute(QWebEngineSettings::LocalContentCanAccessRemoteUrls); + d_ptr->setAttribute(QWebEngineSettings::LocalContentCanAccessRemoteUrls, on); + if (wasOn != on) + Q_EMIT localContentCanAccessRemoteUrlsChanged(); +} + + +void QQuickWebEngineSettings::setSpatialNavigationEnabled(bool on) +{ + bool wasOn = d_ptr->testAttribute(QWebEngineSettings::SpatialNavigationEnabled); + d_ptr->setAttribute(QWebEngineSettings::SpatialNavigationEnabled, on); + if (wasOn != on) + Q_EMIT spatialNavigationEnabledChanged(); +} + +void QQuickWebEngineSettings::setLocalContentCanAccessFileUrls(bool on) +{ + bool wasOn = d_ptr->testAttribute(QWebEngineSettings::LocalContentCanAccessFileUrls); + d_ptr->setAttribute(QWebEngineSettings::LocalContentCanAccessFileUrls, on); + if (wasOn != on) + Q_EMIT localContentCanAccessFileUrlsChanged(); +} + +void QQuickWebEngineSettings::setHyperlinkAuditingEnabled(bool on) +{ + bool wasOn = d_ptr->testAttribute(QWebEngineSettings::HyperlinkAuditingEnabled); + d_ptr->setAttribute(QWebEngineSettings::HyperlinkAuditingEnabled, on); + if (wasOn != on) + Q_EMIT hyperlinkAuditingEnabledChanged(); +} + +void QQuickWebEngineSettings::setErrorPageEnabled(bool on) +{ + bool wasOn = d_ptr->testAttribute(QWebEngineSettings::ErrorPageEnabled); + d_ptr->setAttribute(QWebEngineSettings::ErrorPageEnabled, on); + if (wasOn != on) + Q_EMIT errorPageEnabledChanged(); +} + +void QQuickWebEngineSettings::setPluginsEnabled(bool on) +{ + bool wasOn = d_ptr->testAttribute(QWebEngineSettings::PluginsEnabled); + d_ptr->setAttribute(QWebEngineSettings::PluginsEnabled, on); + if (wasOn != on) + Q_EMIT pluginsEnabledChanged(); +} + +void QQuickWebEngineSettings::setFullScreenSupportEnabled(bool on) +{ + bool wasOn = d_ptr->testAttribute(QWebEngineSettings::FullScreenSupportEnabled); + d_ptr->setAttribute(QWebEngineSettings::FullScreenSupportEnabled, on); + if (wasOn != on) + Q_EMIT fullScreenSupportEnabledChanged(); +} + +void QQuickWebEngineSettings::setScreenCaptureEnabled(bool on) +{ + bool wasOn = d_ptr->testAttribute(QWebEngineSettings::ScreenCaptureEnabled); + d_ptr->setAttribute(QWebEngineSettings::ScreenCaptureEnabled, on); + if (wasOn != on) + Q_EMIT screenCaptureEnabledChanged(); +} + +void QQuickWebEngineSettings::setWebGLEnabled(bool on) +{ + bool wasOn = d_ptr->testAttribute(QWebEngineSettings::WebGLEnabled); + d_ptr->setAttribute(QWebEngineSettings::WebGLEnabled, on); + if (wasOn != on) + Q_EMIT webGLEnabledChanged(); +} + +void QQuickWebEngineSettings::setAccelerated2dCanvasEnabled(bool on) +{ + bool wasOn = d_ptr->testAttribute(QWebEngineSettings::Accelerated2dCanvasEnabled); + d_ptr->setAttribute(QWebEngineSettings::Accelerated2dCanvasEnabled, on); + if (wasOn != on) + Q_EMIT accelerated2dCanvasEnabledChanged(); +} + +void QQuickWebEngineSettings::setAutoLoadIconsForPage(bool on) +{ + bool wasOn = d_ptr->testAttribute(QWebEngineSettings::AutoLoadIconsForPage); + d_ptr->setAttribute(QWebEngineSettings::AutoLoadIconsForPage, on); + if (wasOn != on) + Q_EMIT autoLoadIconsForPageChanged(); +} + +void QQuickWebEngineSettings::setTouchIconsEnabled(bool on) +{ + bool wasOn = d_ptr->testAttribute(QWebEngineSettings::TouchIconsEnabled); + d_ptr->setAttribute(QWebEngineSettings::TouchIconsEnabled, on); + if (wasOn != on) + Q_EMIT touchIconsEnabledChanged(); +} + +void QQuickWebEngineSettings::setPrintElementBackgrounds(bool on) +{ + bool wasOn = d_ptr->testAttribute(QWebEngineSettings::PrintElementBackgrounds); + d_ptr->setAttribute(QWebEngineSettings::PrintElementBackgrounds, on); + if (wasOn != on) + Q_EMIT printElementBackgroundsChanged(); +} + +void QQuickWebEngineSettings::setDefaultTextEncoding(QString encoding) +{ + const QString oldDefaultTextEncoding = d_ptr->defaultTextEncoding(); + d_ptr->setDefaultTextEncoding(encoding); + if (oldDefaultTextEncoding.compare(encoding)) + Q_EMIT defaultTextEncodingChanged(); +} + +void QQuickWebEngineSettings::setFocusOnNavigationEnabled(bool on) +{ + bool wasOn = d_ptr->testAttribute(QWebEngineSettings::FocusOnNavigationEnabled); + d_ptr->setAttribute(QWebEngineSettings::FocusOnNavigationEnabled, on); + if (wasOn != on) + Q_EMIT focusOnNavigationEnabledChanged(); +} + + +void QQuickWebEngineSettings::setAllowRunningInsecureContent(bool on) +{ + bool wasOn = d_ptr->testAttribute(QWebEngineSettings::AllowRunningInsecureContent); + d_ptr->setAttribute(QWebEngineSettings::AllowRunningInsecureContent, on); + if (wasOn != on) + Q_EMIT allowRunningInsecureContentChanged(); +} + +void QQuickWebEngineSettings::setAllowGeolocationOnInsecureOrigins(bool on) +{ + bool wasOn = d_ptr->testAttribute(QWebEngineSettings::AllowGeolocationOnInsecureOrigins); + d_ptr->setAttribute(QWebEngineSettings::AllowGeolocationOnInsecureOrigins, on); + if (wasOn != on) + Q_EMIT allowGeolocationOnInsecureOriginsChanged(); +} + +void QQuickWebEngineSettings::setAllowWindowActivationFromJavaScript(bool on) +{ + bool wasOn = d_ptr->testAttribute(QWebEngineSettings::AllowWindowActivationFromJavaScript); + d_ptr->setAttribute(QWebEngineSettings::AllowWindowActivationFromJavaScript, on); + if (wasOn != on) + Q_EMIT allowWindowActivationFromJavaScriptChanged(); +} + +void QQuickWebEngineSettings::setShowScrollBars(bool on) +{ + bool wasOn = d_ptr->testAttribute(QWebEngineSettings::ShowScrollBars); + d_ptr->setAttribute(QWebEngineSettings::ShowScrollBars, on); + if (wasOn != on) + Q_EMIT showScrollBarsChanged(); +} + +void QQuickWebEngineSettings::setPlaybackRequiresUserGesture(bool on) +{ + bool wasOn = d_ptr->testAttribute(QWebEngineSettings::PlaybackRequiresUserGesture); + d_ptr->setAttribute(QWebEngineSettings::PlaybackRequiresUserGesture, on); + if (wasOn != on) + Q_EMIT playbackRequiresUserGestureChanged(); +} + +void QQuickWebEngineSettings::setJavascriptCanPaste(bool on) +{ + bool wasOn = d_ptr->testAttribute(QWebEngineSettings::JavascriptCanPaste); + d_ptr->setAttribute(QWebEngineSettings::JavascriptCanPaste, on); + if (wasOn != on) + Q_EMIT javascriptCanPasteChanged(); +} + +void QQuickWebEngineSettings::setDnsPrefetchEnabled(bool on) +{ + bool wasOn = d_ptr->testAttribute(QWebEngineSettings::DnsPrefetchEnabled); + d_ptr->setAttribute(QWebEngineSettings::DnsPrefetchEnabled, on); + if (wasOn != on) + Q_EMIT dnsPrefetchEnabledChanged(); +} + +void QQuickWebEngineSettings::setPdfViewerEnabled(bool on) +{ + bool wasOn = d_ptr->testAttribute(QWebEngineSettings::PdfViewerEnabled); + d_ptr->setAttribute(QWebEngineSettings::PdfViewerEnabled, on); + if (wasOn != on) + Q_EMIT pdfViewerEnabledChanged(); +} + +void QQuickWebEngineSettings::setNavigateOnDropEnabled(bool on) +{ + bool wasOn = d_ptr->testAttribute(QWebEngineSettings::NavigateOnDropEnabled); + d_ptr->setAttribute(QWebEngineSettings::NavigateOnDropEnabled, on); + if (wasOn != on) + Q_EMIT navigateOnDropEnabledChanged(); +} + +void QQuickWebEngineSettings::setReadingFromCanvasEnabled(bool on) +{ + bool wasOn = d_ptr->testAttribute(QWebEngineSettings::ReadingFromCanvasEnabled); + d_ptr->setAttribute(QWebEngineSettings::ReadingFromCanvasEnabled, on); + if (wasOn != on) + Q_EMIT readingFromCanvasEnabledChanged(); +} + +void QQuickWebEngineSettings::setForceDarkMode(bool on) +{ + bool wasOn = d_ptr->testAttribute(QWebEngineSettings::ForceDarkMode); + d_ptr->setAttribute(QWebEngineSettings::ForceDarkMode, on); + if (wasOn != on) + Q_EMIT forceDarkModeChanged(); +} + +void QQuickWebEngineSettings::setScrollAnimatorEnabled(bool on) +{ + bool wasOn = d_ptr->testAttribute(QWebEngineSettings::ScrollAnimatorEnabled); + d_ptr->setAttribute(QWebEngineSettings::ScrollAnimatorEnabled, on); + if (wasOn != on) + Q_EMIT scrollAnimatorEnabledChanged(); +} + +void QQuickWebEngineSettings::setUnknownUrlSchemePolicy(QQuickWebEngineSettings::UnknownUrlSchemePolicy policy) +{ + QWebEngineSettings::UnknownUrlSchemePolicy oldPolicy = d_ptr->unknownUrlSchemePolicy(); + QWebEngineSettings::UnknownUrlSchemePolicy newPolicy = static_cast<QWebEngineSettings::UnknownUrlSchemePolicy>(policy); + d_ptr->setUnknownUrlSchemePolicy(newPolicy); + if (oldPolicy != newPolicy) + Q_EMIT unknownUrlSchemePolicyChanged(); +} + +void QQuickWebEngineSettings::setWebRTCPublicInterfacesOnly(bool on) +{ + bool wasOn = d_ptr->testAttribute(QWebEngineSettings::WebRTCPublicInterfacesOnly); + d_ptr->setAttribute(QWebEngineSettings::WebRTCPublicInterfacesOnly, on); + if (wasOn != on) + Q_EMIT webRTCPublicInterfacesOnlyChanged(); +} + +void QQuickWebEngineSettings::setParentSettings(QQuickWebEngineSettings *parentSettings) +{ + d_ptr->setParentSettings(parentSettings->d_ptr.data()); +} + +void QQuickWebEngineSettings::setImageAnimationPolicy( + QQuickWebEngineSettings::ImageAnimationPolicy policy) +{ + QWebEngineSettings::ImageAnimationPolicy oldPolicy = d_ptr->imageAnimationPolicy(); + QWebEngineSettings::ImageAnimationPolicy newPolicy = + static_cast<QWebEngineSettings::ImageAnimationPolicy>(policy); + d_ptr->setImageAnimationPolicy(newPolicy); + if (oldPolicy != newPolicy) + Q_EMIT imageAnimationPolicyChanged(); +} + +QT_END_NAMESPACE + +#include "moc_qquickwebenginesettings_p.cpp" diff --git a/src/webenginequick/api/qquickwebenginesettings_p.h b/src/webenginequick/api/qquickwebenginesettings_p.h new file mode 100644 index 000000000..ed3c77884 --- /dev/null +++ b/src/webenginequick/api/qquickwebenginesettings_p.h @@ -0,0 +1,212 @@ +// Copyright (C) 2022 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + +#ifndef QQUICKWEBENGINESETTINGS_P_H +#define QQUICKWEBENGINESETTINGS_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 <QtCore/qobject.h> +#include <QtCore/qscopedpointer.h> +#include <QtQml/qqmlregistration.h> +#include <QtWebEngineQuick/private/qtwebenginequickglobal_p.h> + +QT_BEGIN_NAMESPACE + +class QWebEngineSettings; +class Q_WEBENGINEQUICK_EXPORT QQuickWebEngineSettings : public QObject { + Q_OBJECT + Q_PROPERTY(bool autoLoadImages READ autoLoadImages WRITE setAutoLoadImages NOTIFY autoLoadImagesChanged FINAL) + Q_PROPERTY(bool javascriptEnabled READ javascriptEnabled WRITE setJavascriptEnabled NOTIFY javascriptEnabledChanged FINAL) + Q_PROPERTY(bool javascriptCanOpenWindows READ javascriptCanOpenWindows WRITE setJavascriptCanOpenWindows NOTIFY javascriptCanOpenWindowsChanged FINAL) + Q_PROPERTY(bool javascriptCanAccessClipboard READ javascriptCanAccessClipboard WRITE setJavascriptCanAccessClipboard NOTIFY javascriptCanAccessClipboardChanged FINAL) + Q_PROPERTY(bool linksIncludedInFocusChain READ linksIncludedInFocusChain WRITE setLinksIncludedInFocusChain NOTIFY linksIncludedInFocusChainChanged FINAL) + Q_PROPERTY(bool localStorageEnabled READ localStorageEnabled WRITE setLocalStorageEnabled NOTIFY localStorageEnabledChanged FINAL) + Q_PROPERTY(bool localContentCanAccessRemoteUrls READ localContentCanAccessRemoteUrls WRITE setLocalContentCanAccessRemoteUrls NOTIFY localContentCanAccessRemoteUrlsChanged FINAL) + Q_PROPERTY(bool spatialNavigationEnabled READ spatialNavigationEnabled WRITE setSpatialNavigationEnabled NOTIFY spatialNavigationEnabledChanged FINAL) + Q_PROPERTY(bool localContentCanAccessFileUrls READ localContentCanAccessFileUrls WRITE setLocalContentCanAccessFileUrls NOTIFY localContentCanAccessFileUrlsChanged FINAL) + Q_PROPERTY(bool hyperlinkAuditingEnabled READ hyperlinkAuditingEnabled WRITE setHyperlinkAuditingEnabled NOTIFY hyperlinkAuditingEnabledChanged FINAL) + Q_PROPERTY(bool errorPageEnabled READ errorPageEnabled WRITE setErrorPageEnabled NOTIFY errorPageEnabledChanged FINAL) + Q_PROPERTY(bool pluginsEnabled READ pluginsEnabled WRITE setPluginsEnabled NOTIFY pluginsEnabledChanged FINAL) + Q_PROPERTY(bool fullScreenSupportEnabled READ fullScreenSupportEnabled WRITE setFullScreenSupportEnabled NOTIFY fullScreenSupportEnabledChanged REVISION(1,1) FINAL) + Q_PROPERTY(QString defaultTextEncoding READ defaultTextEncoding WRITE setDefaultTextEncoding NOTIFY defaultTextEncodingChanged FINAL) + Q_PROPERTY(bool screenCaptureEnabled READ screenCaptureEnabled WRITE setScreenCaptureEnabled NOTIFY screenCaptureEnabledChanged REVISION(1,2) FINAL) + Q_PROPERTY(bool webGLEnabled READ webGLEnabled WRITE setWebGLEnabled NOTIFY webGLEnabledChanged REVISION(1,2) FINAL) + Q_PROPERTY(bool accelerated2dCanvasEnabled READ accelerated2dCanvasEnabled WRITE setAccelerated2dCanvasEnabled NOTIFY accelerated2dCanvasEnabledChanged REVISION(1,2) FINAL) + Q_PROPERTY(bool autoLoadIconsForPage READ autoLoadIconsForPage WRITE setAutoLoadIconsForPage NOTIFY autoLoadIconsForPageChanged REVISION(1,2) FINAL) + Q_PROPERTY(bool touchIconsEnabled READ touchIconsEnabled WRITE setTouchIconsEnabled NOTIFY touchIconsEnabledChanged REVISION(1,2) FINAL) + Q_PROPERTY(bool focusOnNavigationEnabled READ focusOnNavigationEnabled WRITE setFocusOnNavigationEnabled NOTIFY focusOnNavigationEnabledChanged REVISION(1,3) FINAL) + Q_PROPERTY(bool printElementBackgrounds READ printElementBackgrounds WRITE setPrintElementBackgrounds NOTIFY printElementBackgroundsChanged REVISION(1,3) FINAL) + Q_PROPERTY(bool allowRunningInsecureContent READ allowRunningInsecureContent WRITE setAllowRunningInsecureContent NOTIFY allowRunningInsecureContentChanged REVISION(1,3) FINAL) + Q_PROPERTY(bool allowGeolocationOnInsecureOrigins READ allowGeolocationOnInsecureOrigins WRITE setAllowGeolocationOnInsecureOrigins NOTIFY allowGeolocationOnInsecureOriginsChanged REVISION(1,4) FINAL) + Q_PROPERTY(bool allowWindowActivationFromJavaScript READ allowWindowActivationFromJavaScript WRITE setAllowWindowActivationFromJavaScript NOTIFY allowWindowActivationFromJavaScriptChanged REVISION(1,5) FINAL) + Q_PROPERTY(bool showScrollBars READ showScrollBars WRITE setShowScrollBars NOTIFY showScrollBarsChanged REVISION(1,5) FINAL) + Q_PROPERTY(UnknownUrlSchemePolicy unknownUrlSchemePolicy READ unknownUrlSchemePolicy WRITE setUnknownUrlSchemePolicy NOTIFY unknownUrlSchemePolicyChanged REVISION(1,6) FINAL) + Q_PROPERTY(bool playbackRequiresUserGesture READ playbackRequiresUserGesture WRITE setPlaybackRequiresUserGesture NOTIFY playbackRequiresUserGestureChanged REVISION(1,6) FINAL) + Q_PROPERTY(bool webRTCPublicInterfacesOnly READ webRTCPublicInterfacesOnly WRITE setWebRTCPublicInterfacesOnly NOTIFY webRTCPublicInterfacesOnlyChanged REVISION(1,6) FINAL) + Q_PROPERTY(bool javascriptCanPaste READ javascriptCanPaste WRITE setJavascriptCanPaste NOTIFY javascriptCanPasteChanged REVISION(1,6) FINAL) + Q_PROPERTY(bool dnsPrefetchEnabled READ dnsPrefetchEnabled WRITE setDnsPrefetchEnabled NOTIFY dnsPrefetchEnabledChanged REVISION(1,7) FINAL) + Q_PROPERTY(bool pdfViewerEnabled READ pdfViewerEnabled WRITE setPdfViewerEnabled NOTIFY pdfViewerEnabledChanged REVISION(1,8) FINAL) + Q_PROPERTY(bool navigateOnDropEnabled READ navigateOnDropEnabled WRITE setNavigateOnDropEnabled NOTIFY navigateOnDropEnabledChanged REVISION(6,4) FINAL) + Q_PROPERTY(bool readingFromCanvasEnabled READ readingFromCanvasEnabled WRITE setReadingFromCanvasEnabled NOTIFY readingFromCanvasEnabledChanged REVISION(6,6) FINAL) + Q_PROPERTY(bool forceDarkMode READ forceDarkMode WRITE setForceDarkMode NOTIFY forceDarkModeChanged REVISION(6,7) FINAL) + Q_PROPERTY(bool scrollAnimatorEnabled READ scrollAnimatorEnabled WRITE setScrollAnimatorEnabled NOTIFY scrollAnimatorEnabledChanged REVISION(6,8) FINAL) + Q_PROPERTY(ImageAnimationPolicy imageAnimationPolicy READ imageAnimationPolicy WRITE setImageAnimationPolicy NOTIFY imageAnimationPolicyChanged REVISION(6,8) FINAL) + QML_NAMED_ELEMENT(WebEngineSettings) + QML_ADDED_IN_VERSION(1, 1) + QML_EXTRA_VERSION(2, 0) + QML_UNCREATABLE("") +public: + enum UnknownUrlSchemePolicy { + DisallowUnknownUrlSchemes = 1, + AllowUnknownUrlSchemesFromUserInteraction, + AllowAllUnknownUrlSchemes + }; + + Q_ENUM(UnknownUrlSchemePolicy) + + enum ImageAnimationPolicy { + AllowImageAnimation = 1, + AnimateImageOnce, + DisallowImageAnimation + }; + + Q_ENUM(ImageAnimationPolicy) + + ~QQuickWebEngineSettings(); + + bool autoLoadImages() const; + bool javascriptEnabled() const; + bool javascriptCanOpenWindows() const; + bool javascriptCanAccessClipboard() const; + bool linksIncludedInFocusChain() const; + bool localStorageEnabled() const; + bool localContentCanAccessRemoteUrls() const; + bool spatialNavigationEnabled() const; + bool localContentCanAccessFileUrls() const; + bool hyperlinkAuditingEnabled() const; + bool errorPageEnabled() const; + bool pluginsEnabled() const; + bool fullScreenSupportEnabled() const; + QString defaultTextEncoding() const; + bool screenCaptureEnabled() const; + bool webGLEnabled() const; + bool accelerated2dCanvasEnabled() const; + bool autoLoadIconsForPage() const; + bool touchIconsEnabled() const; + bool focusOnNavigationEnabled() const; + bool printElementBackgrounds() const; + bool allowRunningInsecureContent() const; + bool allowGeolocationOnInsecureOrigins() const; + bool allowWindowActivationFromJavaScript() const; + bool showScrollBars() const; + UnknownUrlSchemePolicy unknownUrlSchemePolicy() const; + bool playbackRequiresUserGesture() const; + bool webRTCPublicInterfacesOnly() const; + bool javascriptCanPaste() const; + bool dnsPrefetchEnabled() const; + bool pdfViewerEnabled() const; + bool navigateOnDropEnabled() const; + bool readingFromCanvasEnabled() const; + bool forceDarkMode() const; + bool scrollAnimatorEnabled() const; + ImageAnimationPolicy imageAnimationPolicy() const; + + void setAutoLoadImages(bool on); + void setJavascriptEnabled(bool on); + void setJavascriptCanOpenWindows(bool on); + void setJavascriptCanAccessClipboard(bool on); + void setLinksIncludedInFocusChain(bool on); + void setLocalStorageEnabled(bool on); + void setLocalContentCanAccessRemoteUrls(bool on); + void setSpatialNavigationEnabled(bool on); + void setLocalContentCanAccessFileUrls(bool on); + void setHyperlinkAuditingEnabled(bool on); + void setErrorPageEnabled(bool on); + void setPluginsEnabled(bool on); + void setFullScreenSupportEnabled(bool on); + void setDefaultTextEncoding(QString encoding); + void setScreenCaptureEnabled(bool on); + void setWebGLEnabled(bool on); + void setAccelerated2dCanvasEnabled(bool on); + void setAutoLoadIconsForPage(bool on); + void setTouchIconsEnabled(bool on); + void setFocusOnNavigationEnabled(bool on); + void setPrintElementBackgrounds(bool on); + void setAllowRunningInsecureContent(bool on); + void setAllowGeolocationOnInsecureOrigins(bool on); + void setAllowWindowActivationFromJavaScript(bool on); + void setShowScrollBars(bool on); + void setUnknownUrlSchemePolicy(UnknownUrlSchemePolicy policy); + void setPlaybackRequiresUserGesture(bool on); + void setWebRTCPublicInterfacesOnly(bool on); + void setJavascriptCanPaste(bool on); + void setDnsPrefetchEnabled(bool on); + void setPdfViewerEnabled(bool on); + void setNavigateOnDropEnabled(bool on); + void setReadingFromCanvasEnabled(bool on); + void setForceDarkMode(bool on); + void setScrollAnimatorEnabled(bool on); + void setImageAnimationPolicy(ImageAnimationPolicy policy); + +signals: + void autoLoadImagesChanged(); + void javascriptEnabledChanged(); + void javascriptCanOpenWindowsChanged(); + void javascriptCanAccessClipboardChanged(); + void linksIncludedInFocusChainChanged(); + void localStorageEnabledChanged(); + void localContentCanAccessRemoteUrlsChanged(); + void spatialNavigationEnabledChanged(); + void localContentCanAccessFileUrlsChanged(); + void hyperlinkAuditingEnabledChanged(); + void errorPageEnabledChanged(); + void pluginsEnabledChanged(); + Q_REVISION(1,1) void fullScreenSupportEnabledChanged(); + void defaultTextEncodingChanged(); + Q_REVISION(1,2) void screenCaptureEnabledChanged(); + Q_REVISION(1,2) void webGLEnabledChanged(); + Q_REVISION(1,2) void accelerated2dCanvasEnabledChanged(); + Q_REVISION(1,2) void autoLoadIconsForPageChanged(); + Q_REVISION(1,2) void touchIconsEnabledChanged(); + Q_REVISION(1,3) void focusOnNavigationEnabledChanged(); + Q_REVISION(1,3) void printElementBackgroundsChanged(); + Q_REVISION(1,3) void allowRunningInsecureContentChanged(); + Q_REVISION(1,4) void allowGeolocationOnInsecureOriginsChanged(); + Q_REVISION(1,5) void allowWindowActivationFromJavaScriptChanged(); + Q_REVISION(1,5) void showScrollBarsChanged(); + Q_REVISION(1,6) void unknownUrlSchemePolicyChanged(); + Q_REVISION(1,6) void playbackRequiresUserGestureChanged(); + Q_REVISION(1,6) void webRTCPublicInterfacesOnlyChanged(); + Q_REVISION(1,6) void javascriptCanPasteChanged(); + Q_REVISION(1,7) void dnsPrefetchEnabledChanged(); + Q_REVISION(1,8) void pdfViewerEnabledChanged(); + Q_REVISION(6,4) void navigateOnDropEnabledChanged(); + Q_REVISION(6,6) void readingFromCanvasEnabledChanged(); + Q_REVISION(6,7) void forceDarkModeChanged(); + Q_REVISION(6,8) void scrollAnimatorEnabledChanged(); + Q_REVISION(6,8) void imageAnimationPolicyChanged(); + +private: + explicit QQuickWebEngineSettings(QQuickWebEngineSettings *parentSettings = nullptr); + Q_DISABLE_COPY(QQuickWebEngineSettings) + friend class QQuickWebEngineProfilePrivate; + friend class QQuickWebEngineViewPrivate; + friend class QQuickWebEngineView; + void setParentSettings(QQuickWebEngineSettings *parentSettings); + + QScopedPointer<QWebEngineSettings> d_ptr; +}; + +QT_END_NAMESPACE + +#endif // QQUICKWEBENGINESETTINGS_P_H diff --git a/src/webenginequick/api/qquickwebenginesingleton.cpp b/src/webenginequick/api/qquickwebenginesingleton.cpp new file mode 100644 index 000000000..a51d2aca4 --- /dev/null +++ b/src/webenginequick/api/qquickwebenginesingleton.cpp @@ -0,0 +1,87 @@ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + +#include "qquickwebengineprofile.h" +#include "qquickwebenginesettings_p.h" +#include "qquickwebenginesingleton_p.h" + +#include <QtQml/qqmlcontext.h> +#include <QtQml/qqmlengine.h> + +QT_BEGIN_NAMESPACE + +/*! + \qmltype WebEngine + //! \instantiates QQuickWebEngineSingleton + \inqmlmodule QtWebEngine + \since QtWebEngine 1.1 + \brief Provides access to the default settings and profiles shared by all web engine views. + + The WebEngine singleton type provides access to the default profile and the default settings + shared by all web engine views. It can be used to change settings globally, as illustrated by + the following code snippet: + + \code + Component.onCompleted: { + WebEngine.settings.pluginsEnabled = true; + } + \endcode +*/ + +/*! + \qmlproperty WebEngineSettings WebEngine::settings + \readonly + \since QtWebEngine 1.1 + + Default settings for all web engine views. + + \sa WebEngineSettings +*/ + +QQuickWebEngineSettings *QQuickWebEngineSingleton::settings() const +{ + return defaultProfile()->settings(); +} + +/*! + \qmlproperty WebEngineProfile WebEngine::defaultProfile + \readonly + \since QtWebEngine 1.1 + + Default profile for all web engine views. + + \sa WebEngineProfile +*/ +QQuickWebEngineProfile *QQuickWebEngineSingleton::defaultProfile() const +{ + auto profile = QQuickWebEngineProfile::defaultProfile(); + + // MEMO first ever call to default profile will create one without context + // it needs something to get qml engine from (WebEngine singleton is created in qml land) + profile->ensureQmlContext(this); + + return profile; +} + +/*! + \qmlmethod WebEngineScript WebEngine::script + //! \instantiates QWebEngineScript + \since QtWebEngine 6.2 + + Constructs WebEngineScript, which can be set up and inserted into user scripts' collection + for \l{WebEngineView::userScripts}{WebEngineView.userScripts} or + \l{WebEngineProfile::userScripts}{WebEngineProfile.userScripts} + using \l{WebEngineScriptCollection}. + + \sa WebEngineScript WebEngineScriptCollection +*/ + +QWebEngineScript QQuickWebEngineSingleton::script() const +{ + return QWebEngineScript(); +} + +QT_END_NAMESPACE + +#include "moc_qquickwebenginesingleton_p.cpp" + diff --git a/src/webenginequick/api/qquickwebenginesingleton_p.h b/src/webenginequick/api/qquickwebenginesingleton_p.h new file mode 100644 index 000000000..b05daecd6 --- /dev/null +++ b/src/webenginequick/api/qquickwebenginesingleton_p.h @@ -0,0 +1,44 @@ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + +#ifndef QQUICKWEBENGINESINGLETON_P_H +#define QQUICKWEBENGINESINGLETON_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 <QtCore/qobject.h> +#include <QtQml/qqml.h> +#include <QtWebEngineCore/qwebenginescript.h> +#include <QtWebEngineQuick/private/qtwebenginequickglobal_p.h> + +QT_BEGIN_NAMESPACE + +class QQuickWebEngineSettings; +class QQuickWebEngineProfile; + +class Q_WEBENGINEQUICK_EXPORT QQuickWebEngineSingleton : public QObject { + Q_OBJECT + Q_PROPERTY(QQuickWebEngineSettings* settings READ settings CONSTANT FINAL) + Q_PROPERTY(QQuickWebEngineProfile* defaultProfile READ defaultProfile CONSTANT FINAL REVISION(1,1)) + QML_SINGLETON + QML_NAMED_ELEMENT(WebEngine) + QML_ADDED_IN_VERSION(1, 1) + QML_EXTRA_VERSION(2, 0) +public: + QQuickWebEngineSettings *settings() const; + QQuickWebEngineProfile *defaultProfile() const; + Q_INVOKABLE QWebEngineScript script() const; +}; + +QT_END_NAMESPACE + +#endif // QQUICKWEBENGINESINGLETON_P_H diff --git a/src/webenginequick/api/qquickwebenginetouchhandle.cpp b/src/webenginequick/api/qquickwebenginetouchhandle.cpp new file mode 100644 index 000000000..473463fa3 --- /dev/null +++ b/src/webenginequick/api/qquickwebenginetouchhandle.cpp @@ -0,0 +1,45 @@ +// Copyright (C) 2022 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + +#include "qquickwebenginetouchhandle_p.h" +#include "qquickwebenginetouchhandleprovider_p_p.h" +#include "web_contents_adapter_client.h" +#include <QtQuick/qquickitem.h> + +QT_BEGIN_NAMESPACE + +QQuickWebEngineTouchHandle::QQuickWebEngineTouchHandle() : QObject(nullptr), m_hasImage(false) { } + +void QQuickWebEngineTouchHandle::setBounds(const QRect &bounds) +{ + m_item->setX(bounds.x()); + m_item->setY(bounds.y()); + m_item->setWidth(bounds.width()); + m_item->setHeight(bounds.height()); +} + +void QQuickWebEngineTouchHandle::setOpacity(float opacity) +{ + m_item->setOpacity(opacity); +} + +void QQuickWebEngineTouchHandle::setImage(int orientation) +{ + if (m_hasImage) { + QUrl url = QQuickWebEngineTouchHandleProvider::url(orientation); + m_item->setProperty("source", url); + } +} + +void QQuickWebEngineTouchHandle::setVisible(bool visible) +{ + m_item->setVisible(visible); +} + +void QQuickWebEngineTouchHandle::setItem(QQuickItem *item, bool hasImage) +{ + m_hasImage = hasImage; + m_item.reset(item); +} + +QT_END_NAMESPACE diff --git a/src/webenginequick/api/qquickwebenginetouchhandle_p.h b/src/webenginequick/api/qquickwebenginetouchhandle_p.h new file mode 100644 index 000000000..d1deceae3 --- /dev/null +++ b/src/webenginequick/api/qquickwebenginetouchhandle_p.h @@ -0,0 +1,47 @@ +// Copyright (C) 2022 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + +#ifndef QQUICKWEBENGINETOUCHHANDLE_P_H +#define QQUICKWEBENGINETOUCHHANDLE_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 "touch_handle_drawable_client.h" +#include <QtQml/qqmlregistration.h> +#include <QtCore/qrect.h> +#include <QtCore/qobject.h> + +namespace QtWebEngineCore { +class WebContentsAdapterClient; +} + +QT_BEGIN_NAMESPACE + +class QQuickItem; +class QQuickWebEngineTouchHandle : public QtWebEngineCore::TouchHandleDrawableDelegate, + public QObject +{ +public: + QQuickWebEngineTouchHandle(); + void setImage(int orintation) override; + void setBounds(const QRect &bounds) override; + void setVisible(bool visible) override; + void setOpacity(float opacity) override; + void setItem(QQuickItem *item, bool hasImage); + +private: + QScopedPointer<QQuickItem> m_item; + bool m_hasImage; +}; + +QT_END_NAMESPACE + +#endif // QQUICKWEBENGINETOUCHHANDLE_P_H diff --git a/src/webenginequick/api/qquickwebenginetouchhandleprovider.cpp b/src/webenginequick/api/qquickwebenginetouchhandleprovider.cpp new file mode 100644 index 000000000..099fa8876 --- /dev/null +++ b/src/webenginequick/api/qquickwebenginetouchhandleprovider.cpp @@ -0,0 +1,44 @@ +// Copyright (C) 2018 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + +#include "qquickwebenginetouchhandleprovider_p_p.h" + +// static +QString QQuickWebEngineTouchHandleProvider::identifier() +{ + return QStringLiteral("touchhandle"); +} + +// static +QUrl QQuickWebEngineTouchHandleProvider::url(int orientation) +{ + return QUrl(QStringLiteral("image://%1/%2").arg(identifier(), QString::number(orientation))); +} + +QQuickWebEngineTouchHandleProvider::QQuickWebEngineTouchHandleProvider() + : QQuickImageProvider(QQuickImageProvider::Image) +{ +} + +QQuickWebEngineTouchHandleProvider::~QQuickWebEngineTouchHandleProvider() +{ +} + +void QQuickWebEngineTouchHandleProvider::init(const QMap<int, QImage> &images) +{ + if (!m_touchHandleMap.empty()) { + Q_ASSERT(images.size() == m_touchHandleMap.size()); + return; + } + + m_touchHandleMap = images; +} + +QImage QQuickWebEngineTouchHandleProvider::requestImage(const QString &id, QSize *size, const QSize &requestedSize) +{ + Q_UNUSED(size); + Q_UNUSED(requestedSize); + + Q_ASSERT(m_touchHandleMap.contains(id.toInt())); + return m_touchHandleMap.value(id.toInt()); +} diff --git a/src/webenginequick/api/qquickwebenginetouchhandleprovider_p_p.h b/src/webenginequick/api/qquickwebenginetouchhandleprovider_p_p.h new file mode 100644 index 000000000..92a13b08e --- /dev/null +++ b/src/webenginequick/api/qquickwebenginetouchhandleprovider_p_p.h @@ -0,0 +1,41 @@ +// Copyright (C) 2018 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + +#ifndef QQUICKWEBENGINETOUCHHANDLEPROVIDER_P_P_H +#define QQUICKWEBENGINETOUCHHANDLEPROVIDER_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 <QtQuick/qquickimageprovider.h> +#include <QtWebEngineQuick/private/qtwebenginequickglobal_p.h> + +QT_BEGIN_NAMESPACE + +class Q_WEBENGINEQUICK_EXPORT QQuickWebEngineTouchHandleProvider : public QQuickImageProvider { +public: + static QString identifier(); + static QUrl url(int orientation); + + QQuickWebEngineTouchHandleProvider(); + ~QQuickWebEngineTouchHandleProvider(); + + void init(const QMap<int, QImage> &images); + QImage requestImage(const QString &id, QSize *size, const QSize &requestedSize) override; + +private: + QMap<int, QImage> m_touchHandleMap; +}; + + +QT_END_NAMESPACE + +#endif // QQUICKWEBENGINETOUCHHANDLEPROVIDER_P_P_H diff --git a/src/webenginequick/api/qquickwebenginetouchselectionmenurequest.cpp b/src/webenginequick/api/qquickwebenginetouchselectionmenurequest.cpp new file mode 100644 index 000000000..70519525d --- /dev/null +++ b/src/webenginequick/api/qquickwebenginetouchselectionmenurequest.cpp @@ -0,0 +1,108 @@ +// Copyright (C) 2021 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + +#include "qquickwebenginetouchselectionmenurequest_p.h" +#include "qquickwebenginetouchselectionmenurequest_p_p.h" +#include "touch_selection_menu_controller.h" + +QT_BEGIN_NAMESPACE + +ASSERT_ENUMS_MATCH(QQuickWebEngineTouchSelectionMenuRequest::Cut, + QtWebEngineCore::TouchSelectionMenuController::TouchSelectionCommandFlag::Cut) +ASSERT_ENUMS_MATCH(QQuickWebEngineTouchSelectionMenuRequest::Copy, + QtWebEngineCore::TouchSelectionMenuController::TouchSelectionCommandFlag::Copy) +ASSERT_ENUMS_MATCH(QQuickWebEngineTouchSelectionMenuRequest::Paste, + QtWebEngineCore::TouchSelectionMenuController::TouchSelectionCommandFlag::Paste) + +/*! + \class QQuickWebEngineTouchSelectionMenuRequest + \since 6.3 + \brief The QQuickWebEngineTouchSelectionMenuRequest class provides request for a touch selection menu. + \inmodule QtWebEngineQuick + QQuickWebEngineTouchSelectionMenuRequest is returned after a touch selection event, + and contains information about where the bounding box of touch selection is and what + actions are available. + + \internal +*/ + +/*! + \enum QQuickWebEngineTouchSelectionMenuRequest::TouchSelectionCommandFlag + \readonly + \since 6.3 + + The available operations in the current touch selection menu request. + + \value Cut Cut is available. + \value Copy Copy is available. + \value Paste Paste is available. +*/ +QQuickWebEngineTouchSelectionMenuRequest::QQuickWebEngineTouchSelectionMenuRequest( + QRect bounds, QtWebEngineCore::TouchSelectionMenuController *touchSelectionMenuController) + : d(new QQuickWebEngineTouchSelectionMenuRequestPrivate(bounds, touchSelectionMenuController)) +{ +} + +QQuickWebEngineTouchSelectionMenuRequestPrivate::QQuickWebEngineTouchSelectionMenuRequestPrivate( + QRect bounds, QtWebEngineCore::TouchSelectionMenuController *touchSelectionMenuController) +{ + selectionBounds = bounds; + buttonCount = touchSelectionMenuController->buttonCount(); + touchSelectionCommandFlags = touchSelectionMenuController->availableActions(); +} + +/*! + Destroys the touch selection menu request. +*/ +QQuickWebEngineTouchSelectionMenuRequest::~QQuickWebEngineTouchSelectionMenuRequest() +{ +} + +/*! + Returns the number of buttons that must be displayed, based on the available actions. +*/ +int QQuickWebEngineTouchSelectionMenuRequest::buttonCount() +{ + return d->buttonCount; +} + +/*! + Indicates whether the touch selection menu request has been + accepted by the signal handler. + + If the property is \c false after any signal handlers + for WebEngineView::touchSelectionMenuRequested have been executed, + a default touch selection menu will be shown. + To prevent this, set \c{request.accepted} to \c true. + + The default is \c false. +*/ +bool QQuickWebEngineTouchSelectionMenuRequest::isAccepted() const +{ + return d->accepted; +} + +void QQuickWebEngineTouchSelectionMenuRequest::setAccepted(bool accepted) +{ + d->accepted = accepted; +} + +/*! + Returns the bound rectangle of text selection. +*/ +QRect QQuickWebEngineTouchSelectionMenuRequest::selectionBounds() +{ + return d->selectionBounds; +} + +/*! + Returns the available operations in the current context. +*/ +QQuickWebEngineTouchSelectionMenuRequest::TouchSelectionCommandFlags QQuickWebEngineTouchSelectionMenuRequest::touchSelectionCommandFlags() const +{ + return static_cast<QQuickWebEngineTouchSelectionMenuRequest::TouchSelectionCommandFlags>(d->touchSelectionCommandFlags); +} + +QT_END_NAMESPACE + +#include "moc_qquickwebenginetouchselectionmenurequest_p.cpp" diff --git a/src/webenginequick/api/qquickwebenginetouchselectionmenurequest_p.h b/src/webenginequick/api/qquickwebenginetouchselectionmenurequest_p.h new file mode 100644 index 000000000..c7decafe1 --- /dev/null +++ b/src/webenginequick/api/qquickwebenginetouchselectionmenurequest_p.h @@ -0,0 +1,66 @@ +// Copyright (C) 2021 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + +#ifndef QQUICKWEBENGINETOUCHSELECTIONMENUREQUEST_P_H +#define QQUICKWEBENGINETOUCHSELECTIONMENUREQUEST_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 <QtWebEngineQuick/qtwebenginequickglobal.h> +#include <QtCore/qobject.h> +#include <QtCore/qscopedpointer.h> +#include <QtQml/qqmlregistration.h> + +namespace QtWebEngineCore { +class TouchSelectionMenuController; +} + +QT_BEGIN_NAMESPACE + +class QQuickWebEngineTouchSelectionMenuRequestPrivate; + +class Q_WEBENGINEQUICK_EXPORT QQuickWebEngineTouchSelectionMenuRequest : public QObject +{ + Q_OBJECT +public: + enum TouchSelectionCommandFlag { + Cut = 0x1, + Copy = 0x2, + Paste = 0x4 + }; + + Q_DECLARE_FLAGS(TouchSelectionCommandFlags, TouchSelectionCommandFlag) + Q_FLAG(TouchSelectionCommandFlags) + Q_PROPERTY(bool accepted READ isAccepted WRITE setAccepted FINAL) + Q_PROPERTY(QRect selectionBounds READ selectionBounds CONSTANT FINAL REVISION(1)) + Q_PROPERTY(TouchSelectionCommandFlags touchSelectionCommandFlags READ touchSelectionCommandFlags CONSTANT FINAL REVISION(1)) + QML_NAMED_ELEMENT(TouchSelectionMenuRequest) + QML_ADDED_IN_VERSION(6, 3) + QML_UNCREATABLE("") + + QQuickWebEngineTouchSelectionMenuRequest(QRect bounds, + QtWebEngineCore::TouchSelectionMenuController *touchSelectionMenuController); + ~QQuickWebEngineTouchSelectionMenuRequest(); + + int buttonCount(); + bool isAccepted() const; + void setAccepted(bool accepted); + QRect selectionBounds(); + TouchSelectionCommandFlags touchSelectionCommandFlags() const; + +private: + QScopedPointer<QQuickWebEngineTouchSelectionMenuRequestPrivate> d; +}; + +QT_END_NAMESPACE + +#endif // QQUICKWEBENGINETOUCHSELECTIONMENUREQUEST_P_H diff --git a/src/webenginequick/api/qquickwebenginetouchselectionmenurequest_p_p.h b/src/webenginequick/api/qquickwebenginetouchselectionmenurequest_p_p.h new file mode 100644 index 000000000..f8eba652e --- /dev/null +++ b/src/webenginequick/api/qquickwebenginetouchselectionmenurequest_p_p.h @@ -0,0 +1,43 @@ +// Copyright (C) 2021 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + +#ifndef QQUICKWEBENGINETOUCHSELECTIONMENUREQUEST_P_P_H +#define QQUICKWEBENGINETOUCHSELECTIONMENUREQUEST_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 <QtWebEngineQuick/private/qquickwebengineview_p.h> +#include "qquickwebenginetouchselectionmenurequest_p.h" + +namespace QtWebEngineCore { +class TouchSelectionMenuController; +} + +QT_BEGIN_NAMESPACE + +class QQuickWebEngineTouchSelectionMenuRequest; + +class QQuickWebEngineTouchSelectionMenuRequestPrivate +{ +public: + QQuickWebEngineTouchSelectionMenuRequestPrivate( + QRect bounds, QtWebEngineCore::TouchSelectionMenuController *touchSelectionMenuController); + + bool accepted = false; + QRect selectionBounds; + uint touchSelectionCommandFlags; + int buttonCount; +}; + +QT_END_NAMESPACE + +#endif // QQUICKWEBENGINETOUCHSELECTIONMENUREQUEST_P_P_H diff --git a/src/webenginequick/api/qquickwebengineview.cpp b/src/webenginequick/api/qquickwebengineview.cpp new file mode 100644 index 000000000..85c5e1a73 --- /dev/null +++ b/src/webenginequick/api/qquickwebengineview.cpp @@ -0,0 +1,2543 @@ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + +#include "qquickwebengineaction_p.h" +#include "qquickwebengineaction_p_p.h" +#include "qquickwebengineclientcertificateselection_p.h" +#include "qquickwebenginedialogrequests_p.h" +#include "qquickwebenginefaviconprovider_p_p.h" +#include "qquickwebenginenewwindowrequest_p.h" +#include "qquickwebengineprofile.h" +#include "qquickwebengineprofile_p.h" +#include "qquickwebenginescriptcollection_p.h" +#include "qquickwebenginescriptcollection_p_p.h" +#include "qquickwebenginesettings_p.h" +#include "qquickwebenginetouchhandleprovider_p_p.h" +#include "qquickwebenginetouchhandle_p.h" +#include "qquickwebenginetouchselectionmenurequest_p.h" +#include "qquickwebengineview_p.h" +#include "qquickwebengineview_p_p.h" + +#include "authentication_dialog_controller.h" +#include "autofill_popup_controller.h" +#include "profile_adapter.h" +#include "file_picker_controller.h" +#include "find_text_helper.h" +#include "javascript_dialog_controller.h" +#include "render_widget_host_view_qt_delegate_item.h" +#include "render_widget_host_view_qt_delegate_quickwindow_p.h" +#include "touch_selection_menu_controller.h" +#include "ui_delegates_manager_p.h" +#include "web_contents_adapter.h" + +#include <QtWebEngineCore/qwebenginecertificateerror.h> +#include <QtWebEngineCore/qwebenginedesktopmediarequest.h> +#include <QtWebEngineCore/qwebenginefilesystemaccessrequest.h> +#include <QtWebEngineCore/qwebenginefindtextresult.h> +#include <QtWebEngineCore/qwebenginefullscreenrequest.h> +#include <QtWebEngineCore/qwebengineloadinginfo.h> +#include <QtWebEngineCore/qwebenginenavigationrequest.h> +#include <QtWebEngineCore/qwebenginepage.h> +#include <QtWebEngineCore/qwebengineregisterprotocolhandlerrequest.h> +#include <QtWebEngineCore/qwebenginescriptcollection.h> +#include <QtWebEngineCore/qwebenginewebauthuxrequest.h> +#include <QtWebEngineCore/private/qwebenginecontextmenurequest_p.h> +#include <QtWebEngineCore/private/qwebenginedesktopmediarequest_p.h> +#include <QtWebEngineCore/private/qwebenginehistory_p.h> +#include <QtWebEngineCore/private/qwebenginenewwindowrequest_p.h> +#include <QtWebEngineCore/private/qwebenginescriptcollection_p.h> +#include <QtWebEngineCore/private/qwebenginepage_p.h> +#include <QtWebEngineCore/private/qtwebenginecoreglobal_p.h> + +#include <QtCore/qloggingcategory.h> +#include <QtCore/qmimedata.h> +#include <QtCore/qurl.h> +#include <QtCore/qtimer.h> +#include <QtGui/qclipboard.h> +#include <QtGui/qguiapplication.h> +#include <QtGui/private/qguiapplication_p.h> +#include <QtGui/qpa/qplatformintegration.h> +#include <QtQml/qqmlcomponent.h> +#include <QtQml/qqmlcontext.h> +#include <QtQml/qqmlengine.h> +#include <QtQml/qqmlproperty.h> + +#if QT_CONFIG(accessibility) +#include "qquickwebengine_accessible_p.h" + +#include <QtGui/qaccessible.h> +#endif + +#if QT_CONFIG(webengine_printing_and_pdf) +#include <QtCore/qmargins.h> +#include <QtGui/qpagelayout.h> +#include <QtGui/qpageranges.h> +#include <QtGui/qpagesize.h> +#endif + +#if QT_CONFIG(webengine_webchannel) +#include <QtWebChannelQuick/qqmlwebchannel.h> +#endif + +QT_BEGIN_NAMESPACE +using namespace QtWebEngineCore; + +Q_STATIC_ASSERT(int(QQuickWebEngineView::WebActionCount) == int(QWebEnginePage::WebActionCount)); +using LoadStatus = QWebEngineLoadingInfo::LoadStatus; +using ErrorDomain = QWebEngineLoadingInfo::ErrorDomain; +#if QT_DEPRECATED_SINCE(6, 2) +QT_WARNING_PUSH QT_WARNING_DISABLE_DEPRECATED +Q_STATIC_ASSERT(static_cast<int>(QQuickWebEngineView::AcceptRequest) == static_cast<int>(QWebEngineNavigationRequest::AcceptRequest)); +Q_STATIC_ASSERT(static_cast<int>(QQuickWebEngineView::IgnoreRequest) == static_cast<int>(QWebEngineNavigationRequest::IgnoreRequest)); +Q_STATIC_ASSERT(static_cast<int>(QQuickWebEngineView::LinkClickedNavigation) == static_cast<int>(QWebEngineNavigationRequest::LinkClickedNavigation)); +Q_STATIC_ASSERT(static_cast<int>(QQuickWebEngineView::TypedNavigation) == static_cast<int>(QWebEngineNavigationRequest::TypedNavigation)); +Q_STATIC_ASSERT(static_cast<int>(QQuickWebEngineView::FormSubmittedNavigation) == static_cast<int>(QWebEngineNavigationRequest::FormSubmittedNavigation)); +Q_STATIC_ASSERT(static_cast<int>(QQuickWebEngineView::BackForwardNavigation) == static_cast<int>(QWebEngineNavigationRequest::BackForwardNavigation)); +Q_STATIC_ASSERT(static_cast<int>(QQuickWebEngineView::ReloadNavigation) == static_cast<int>(QWebEngineNavigationRequest::ReloadNavigation)); +Q_STATIC_ASSERT(static_cast<int>(QQuickWebEngineView::OtherNavigation) == static_cast<int>(QWebEngineNavigationRequest::OtherNavigation)); +Q_STATIC_ASSERT(static_cast<int>(QQuickWebEngineView::RedirectNavigation) == static_cast<int>(QWebEngineNavigationRequest::RedirectNavigation)); +Q_STATIC_ASSERT(static_cast<int>(QQuickWebEngineView::NewViewInWindow) == static_cast<int>(QWebEngineNewWindowRequest::InNewWindow)); +Q_STATIC_ASSERT(static_cast<int>(QQuickWebEngineView::NewViewInTab) == static_cast<int>(QWebEngineNewWindowRequest::InNewTab)); +Q_STATIC_ASSERT(static_cast<int>(QQuickWebEngineView::NewViewInDialog) == static_cast<int>(QWebEngineNewWindowRequest::InNewDialog)); +Q_STATIC_ASSERT(static_cast<int>(QQuickWebEngineView::NewViewInBackgroundTab) == static_cast<int>(QWebEngineNewWindowRequest::InNewBackgroundTab)); +Q_STATIC_ASSERT(static_cast<int>(QQuickWebEngineView::NoErrorDomain) == static_cast<int>(ErrorDomain::NoErrorDomain)); +Q_STATIC_ASSERT(static_cast<int>(QQuickWebEngineView::InternalErrorDomain) == static_cast<int>(ErrorDomain::InternalErrorDomain)); +Q_STATIC_ASSERT(static_cast<int>(QQuickWebEngineView::ConnectionErrorDomain) == static_cast<int>(ErrorDomain::ConnectionErrorDomain)); +Q_STATIC_ASSERT(static_cast<int>(QQuickWebEngineView::CertificateErrorDomain) == static_cast<int>(ErrorDomain::CertificateErrorDomain)); +Q_STATIC_ASSERT(static_cast<int>(QQuickWebEngineView::HttpErrorDomain) == static_cast<int>(ErrorDomain::HttpErrorDomain)); +Q_STATIC_ASSERT(static_cast<int>(QQuickWebEngineView::FtpErrorDomain) == static_cast<int>(ErrorDomain::FtpErrorDomain)); +Q_STATIC_ASSERT(static_cast<int>(QQuickWebEngineView::DnsErrorDomain) == static_cast<int>(ErrorDomain::DnsErrorDomain)); +Q_STATIC_ASSERT(static_cast<int>(QQuickWebEngineView::LoadStartedStatus) == static_cast<int>(LoadStatus::LoadStartedStatus)); +Q_STATIC_ASSERT(static_cast<int>(QQuickWebEngineView::LoadStoppedStatus) == static_cast<int>(LoadStatus::LoadStoppedStatus)); +Q_STATIC_ASSERT(static_cast<int>(QQuickWebEngineView::LoadFailedStatus) == static_cast<int>(LoadStatus::LoadFailedStatus)); +Q_STATIC_ASSERT(static_cast<int>(QQuickWebEngineView::LoadSucceededStatus) == static_cast<int>(LoadStatus::LoadSucceededStatus)); +QT_WARNING_POP +#endif + +#if QT_CONFIG(webengine_printing_and_pdf) +ASSERT_ENUMS_MATCH(QPageSize::PageSizeId::Letter, QQuickWebEngineView::PrintedPageSizeId::Letter) +ASSERT_ENUMS_MATCH(QPageSize::PageSizeId::Legal, QQuickWebEngineView::PrintedPageSizeId::Legal) +ASSERT_ENUMS_MATCH(QPageSize::PageSizeId::Executive, QQuickWebEngineView::PrintedPageSizeId::Executive) +ASSERT_ENUMS_MATCH(QPageSize::PageSizeId::A0, QQuickWebEngineView::PrintedPageSizeId::A0) +ASSERT_ENUMS_MATCH(QPageSize::PageSizeId::A1, QQuickWebEngineView::PrintedPageSizeId::A1) +ASSERT_ENUMS_MATCH(QPageSize::PageSizeId::A2, QQuickWebEngineView::PrintedPageSizeId::A2) +ASSERT_ENUMS_MATCH(QPageSize::PageSizeId::A3, QQuickWebEngineView::PrintedPageSizeId::A3) +ASSERT_ENUMS_MATCH(QPageSize::PageSizeId::A4, QQuickWebEngineView::PrintedPageSizeId::A4) +ASSERT_ENUMS_MATCH(QPageSize::PageSizeId::A5, QQuickWebEngineView::PrintedPageSizeId::A5) +ASSERT_ENUMS_MATCH(QPageSize::PageSizeId::A6, QQuickWebEngineView::PrintedPageSizeId::A6) +ASSERT_ENUMS_MATCH(QPageSize::PageSizeId::A7, QQuickWebEngineView::PrintedPageSizeId::A7) +ASSERT_ENUMS_MATCH(QPageSize::PageSizeId::A8, QQuickWebEngineView::PrintedPageSizeId::A8) +ASSERT_ENUMS_MATCH(QPageSize::PageSizeId::A9, QQuickWebEngineView::PrintedPageSizeId::A9) +ASSERT_ENUMS_MATCH(QPageSize::PageSizeId::A10, QQuickWebEngineView::PrintedPageSizeId::A10) +ASSERT_ENUMS_MATCH(QPageSize::PageSizeId::B0, QQuickWebEngineView::PrintedPageSizeId::B0) +ASSERT_ENUMS_MATCH(QPageSize::PageSizeId::B1, QQuickWebEngineView::PrintedPageSizeId::B1) +ASSERT_ENUMS_MATCH(QPageSize::PageSizeId::B2, QQuickWebEngineView::PrintedPageSizeId::B2) +ASSERT_ENUMS_MATCH(QPageSize::PageSizeId::B3, QQuickWebEngineView::PrintedPageSizeId::B3) +ASSERT_ENUMS_MATCH(QPageSize::PageSizeId::B4, QQuickWebEngineView::PrintedPageSizeId::B4) +ASSERT_ENUMS_MATCH(QPageSize::PageSizeId::B5, QQuickWebEngineView::PrintedPageSizeId::B5) +ASSERT_ENUMS_MATCH(QPageSize::PageSizeId::B6, QQuickWebEngineView::PrintedPageSizeId::B6) +ASSERT_ENUMS_MATCH(QPageSize::PageSizeId::B7, QQuickWebEngineView::PrintedPageSizeId::B7) +ASSERT_ENUMS_MATCH(QPageSize::PageSizeId::B8, QQuickWebEngineView::PrintedPageSizeId::B8) +ASSERT_ENUMS_MATCH(QPageSize::PageSizeId::B9, QQuickWebEngineView::PrintedPageSizeId::B9) +ASSERT_ENUMS_MATCH(QPageSize::PageSizeId::B10, QQuickWebEngineView::PrintedPageSizeId::B10) +ASSERT_ENUMS_MATCH(QPageSize::PageSizeId::C5E, QQuickWebEngineView::PrintedPageSizeId::C5E) +ASSERT_ENUMS_MATCH(QPageSize::PageSizeId::Comm10E, QQuickWebEngineView::PrintedPageSizeId::Comm10E) +ASSERT_ENUMS_MATCH(QPageSize::PageSizeId::DLE, QQuickWebEngineView::PrintedPageSizeId::DLE) +ASSERT_ENUMS_MATCH(QPageSize::PageSizeId::Folio, QQuickWebEngineView::PrintedPageSizeId::Folio) +ASSERT_ENUMS_MATCH(QPageSize::PageSizeId::Ledger, QQuickWebEngineView::PrintedPageSizeId::Ledger) +ASSERT_ENUMS_MATCH(QPageSize::PageSizeId::Tabloid, QQuickWebEngineView::PrintedPageSizeId::Tabloid) +ASSERT_ENUMS_MATCH(QPageSize::PageSizeId::Custom, QQuickWebEngineView::PrintedPageSizeId::Custom) +ASSERT_ENUMS_MATCH(QPageSize::PageSizeId::A3Extra, QQuickWebEngineView::PrintedPageSizeId::A3Extra) +ASSERT_ENUMS_MATCH(QPageSize::PageSizeId::A4Extra, QQuickWebEngineView::PrintedPageSizeId::A4Extra) +ASSERT_ENUMS_MATCH(QPageSize::PageSizeId::A4Plus, QQuickWebEngineView::PrintedPageSizeId::A4Plus) +ASSERT_ENUMS_MATCH(QPageSize::PageSizeId::A4Small, QQuickWebEngineView::PrintedPageSizeId::A4Small) +ASSERT_ENUMS_MATCH(QPageSize::PageSizeId::A5Extra, QQuickWebEngineView::PrintedPageSizeId::A5Extra) +ASSERT_ENUMS_MATCH(QPageSize::PageSizeId::B5Extra, QQuickWebEngineView::PrintedPageSizeId::B5Extra) +ASSERT_ENUMS_MATCH(QPageSize::PageSizeId::JisB0, QQuickWebEngineView::PrintedPageSizeId::JisB0) +ASSERT_ENUMS_MATCH(QPageSize::PageSizeId::JisB1, QQuickWebEngineView::PrintedPageSizeId::JisB1) +ASSERT_ENUMS_MATCH(QPageSize::PageSizeId::JisB2, QQuickWebEngineView::PrintedPageSizeId::JisB2) +ASSERT_ENUMS_MATCH(QPageSize::PageSizeId::JisB3, QQuickWebEngineView::PrintedPageSizeId::JisB3) +ASSERT_ENUMS_MATCH(QPageSize::PageSizeId::JisB4, QQuickWebEngineView::PrintedPageSizeId::JisB4) +ASSERT_ENUMS_MATCH(QPageSize::PageSizeId::JisB5, QQuickWebEngineView::PrintedPageSizeId::JisB5) +ASSERT_ENUMS_MATCH(QPageSize::PageSizeId::JisB6, QQuickWebEngineView::PrintedPageSizeId::JisB6) +ASSERT_ENUMS_MATCH(QPageSize::PageSizeId::JisB7, QQuickWebEngineView::PrintedPageSizeId::JisB7) +ASSERT_ENUMS_MATCH(QPageSize::PageSizeId::JisB8, QQuickWebEngineView::PrintedPageSizeId::JisB8) +ASSERT_ENUMS_MATCH(QPageSize::PageSizeId::JisB9, QQuickWebEngineView::PrintedPageSizeId::JisB9) +ASSERT_ENUMS_MATCH(QPageSize::PageSizeId::JisB10, QQuickWebEngineView::PrintedPageSizeId::JisB10) +ASSERT_ENUMS_MATCH(QPageSize::PageSizeId::AnsiC, QQuickWebEngineView::PrintedPageSizeId::AnsiC) +ASSERT_ENUMS_MATCH(QPageSize::PageSizeId::AnsiD, QQuickWebEngineView::PrintedPageSizeId::AnsiD) +ASSERT_ENUMS_MATCH(QPageSize::PageSizeId::AnsiE, QQuickWebEngineView::PrintedPageSizeId::AnsiE) +ASSERT_ENUMS_MATCH(QPageSize::PageSizeId::LegalExtra, QQuickWebEngineView::PrintedPageSizeId::LegalExtra) +ASSERT_ENUMS_MATCH(QPageSize::PageSizeId::LetterExtra, QQuickWebEngineView::PrintedPageSizeId::LetterExtra) +ASSERT_ENUMS_MATCH(QPageSize::PageSizeId::LetterPlus, QQuickWebEngineView::PrintedPageSizeId::LetterPlus) +ASSERT_ENUMS_MATCH(QPageSize::PageSizeId::LetterSmall, QQuickWebEngineView::PrintedPageSizeId::LetterSmall) +ASSERT_ENUMS_MATCH(QPageSize::PageSizeId::TabloidExtra, QQuickWebEngineView::PrintedPageSizeId::TabloidExtra) +ASSERT_ENUMS_MATCH(QPageSize::PageSizeId::ArchA, QQuickWebEngineView::PrintedPageSizeId::ArchA) +ASSERT_ENUMS_MATCH(QPageSize::PageSizeId::ArchB, QQuickWebEngineView::PrintedPageSizeId::ArchB) +ASSERT_ENUMS_MATCH(QPageSize::PageSizeId::ArchC, QQuickWebEngineView::PrintedPageSizeId::ArchC) +ASSERT_ENUMS_MATCH(QPageSize::PageSizeId::ArchD, QQuickWebEngineView::PrintedPageSizeId::ArchD) +ASSERT_ENUMS_MATCH(QPageSize::PageSizeId::ArchE, QQuickWebEngineView::PrintedPageSizeId::ArchE) +ASSERT_ENUMS_MATCH(QPageSize::PageSizeId::Imperial7x9, QQuickWebEngineView::PrintedPageSizeId::Imperial7x9) +ASSERT_ENUMS_MATCH(QPageSize::PageSizeId::Imperial8x10, QQuickWebEngineView::PrintedPageSizeId::Imperial8x10) +ASSERT_ENUMS_MATCH(QPageSize::PageSizeId::Imperial9x11, QQuickWebEngineView::PrintedPageSizeId::Imperial9x11) +ASSERT_ENUMS_MATCH(QPageSize::PageSizeId::Imperial9x12, QQuickWebEngineView::PrintedPageSizeId::Imperial9x12) +ASSERT_ENUMS_MATCH(QPageSize::PageSizeId::Imperial10x11, QQuickWebEngineView::PrintedPageSizeId::Imperial10x11) +ASSERT_ENUMS_MATCH(QPageSize::PageSizeId::Imperial10x13, QQuickWebEngineView::PrintedPageSizeId::Imperial10x13) +ASSERT_ENUMS_MATCH(QPageSize::PageSizeId::Imperial10x14, QQuickWebEngineView::PrintedPageSizeId::Imperial10x14) +ASSERT_ENUMS_MATCH(QPageSize::PageSizeId::Imperial12x11, QQuickWebEngineView::PrintedPageSizeId::Imperial12x11) +ASSERT_ENUMS_MATCH(QPageSize::PageSizeId::Imperial15x11, QQuickWebEngineView::PrintedPageSizeId::Imperial15x11) +ASSERT_ENUMS_MATCH(QPageSize::PageSizeId::ExecutiveStandard, QQuickWebEngineView::PrintedPageSizeId::ExecutiveStandard) +ASSERT_ENUMS_MATCH(QPageSize::PageSizeId::Note, QQuickWebEngineView::PrintedPageSizeId::Note) +ASSERT_ENUMS_MATCH(QPageSize::PageSizeId::Quarto, QQuickWebEngineView::PrintedPageSizeId::Quarto) +ASSERT_ENUMS_MATCH(QPageSize::PageSizeId::Statement, QQuickWebEngineView::PrintedPageSizeId::Statement) +ASSERT_ENUMS_MATCH(QPageSize::PageSizeId::SuperA, QQuickWebEngineView::PrintedPageSizeId::SuperA) +ASSERT_ENUMS_MATCH(QPageSize::PageSizeId::SuperB, QQuickWebEngineView::PrintedPageSizeId::SuperB) +ASSERT_ENUMS_MATCH(QPageSize::PageSizeId::Postcard, QQuickWebEngineView::PrintedPageSizeId::Postcard) +ASSERT_ENUMS_MATCH(QPageSize::PageSizeId::DoublePostcard, QQuickWebEngineView::PrintedPageSizeId::DoublePostcard) +ASSERT_ENUMS_MATCH(QPageSize::PageSizeId::Prc16K, QQuickWebEngineView::PrintedPageSizeId::Prc16K) +ASSERT_ENUMS_MATCH(QPageSize::PageSizeId::Prc32K, QQuickWebEngineView::PrintedPageSizeId::Prc32K) +ASSERT_ENUMS_MATCH(QPageSize::PageSizeId::Prc32KBig, QQuickWebEngineView::PrintedPageSizeId::Prc32KBig) +ASSERT_ENUMS_MATCH(QPageSize::PageSizeId::FanFoldUS, QQuickWebEngineView::PrintedPageSizeId::FanFoldUS) +ASSERT_ENUMS_MATCH(QPageSize::PageSizeId::FanFoldGerman, QQuickWebEngineView::PrintedPageSizeId::FanFoldGerman) +ASSERT_ENUMS_MATCH(QPageSize::PageSizeId::FanFoldGermanLegal, QQuickWebEngineView::PrintedPageSizeId::FanFoldGermanLegal) +ASSERT_ENUMS_MATCH(QPageSize::PageSizeId::EnvelopeB4, QQuickWebEngineView::PrintedPageSizeId::EnvelopeB4) +ASSERT_ENUMS_MATCH(QPageSize::PageSizeId::EnvelopeB5, QQuickWebEngineView::PrintedPageSizeId::EnvelopeB5) +ASSERT_ENUMS_MATCH(QPageSize::PageSizeId::EnvelopeB6, QQuickWebEngineView::PrintedPageSizeId::EnvelopeB6) +ASSERT_ENUMS_MATCH(QPageSize::PageSizeId::EnvelopeC0, QQuickWebEngineView::PrintedPageSizeId::EnvelopeC0) +ASSERT_ENUMS_MATCH(QPageSize::PageSizeId::EnvelopeC1, QQuickWebEngineView::PrintedPageSizeId::EnvelopeC1) +ASSERT_ENUMS_MATCH(QPageSize::PageSizeId::EnvelopeC2, QQuickWebEngineView::PrintedPageSizeId::EnvelopeC2) +ASSERT_ENUMS_MATCH(QPageSize::PageSizeId::EnvelopeC3, QQuickWebEngineView::PrintedPageSizeId::EnvelopeC3) +ASSERT_ENUMS_MATCH(QPageSize::PageSizeId::EnvelopeC4, QQuickWebEngineView::PrintedPageSizeId::EnvelopeC4) +ASSERT_ENUMS_MATCH(QPageSize::PageSizeId::EnvelopeC6, QQuickWebEngineView::PrintedPageSizeId::EnvelopeC6) +ASSERT_ENUMS_MATCH(QPageSize::PageSizeId::EnvelopeC65, QQuickWebEngineView::PrintedPageSizeId::EnvelopeC65) +ASSERT_ENUMS_MATCH(QPageSize::PageSizeId::EnvelopeC7, QQuickWebEngineView::PrintedPageSizeId::EnvelopeC7) +ASSERT_ENUMS_MATCH(QPageSize::PageSizeId::Envelope9, QQuickWebEngineView::PrintedPageSizeId::Envelope9) +ASSERT_ENUMS_MATCH(QPageSize::PageSizeId::Envelope11, QQuickWebEngineView::PrintedPageSizeId::Envelope11) +ASSERT_ENUMS_MATCH(QPageSize::PageSizeId::Envelope12, QQuickWebEngineView::PrintedPageSizeId::Envelope12) +ASSERT_ENUMS_MATCH(QPageSize::PageSizeId::Envelope14, QQuickWebEngineView::PrintedPageSizeId::Envelope14) +ASSERT_ENUMS_MATCH(QPageSize::PageSizeId::EnvelopeMonarch, QQuickWebEngineView::PrintedPageSizeId::EnvelopeMonarch) +ASSERT_ENUMS_MATCH(QPageSize::PageSizeId::EnvelopePersonal, QQuickWebEngineView::PrintedPageSizeId::EnvelopePersonal) +ASSERT_ENUMS_MATCH(QPageSize::PageSizeId::EnvelopeChou3, QQuickWebEngineView::PrintedPageSizeId::EnvelopeChou3) +ASSERT_ENUMS_MATCH(QPageSize::PageSizeId::EnvelopeChou4, QQuickWebEngineView::PrintedPageSizeId::EnvelopeChou4) +ASSERT_ENUMS_MATCH(QPageSize::PageSizeId::EnvelopeInvite, QQuickWebEngineView::PrintedPageSizeId::EnvelopeInvite) +ASSERT_ENUMS_MATCH(QPageSize::PageSizeId::EnvelopeItalian, QQuickWebEngineView::PrintedPageSizeId::EnvelopeItalian) +ASSERT_ENUMS_MATCH(QPageSize::PageSizeId::EnvelopeKaku2, QQuickWebEngineView::PrintedPageSizeId::EnvelopeKaku2) +ASSERT_ENUMS_MATCH(QPageSize::PageSizeId::EnvelopeKaku3, QQuickWebEngineView::PrintedPageSizeId::EnvelopeKaku3) +ASSERT_ENUMS_MATCH(QPageSize::PageSizeId::EnvelopePrc1, QQuickWebEngineView::PrintedPageSizeId::EnvelopePrc1) +ASSERT_ENUMS_MATCH(QPageSize::PageSizeId::EnvelopePrc2, QQuickWebEngineView::PrintedPageSizeId::EnvelopePrc2) +ASSERT_ENUMS_MATCH(QPageSize::PageSizeId::EnvelopePrc3, QQuickWebEngineView::PrintedPageSizeId::EnvelopePrc3) +ASSERT_ENUMS_MATCH(QPageSize::PageSizeId::EnvelopePrc4, QQuickWebEngineView::PrintedPageSizeId::EnvelopePrc4) +ASSERT_ENUMS_MATCH(QPageSize::PageSizeId::EnvelopePrc5, QQuickWebEngineView::PrintedPageSizeId::EnvelopePrc5) +ASSERT_ENUMS_MATCH(QPageSize::PageSizeId::EnvelopePrc6, QQuickWebEngineView::PrintedPageSizeId::EnvelopePrc6) +ASSERT_ENUMS_MATCH(QPageSize::PageSizeId::EnvelopePrc7, QQuickWebEngineView::PrintedPageSizeId::EnvelopePrc7) +ASSERT_ENUMS_MATCH(QPageSize::PageSizeId::EnvelopePrc8, QQuickWebEngineView::PrintedPageSizeId::EnvelopePrc8) +ASSERT_ENUMS_MATCH(QPageSize::PageSizeId::EnvelopePrc9, QQuickWebEngineView::PrintedPageSizeId::EnvelopePrc9) +ASSERT_ENUMS_MATCH(QPageSize::PageSizeId::EnvelopePrc10, QQuickWebEngineView::PrintedPageSizeId::EnvelopePrc10) +ASSERT_ENUMS_MATCH(QPageSize::PageSizeId::EnvelopeYou4, QQuickWebEngineView::PrintedPageSizeId::EnvelopeYou4) +ASSERT_ENUMS_MATCH(QPageSize::PageSizeId::LastPageSize, QQuickWebEngineView::PrintedPageSizeId::LastPageSize) +ASSERT_ENUMS_MATCH(QPageSize::PageSizeId::AnsiA, QQuickWebEngineView::PrintedPageSizeId::AnsiA) +ASSERT_ENUMS_MATCH(QPageSize::PageSizeId::AnsiB, QQuickWebEngineView::PrintedPageSizeId::AnsiB) +ASSERT_ENUMS_MATCH(QPageSize::PageSizeId::EnvelopeC5, QQuickWebEngineView::PrintedPageSizeId::EnvelopeC5) +ASSERT_ENUMS_MATCH(QPageSize::PageSizeId::EnvelopeDL, QQuickWebEngineView::PrintedPageSizeId::EnvelopeDL) +ASSERT_ENUMS_MATCH(QPageSize::PageSizeId::Envelope10, QQuickWebEngineView::PrintedPageSizeId::Envelope10) +#endif + +class WebEngineQuickWidgetDelegate : public QtWebEngineCore::WidgetDelegate +{ +public: + WebEngineQuickWidgetDelegate(QtWebEngineCore::RenderWidgetHostViewQtDelegateItem *item, QQuickWebEngineView *parent) + : m_contentItem(item) + , m_parentView(parent) + { + } + + ~WebEngineQuickWidgetDelegate() override + { + if (m_contentItem) + m_contentItem->setWidgetDelegate(nullptr); + } + + void InitAsPopup(const QRect &screenRect) override + { + Q_UNUSED(screenRect); + Q_UNREACHABLE(); + } + + void Bind(WebContentsAdapterClient *client) override + { + QQuickWebEngineViewPrivate::bindViewAndDelegateItem( + static_cast<QQuickWebEngineViewPrivate *>(client), m_contentItem); + } + + void Unbind() override + { + QQuickWebEngineViewPrivate::bindViewAndDelegateItem(nullptr, m_contentItem); + } + + void Destroy() override + { + delete this; + } + + bool ActiveFocusOnPress() override + { + return m_parentView->property("activeFocusOnPress").toBool() || m_parentView->hasActiveFocus(); + } + +private: + QPointer<RenderWidgetHostViewQtDelegateItem> m_contentItem; // deleted by core + QPointer<QQuickWebEngineView> m_parentView; +}; + +#if QT_CONFIG(accessibility) +static QAccessibleInterface *webAccessibleFactory(const QString &, QObject *object) +{ + if (QQuickWebEngineView *v = qobject_cast<QQuickWebEngineView*>(object)) + return new QQuickWebEngineViewAccessible(v); + return nullptr; +} +#endif // QT_CONFIG(accessibility) + +static QLatin1String defaultMimeType("text/html;charset=UTF-8"); + +QQuickWebEngineViewPrivate::QQuickWebEngineViewPrivate() + : m_profile(nullptr) + , adapter(QSharedPointer<WebContentsAdapter>::create()) + , m_history(new QWebEngineHistory(new QWebEngineHistoryPrivate(this, [] (const QUrl &url) { + return QQuickWebEngineFaviconProvider::faviconProviderUrl(url); + }))) + , contextMenuExtraItems(nullptr) + , loadProgress(0) + , m_fullscreenMode(false) + , isLoading(false) + , m_activeFocusOnPress(true) + , m_webChannel(nullptr) + , m_webChannelWorld(0) + , m_defaultAudioMuted(false) + , m_isBeingAdopted(false) + , m_backgroundColor(Qt::white) + , m_zoomFactor(1.0) + , m_profileInitialized(false) + , m_contextMenuRequest(nullptr) + , m_touchHandleDelegate(nullptr) +{ + memset(actions, 0, sizeof(actions)); + +#if QT_CONFIG(accessibility) + QAccessible::installFactory(&webAccessibleFactory); +#endif // QT_CONFIG(accessibility) +} + +QQuickWebEngineViewPrivate::~QQuickWebEngineViewPrivate() +{ + Q_ASSERT(m_profileInitialized); + m_profile->d_ptr->removeWebContentsAdapterClient(this); + FaviconProviderHelper::instance()->detach(q_ptr); + bindViewAndDelegateItem(this, nullptr); +} + +void QQuickWebEngineViewPrivate::initializeProfile() +{ + if (!m_profileInitialized) { + Q_ASSERT(!adapter->isInitialized()); + m_profileInitialized = true; + + if (!m_profile) { + m_profile = QQuickWebEngineProfile::defaultProfile(); + + // MEMO first ever call to default profile will create one without context + // it needs something to get qml engine from (and view is created in qml land) + m_profile->ensureQmlContext(q_ptr); + } + + m_profile->d_ptr->addWebContentsAdapterClient(this); + m_settings.reset(new QQuickWebEngineSettings(m_profile->settings())); + adapter->setClient(this); + } +} + +bool QQuickWebEngineViewPrivate::profileInitialized() const +{ + return m_profileInitialized; +} + +void QQuickWebEngineViewPrivate::releaseProfile() +{ + // The profile for this web contents is about to be + // garbage collected, delete WebContents first and + // let the QQuickWebEngineView be collected later by gc. + bindViewAndDelegateItem(this, nullptr); + q_ptr->d_ptr.reset(); +} + +UIDelegatesManager *QQuickWebEngineViewPrivate::ui() +{ + Q_Q(QQuickWebEngineView); + if (m_uIDelegatesManager.isNull()) + m_uIDelegatesManager.reset(new UIDelegatesManager(q)); + return m_uIDelegatesManager.data(); +} + +RenderWidgetHostViewQtDelegate *QQuickWebEngineViewPrivate::CreateRenderWidgetHostViewQtDelegate(RenderWidgetHostViewQtDelegateClient *client) +{ + Q_Q(QQuickWebEngineView); + auto *item = new RenderWidgetHostViewQtDelegateItem(client, /*isPopup = */ false); + item->setWidgetDelegate(new WebEngineQuickWidgetDelegate(item, q)); + return item; +} + +RenderWidgetHostViewQtDelegate *QQuickWebEngineViewPrivate::CreateRenderWidgetHostViewQtDelegateForPopup(RenderWidgetHostViewQtDelegateClient *client) +{ + Q_Q(QQuickWebEngineView); + const bool hasWindowCapability = QGuiApplicationPrivate::platformIntegration()->hasCapability(QPlatformIntegration::MultipleWindows); + RenderWidgetHostViewQtDelegateItem *quickDelegate = new RenderWidgetHostViewQtDelegateItem(client, /*isPopup = */ true); + if (hasWindowCapability) { + RenderWidgetHostViewQtDelegateQuickWindow *wrapperWindow = + new RenderWidgetHostViewQtDelegateQuickWindow(quickDelegate, q->window()); + quickDelegate->setWidgetDelegate(wrapperWindow); + wrapperWindow->setVirtualParent(q); + return quickDelegate; + } + quickDelegate->setParentItem(q); + quickDelegate->setWidgetDelegate(new WebEngineQuickWidgetDelegate(quickDelegate, q)); + quickDelegate->show(); + return quickDelegate; +} + +void QQuickWebEngineViewPrivate::contextMenuRequested(QWebEngineContextMenuRequest *request) +{ + Q_Q(QQuickWebEngineView); + + m_contextMenuRequest = request; + + QQmlEngine *engine = qmlEngine(q); + + // TODO: this is a workaround for QTBUG-65044 + if (!engine) + return; + + // mark the object for gc by creating temporary jsvalue + // FIXME: we most likely do not need to make any copy here + auto *r = new QWebEngineContextMenuRequest( + new QWebEngineContextMenuRequestPrivate(*request->d.data())); + engine->newQObject(r); + Q_EMIT q->contextMenuRequested(r); + + if (r->isAccepted()) + return; + + // Assign the WebEngineView as the parent of the menu, so mouse events are properly propagated + // on OSX. + QObject *menu = ui()->addMenu(q, QString(), r->position()); + if (!menu) + return; + + QQuickContextMenuBuilder contextMenuBuilder(r, q, menu); + + // Populate our menu + contextMenuBuilder.initMenu(); + + // FIXME: expose the context menu data as an attached property to make this more useful + if (contextMenuExtraItems) + contextMenuBuilder.appendExtraItems(engine); + + // Now fire the popup() method on the top level menu + ui()->showMenu(menu); +} + +void QQuickWebEngineViewPrivate::navigationRequested(int navigationType, const QUrl &url, bool &accepted, bool isMainFrame, bool hasFrameData) +{ + Q_Q(QQuickWebEngineView); + auto request = new QWebEngineNavigationRequest(url, static_cast<QWebEngineNavigationRequest::NavigationType>(navigationType), isMainFrame, hasFrameData); + qmlEngine(q)->newQObject(request); + Q_EMIT q->navigationRequested(request); + + accepted = request->isAccepted(); + if (accepted && adapter->findTextHelper()->isFindTextInProgress()) + adapter->findTextHelper()->stopFinding(); +} + +void QQuickWebEngineViewPrivate::javascriptDialog(QSharedPointer<JavaScriptDialogController> dialog) +{ + Q_Q(QQuickWebEngineView); + QQuickWebEngineJavaScriptDialogRequest *request = new QQuickWebEngineJavaScriptDialogRequest(dialog); + // mark the object for gc by creating temporary jsvalue + qmlEngine(q)->newQObject(request); + Q_EMIT q->javaScriptDialogRequested(request); + if (!request->isAccepted()) + ui()->showDialog(dialog); +} + +void QQuickWebEngineViewPrivate::allowCertificateError(const QWebEngineCertificateError &error) +{ + Q_Q(QQuickWebEngineView); + Q_EMIT q->certificateError(error); +} + +void QQuickWebEngineViewPrivate::selectClientCert( + const QSharedPointer<QtWebEngineCore::ClientCertSelectController> &controller) +{ + Q_Q(QQuickWebEngineView); + QQuickWebEngineClientCertificateSelection *certSelection = new QQuickWebEngineClientCertificateSelection(controller); + // mark the object for gc by creating temporary jsvalue + qmlEngine(q)->newQObject(certSelection); + Q_EMIT q->selectClientCertificate(certSelection); +} + +static QQuickWebEngineView::Feature toFeature(QtWebEngineCore::ProfileAdapter::PermissionType type) +{ + switch (type) { + case QtWebEngineCore::ProfileAdapter::NotificationPermission: + return QQuickWebEngineView::Notifications; + case QtWebEngineCore::ProfileAdapter::GeolocationPermission: + return QQuickWebEngineView::Geolocation; + case QtWebEngineCore::ProfileAdapter::ClipboardReadWrite: + return QQuickWebEngineView::ClipboardReadWrite; + case QtWebEngineCore::ProfileAdapter::LocalFontsPermission: + return QQuickWebEngineView::LocalFontsAccess; + default: + break; + } + Q_UNREACHABLE(); + return QQuickWebEngineView::Feature(-1); +} + + +void QQuickWebEngineViewPrivate::runFeaturePermissionRequest(QtWebEngineCore::ProfileAdapter::PermissionType permission, const QUrl &url) +{ + Q_Q(QQuickWebEngineView); + Q_EMIT q->featurePermissionRequested(url, toFeature(permission)); +} + +void QQuickWebEngineViewPrivate::showColorDialog(QSharedPointer<ColorChooserController> controller) +{ + Q_Q(QQuickWebEngineView); + QQuickWebEngineColorDialogRequest *request = new QQuickWebEngineColorDialogRequest(controller); + // mark the object for gc by creating temporary jsvalue + qmlEngine(q)->newQObject(request); + Q_EMIT q->colorDialogRequested(request); + if (!request->isAccepted()) + ui()->showColorDialog(controller); +} + +void QQuickWebEngineViewPrivate::runFileChooser(QSharedPointer<FilePickerController> controller) +{ + Q_Q(QQuickWebEngineView); + QQuickWebEngineFileDialogRequest *request = new QQuickWebEngineFileDialogRequest(controller); + // mark the object for gc by creating temporary jsvalue + qmlEngine(q)->newQObject(request); + Q_EMIT q->fileDialogRequested(request); + if (!request->isAccepted()) + ui()->showFilePicker(controller); +} + +bool QQuickWebEngineViewPrivate::passOnFocus(bool reverse) +{ + Q_Q(QQuickWebEngineView); + // The child delegate currently has focus, find the next one from there and give it focus. + QQuickItem *next = q->scopedFocusItem()->nextItemInFocusChain(!reverse); + if (next) { + next->forceActiveFocus(reverse ? Qt::BacktabFocusReason : Qt::TabFocusReason); + return true; + } + return false; +} + +void QQuickWebEngineViewPrivate::titleChanged(const QString &title) +{ + Q_Q(QQuickWebEngineView); + Q_UNUSED(title); + Q_EMIT q->titleChanged(); +} + +void QQuickWebEngineViewPrivate::urlChanged() +{ + Q_Q(QQuickWebEngineView); + QUrl url = adapter->activeUrl(); + if (m_url != url) { + m_url = url; + Q_EMIT q->urlChanged(); + } +} + +void QQuickWebEngineViewPrivate::iconChanged(const QUrl &url) +{ + Q_Q(QQuickWebEngineView); + + if (iconUrl == QQuickWebEngineFaviconProvider::faviconProviderUrl(url)) + return; + + iconUrl = QQuickWebEngineFaviconProvider::faviconProviderUrl(url); + m_history->reset(); + QTimer::singleShot(0, q, &QQuickWebEngineView::iconChanged); +} + +void QQuickWebEngineViewPrivate::loadProgressChanged(int progress) +{ + Q_Q(QQuickWebEngineView); + loadProgress = progress; + QTimer::singleShot(0, q, &QQuickWebEngineView::loadProgressChanged); +} + +void QQuickWebEngineViewPrivate::didUpdateTargetURL(const QUrl &hoveredUrl) +{ + Q_Q(QQuickWebEngineView); + Q_EMIT q->linkHovered(hoveredUrl); +} + +void QQuickWebEngineViewPrivate::selectionChanged() +{ + updateEditActions(); +} + +void QQuickWebEngineViewPrivate::zoomUpdateIsNeeded() +{ + Q_Q(QQuickWebEngineView); + q->setZoomFactor(m_zoomFactor); +} + +void QQuickWebEngineViewPrivate::recentlyAudibleChanged(bool recentlyAudible) +{ + Q_Q(QQuickWebEngineView); + Q_EMIT q->recentlyAudibleChanged(recentlyAudible); +} + +void QQuickWebEngineViewPrivate::renderProcessPidChanged(qint64 pid) +{ + Q_Q(QQuickWebEngineView); + Q_EMIT q->renderProcessPidChanged(pid); +} + +QRectF QQuickWebEngineViewPrivate::viewportRect() const +{ + Q_Q(const QQuickWebEngineView); + return QRectF(q->x(), q->y(), q->width(), q->height()); +} + +QColor QQuickWebEngineViewPrivate::backgroundColor() const +{ + return m_backgroundColor; +} + +void QQuickWebEngineViewPrivate::loadStarted(QWebEngineLoadingInfo info) +{ + Q_Q(QQuickWebEngineView); + isLoading = true; + m_history->reset(); + QTimer::singleShot(0, q, [q, info] () { + emit q->loadingChanged(info); + }); +} + +void QQuickWebEngineViewPrivate::loadCommitted() +{ + m_history->reset(); +} + +void QQuickWebEngineViewPrivate::loadFinished(QWebEngineLoadingInfo info) +{ + Q_Q(QQuickWebEngineView); + isLoading = false; + m_history->reset(); + QTimer::singleShot(0, q, [q, info] () { + emit q->loadingChanged(info); + }); + return; +} + +void QQuickWebEngineViewPrivate::focusContainer() +{ + Q_Q(QQuickWebEngineView); + QQuickWindow *window = q->window(); + if (window) + window->requestActivate(); + q->forceActiveFocus(); +} + +void QQuickWebEngineViewPrivate::unhandledKeyEvent(QKeyEvent *event) +{ + Q_Q(QQuickWebEngineView); + if (q->parentItem()) + QCoreApplication::sendEvent(q->parentItem(), event); +} + +static QWebEngineNewWindowRequest::DestinationType toDestinationType(WebContentsAdapterClient::WindowOpenDisposition disposition) +{ + switch (disposition) { + case WebContentsAdapterClient::NewForegroundTabDisposition: + return QWebEngineNewWindowRequest::InNewTab; + case WebContentsAdapterClient::NewBackgroundTabDisposition: + return QWebEngineNewWindowRequest::InNewBackgroundTab; + case WebContentsAdapterClient::NewPopupDisposition: + return QWebEngineNewWindowRequest::InNewDialog; + case WebContentsAdapterClient::NewWindowDisposition: + return QWebEngineNewWindowRequest::InNewWindow; + default: + Q_UNREACHABLE(); + } +} + +QSharedPointer<WebContentsAdapter> +QQuickWebEngineViewPrivate::adoptNewWindow(QSharedPointer<WebContentsAdapter> newWebContents, + WindowOpenDisposition disposition, bool userGesture, + const QRect &geometry, const QUrl &targetUrl) +{ + Q_Q(QQuickWebEngineView); + Q_ASSERT(newWebContents); + QQuickWebEngineNewWindowRequest request(toDestinationType(disposition), geometry, + targetUrl, userGesture, newWebContents); + + Q_EMIT q->newWindowRequested(&request); + + if (request.d_ptr->isRequestHandled) + return newWebContents; + return nullptr; +} + +bool QQuickWebEngineViewPrivate::isBeingAdopted() +{ + return false; +} + +void QQuickWebEngineViewPrivate::close() +{ + Q_Q(QQuickWebEngineView); + emit q->windowCloseRequested(); +} + +void QQuickWebEngineViewPrivate::windowCloseRejected() +{ + Q_Q(QQuickWebEngineView); + + if (Q_UNLIKELY(q->metaObject()->indexOfMethod("windowCloseRejected()") != -1)) + QMetaObject::invokeMethod(q, "windowCloseRejected"); +} + +void QQuickWebEngineViewPrivate::desktopMediaRequested( + QtWebEngineCore::DesktopMediaController *controller) +{ + Q_Q(QQuickWebEngineView); + QTimer::singleShot(0, q, [q, controller]() { + Q_EMIT q->desktopMediaRequested(QWebEngineDesktopMediaRequest(controller)); + }); +} + +void QQuickWebEngineViewPrivate::requestFullScreenMode(const QUrl &origin, bool fullscreen) +{ + Q_Q(QQuickWebEngineView); + QWebEngineFullScreenRequest request(origin, fullscreen, [q = QPointer(q)] (bool toggleOn) { if (q) q->d_ptr->setFullScreenMode(toggleOn); }); + Q_EMIT q->fullScreenRequested(request); +} + +bool QQuickWebEngineViewPrivate::isFullScreenMode() const +{ + return m_fullscreenMode; +} + +void QQuickWebEngineViewPrivate::javaScriptConsoleMessage(JavaScriptConsoleMessageLevel level, const QString& message, int lineNumber, const QString& sourceID) +{ + Q_Q(QQuickWebEngineView); + if (q->receivers(SIGNAL(javaScriptConsoleMessage(QQuickWebEngineView::JavaScriptConsoleMessageLevel,QString,int,QString))) > 0) { + Q_EMIT q->javaScriptConsoleMessage(static_cast<QQuickWebEngineView::JavaScriptConsoleMessageLevel>(level), message, lineNumber, sourceID); + return; + } + + static QLoggingCategory loggingCategory("js", QtWarningMsg); + const QByteArray file = sourceID.toUtf8(); + QMessageLogger logger(file.constData(), lineNumber, nullptr, loggingCategory.categoryName()); + + switch (level) { + case JavaScriptConsoleMessageLevel::Info: + if (loggingCategory.isInfoEnabled()) + logger.info().noquote() << message; + break; + case JavaScriptConsoleMessageLevel::Warning: + if (loggingCategory.isWarningEnabled()) + logger.warning().noquote() << message; + break; + case JavaScriptConsoleMessageLevel::Error: + if (loggingCategory.isCriticalEnabled()) + logger.critical().noquote() << message; + break; + } +} + +void QQuickWebEngineViewPrivate::authenticationRequired(QSharedPointer<AuthenticationDialogController> controller) +{ + Q_Q(QQuickWebEngineView); + QQuickWebEngineAuthenticationDialogRequest *request = new QQuickWebEngineAuthenticationDialogRequest(controller); + // mark the object for gc by creating temporary jsvalue + qmlEngine(q)->newQObject(request); + Q_EMIT q->authenticationDialogRequested(request); + if (!request->isAccepted()) + ui()->showDialog(controller); +} + +void QQuickWebEngineViewPrivate::runMediaAccessPermissionRequest(const QUrl &securityOrigin, WebContentsAdapterClient::MediaRequestFlags requestFlags) +{ + Q_Q(QQuickWebEngineView); + if (!requestFlags) + return; + QQuickWebEngineView::Feature feature; + if (requestFlags.testFlag(WebContentsAdapterClient::MediaAudioCapture) && requestFlags.testFlag(WebContentsAdapterClient::MediaVideoCapture)) + feature = QQuickWebEngineView::MediaAudioVideoCapture; + else if (requestFlags.testFlag(WebContentsAdapterClient::MediaAudioCapture)) + feature = QQuickWebEngineView::MediaAudioCapture; + else if (requestFlags.testFlag(WebContentsAdapterClient::MediaVideoCapture)) + feature = QQuickWebEngineView::MediaVideoCapture; + else if (requestFlags.testFlag(WebContentsAdapterClient::MediaDesktopAudioCapture) && + requestFlags.testFlag(WebContentsAdapterClient::MediaDesktopVideoCapture)) + feature = QQuickWebEngineView::DesktopAudioVideoCapture; + else // if (requestFlags.testFlag(WebContentsAdapterClient::MediaDesktopVideoCapture)) + feature = QQuickWebEngineView::DesktopVideoCapture; + Q_EMIT q->featurePermissionRequested(securityOrigin, feature); +} + +void QQuickWebEngineViewPrivate::runMouseLockPermissionRequest(const QUrl &securityOrigin) +{ + // TODO: Add mouse lock support + adapter->grantMouseLockPermission(securityOrigin, false); +} + +void QQuickWebEngineViewPrivate::runRegisterProtocolHandlerRequest(QWebEngineRegisterProtocolHandlerRequest request) +{ + Q_Q(QQuickWebEngineView); + Q_EMIT q->registerProtocolHandlerRequested(request); +} + +void QQuickWebEngineViewPrivate::runFileSystemAccessRequest( + QWebEngineFileSystemAccessRequest request) +{ + Q_Q(QQuickWebEngineView); + Q_EMIT q->fileSystemAccessRequested(request); +} + +QObject *QQuickWebEngineViewPrivate::accessibilityParentObject() +{ + Q_Q(QQuickWebEngineView); + return q; +} + +ProfileAdapter *QQuickWebEngineViewPrivate::profileAdapter() +{ + return m_profile->d_ptr->profileAdapter(); +} + +WebContentsAdapter *QQuickWebEngineViewPrivate::webContentsAdapter() +{ + return adapter.data(); +} + +void QQuickWebEngineViewPrivate::printRequested() +{ + Q_Q(QQuickWebEngineView); + QTimer::singleShot(0, q, [q]() { + Q_EMIT q->printRequested(); + }); +} + +void QQuickWebEngineViewPrivate::findTextFinished(const QWebEngineFindTextResult &result) +{ + Q_Q(QQuickWebEngineView); + Q_EMIT q->findTextFinished(result); +} + +void QQuickWebEngineViewPrivate::showAutofillPopup( + QtWebEngineCore::AutofillPopupController *controller, const QRect &bounds, + bool autoselectFirstSuggestion) +{ + ui()->showAutofillPopup(controller, bounds.bottomLeft(), bounds.width() + 2, + autoselectFirstSuggestion); +} + +void QQuickWebEngineViewPrivate::hideAutofillPopup() +{ + ui()->hideAutofillPopup(); +} + +QWebEngineSettings *QQuickWebEngineViewPrivate::webEngineSettings() const +{ + return m_settings->d_ptr.data(); +} + +const QObject *QQuickWebEngineViewPrivate::holdingQObject() const +{ + Q_Q(const QQuickWebEngineView); + return q; +} + +void QQuickWebEngineViewPrivate::lifecycleStateChanged(LifecycleState state) +{ + Q_Q(QQuickWebEngineView); + Q_EMIT q->lifecycleStateChanged(static_cast<QQuickWebEngineView::LifecycleState>(state)); +} + +void QQuickWebEngineViewPrivate::recommendedStateChanged(LifecycleState state) +{ + Q_Q(QQuickWebEngineView); + QTimer::singleShot(0, q, [q, state]() { + Q_EMIT q->recommendedStateChanged(static_cast<QQuickWebEngineView::LifecycleState>(state)); + }); +} + +void QQuickWebEngineViewPrivate::visibleChanged(bool visible) +{ + Q_UNUSED(visible); +} + +class WebContentsAdapterOwner : public QObject +{ +public: + typedef QSharedPointer<QtWebEngineCore::WebContentsAdapter> AdapterPtr; + WebContentsAdapterOwner(const AdapterPtr &ptr) + : adapter(ptr) + {} + +private: + AdapterPtr adapter; +}; + +bool QQuickWebEngineViewPrivate::adoptWebContents(WebContentsAdapter *webContents) +{ + Q_ASSERT(webContents); + if (webContents->profileAdapter() && profileAdapter() != webContents->profileAdapter()) { + qWarning("Can not adopt content from a different WebEngineProfile."); + return false; + } + + m_isBeingAdopted = true; + + // This throws away the WebContentsAdapter that has been used until now. + // All its states, particularly the loading URL, are replaced by the adopted WebContentsAdapter. + WebContentsAdapterOwner *adapterOwner = new WebContentsAdapterOwner(adapter->sharedFromThis()); + adapterOwner->deleteLater(); + + adapter = webContents->sharedFromThis(); + adapter->setClient(this); + return true; +} + +QQuickWebEngineView::QQuickWebEngineView(QQuickItem *parent) + : QQuickItem(parent) + , d_ptr(new QQuickWebEngineViewPrivate) +{ + Q_D(QQuickWebEngineView); + d->q_ptr = this; + this->setActiveFocusOnTab(true); + this->setFlags(QQuickItem::ItemIsFocusScope | QQuickItem::ItemAcceptsDrops); + + connect(action(WebAction::Back), &QQuickWebEngineAction::enabledChanged, + this, &QQuickWebEngineView::canGoBackChanged); + connect(action(WebAction::Forward), &QQuickWebEngineAction::enabledChanged, + this, &QQuickWebEngineView::canGoForwardChanged); +} + +QQuickWebEngineView::~QQuickWebEngineView() +{ + if (hasFocus()) + setFocus(false); +} + +void QQuickWebEngineViewPrivate::ensureContentsAdapter() +{ + initializeProfile(); + if (!adapter->isInitialized()) { + if (!m_html.isEmpty()) + adapter->setContent(m_html.toUtf8(), defaultMimeType, m_url); + else if (m_url.isValid()) + adapter->load(m_url); + else + adapter->loadDefault(); + } + + FaviconProviderHelper::instance()->attach(q_ptr); +} + +void QQuickWebEngineViewPrivate::initializationFinished() +{ + Q_Q(QQuickWebEngineView); + + Q_ASSERT(m_profileInitialized); + if (m_backgroundColor != Qt::white) { + adapter->setBackgroundColor(m_backgroundColor); + emit q->backgroundColorChanged(); + } + + // apply if it was set before first ever navigation already + q->setZoomFactor(m_zoomFactor); + +#if QT_CONFIG(webengine_webchannel) + if (m_webChannel) + adapter->setWebChannel(m_webChannel, m_webChannelWorld); +#endif + + if (m_defaultAudioMuted != adapter->isAudioMuted()) + adapter->setAudioMuted(m_defaultAudioMuted); + + if (devToolsView && devToolsView->d_ptr->adapter) + adapter->openDevToolsFrontend(devToolsView->d_ptr->adapter); + + if (m_scriptCollection) + m_scriptCollection->d->d->initializationFinished(adapter); + + if (q->window()) + adapter->setVisible(q->isVisible()); + + if (!m_isBeingAdopted) + return; + + // Ideally these would only be emitted if something actually changed. + emit q->titleChanged(); + emit q->urlChanged(); + emit q->iconChanged(); + emit q->loadingChanged(QWebEngineLoadingInfo(m_url, LoadStatus::LoadSucceededStatus)); + emit q->loadProgressChanged(); + + m_isBeingAdopted = false; +} + +void QQuickWebEngineViewPrivate::setFullScreenMode(bool fullscreen) +{ + Q_Q(QQuickWebEngineView); + if (m_fullscreenMode != fullscreen) { + m_fullscreenMode = fullscreen; + adapter->changedFullScreen(); + Q_EMIT q->isFullScreenChanged(); + } +} + +// static +void QQuickWebEngineViewPrivate::bindViewAndDelegateItem(QQuickWebEngineViewPrivate *viewPrivate, + RenderWidgetHostViewQtDelegateItem *delegateItem) +{ + auto oldDelegateItem = viewPrivate ? viewPrivate->delegateItem : nullptr; + auto oldAdapterClient = delegateItem ? delegateItem->m_adapterClient : nullptr; + + auto *oldViewPrivate = static_cast<QQuickWebEngineViewPrivate *>(oldAdapterClient); + + // Change pointers first. + + if (delegateItem && oldViewPrivate != viewPrivate) { + if (oldViewPrivate) + oldViewPrivate->delegateItem = nullptr; + delegateItem->m_adapterClient = viewPrivate; + } + + if (viewPrivate && oldDelegateItem != delegateItem) { + if (oldDelegateItem) + oldDelegateItem->m_adapterClient = nullptr; + viewPrivate->delegateItem = delegateItem; + } + + // Then notify. + + if (oldViewPrivate && oldViewPrivate != viewPrivate) + oldViewPrivate->delegateItemChanged(delegateItem, nullptr); + + if (viewPrivate && oldDelegateItem != delegateItem) + viewPrivate->delegateItemChanged(oldDelegateItem, delegateItem); +} + +void QQuickWebEngineViewPrivate::delegateItemChanged(QtWebEngineCore::RenderWidgetHostViewQtDelegateItem *oldDelegateItem, + QtWebEngineCore::RenderWidgetHostViewQtDelegateItem *newDelegateItem) +{ + Q_Q(QQuickWebEngineView); + + if (oldDelegateItem) { + oldDelegateItem->setParentItem(nullptr); +#if QT_CONFIG(accessibility) + if (!QtWebEngineCore::closingDown()) { + if (auto iface = QAccessible::queryAccessibleInterface(oldDelegateItem)) + QAccessible::deleteAccessibleInterface(QAccessible::uniqueId(iface)); + } +#endif + } + + if (newDelegateItem) { + Q_ASSERT(!QtWebEngineCore::closingDown()); +#if QT_CONFIG(accessibility) + QAccessible::registerAccessibleInterface(new QtWebEngineCore::RenderWidgetHostViewQtDelegateQuickAccessible(newDelegateItem, q)); +#endif + newDelegateItem->setParentItem(q); + newDelegateItem->setSize(q->boundingRect().size()); + // Focus on creation if the view accepts it + if (q->activeFocusOnPress()) + newDelegateItem->setFocus(true); + } +} + +void QQuickWebEngineViewPrivate::updateAction(QQuickWebEngineView::WebAction action) const +{ + QQuickWebEngineAction *a = actions[action]; + if (!a) + return; + + bool enabled = true; + + switch (action) { + case QQuickWebEngineView::Back: + enabled = adapter->canGoBack(); + break; + case QQuickWebEngineView::Forward: + enabled = adapter->canGoForward(); + break; + case QQuickWebEngineView::Stop: + enabled = isLoading; + break; + case QQuickWebEngineView::Reload: + case QQuickWebEngineView::ReloadAndBypassCache: + enabled = !isLoading; + break; + case QQuickWebEngineView::ViewSource: + enabled = adapter->canViewSource(); + break; + case QQuickWebEngineView::Cut: + case QQuickWebEngineView::Copy: + case QQuickWebEngineView::Unselect: + enabled = adapter->hasFocusedFrame() && !adapter->selectedText().isEmpty(); + break; + case QQuickWebEngineView::Paste: + case QQuickWebEngineView::Undo: + case QQuickWebEngineView::Redo: + case QQuickWebEngineView::SelectAll: + case QQuickWebEngineView::PasteAndMatchStyle: + enabled = adapter->hasFocusedFrame(); + break; + default: + break; + } + + a->d_ptr->setEnabled(enabled); +} + +void QQuickWebEngineViewPrivate::updateNavigationActions() +{ + updateAction(QQuickWebEngineView::Back); + updateAction(QQuickWebEngineView::Forward); + updateAction(QQuickWebEngineView::Stop); + updateAction(QQuickWebEngineView::Reload); + updateAction(QQuickWebEngineView::ReloadAndBypassCache); + updateAction(QQuickWebEngineView::ViewSource); +} + +void QQuickWebEngineViewPrivate::updateEditActions() +{ + updateAction(QQuickWebEngineView::Cut); + updateAction(QQuickWebEngineView::Copy); + updateAction(QQuickWebEngineView::Paste); + updateAction(QQuickWebEngineView::Undo); + updateAction(QQuickWebEngineView::Redo); + updateAction(QQuickWebEngineView::SelectAll); + updateAction(QQuickWebEngineView::PasteAndMatchStyle); + updateAction(QQuickWebEngineView::Unselect); +} + +QQuickWebEngineScriptCollection *QQuickWebEngineViewPrivate::getUserScripts() +{ + Q_Q(QQuickWebEngineView); + if (!m_scriptCollection) + m_scriptCollection.reset( + new QQuickWebEngineScriptCollection( + new QQuickWebEngineScriptCollectionPrivate( + new QWebEngineScriptCollectionPrivate( + profileAdapter()->userResourceController(), adapter)))); + + if (!m_scriptCollection->qmlEngine()) + m_scriptCollection->setQmlEngine(qmlEngine(q)); + + return m_scriptCollection.data(); +} + +QUrl QQuickWebEngineView::url() const +{ + Q_D(const QQuickWebEngineView); + return d->m_url; +} + +void QQuickWebEngineView::setUrl(const QUrl& url) +{ + Q_D(QQuickWebEngineView); + if (url.isEmpty()) + return; + + if (d->m_url != url) { + d->m_url = url; + d->m_html.clear(); + emit urlChanged(); + } + + if (d->adapter->isInitialized()) { + d->adapter->load(url); + } +} + +QUrl QQuickWebEngineView::icon() const +{ + Q_D(const QQuickWebEngineView); + return d->iconUrl; +} + +void QQuickWebEngineView::loadHtml(const QString &html, const QUrl &baseUrl) +{ + Q_D(QQuickWebEngineView); + d->m_url = baseUrl; + d->m_html = html; + if (d->adapter->isInitialized()) { + d->adapter->setContent(html.toUtf8(), defaultMimeType, baseUrl); + return; + } +} + +void QQuickWebEngineView::goBack() +{ + Q_D(QQuickWebEngineView); + d->adapter->navigateBack(); +} + +void QQuickWebEngineView::goForward() +{ + Q_D(QQuickWebEngineView); + d->adapter->navigateForward(); +} + +void QQuickWebEngineView::reload() +{ + Q_D(QQuickWebEngineView); + d->adapter->reload(); +} + +void QQuickWebEngineView::reloadAndBypassCache() +{ + Q_D(QQuickWebEngineView); + d->adapter->reloadAndBypassCache(); +} + +void QQuickWebEngineView::stop() +{ + Q_D(QQuickWebEngineView); + d->adapter->stop(); +} + +void QQuickWebEngineView::setZoomFactor(qreal arg) +{ + Q_D(QQuickWebEngineView); + if (d->adapter->isInitialized() && !qFuzzyCompare(arg, zoomFactor())) { + d->adapter->setZoomFactor(arg); + // MEMO: should reset if factor was not applied due to being invalid + d->m_zoomFactor = zoomFactor(); + emit zoomFactorChanged(d->m_zoomFactor); + } else { + d->m_zoomFactor = arg; + } +} + +QQuickWebEngineProfile *QQuickWebEngineView::profile() +{ + Q_D(QQuickWebEngineView); + d->initializeProfile(); + return d->m_profile; +} + +void QQuickWebEngineView::setProfile(QQuickWebEngineProfile *profile) +{ + Q_D(QQuickWebEngineView); + + if (d->m_profile == profile) + return; + + if (!d->profileInitialized()) { + d->m_profile = profile; + return; + } + + if (d->m_profile) + d->m_profile->d_ptr->removeWebContentsAdapterClient(d); + + d->m_profile = profile; + d->m_profile->d_ptr->addWebContentsAdapterClient(d); + d->m_settings->setParentSettings(profile->settings()); + + d->updateAdapter(); + Q_EMIT profileChanged(); +} + +QQuickWebEngineSettings *QQuickWebEngineView::settings() +{ + Q_D(QQuickWebEngineView); + d->initializeProfile(); + return d->m_settings.data(); +} + +QQuickWebEngineScriptCollection *QQuickWebEngineView::userScripts() +{ + Q_D(QQuickWebEngineView); + return d->getUserScripts(); +} + +void QQuickWebEngineViewPrivate::updateAdapter() +{ + // When the profile changes we need to create a new WebContentAdapter and reload the active URL. + bool wasInitialized = adapter->isInitialized(); + adapter = QSharedPointer<WebContentsAdapter>::create(); + adapter->setClient(this); + if (wasInitialized) { + if (!m_html.isEmpty()) + adapter->setContent(m_html.toUtf8(), defaultMimeType, m_url); + else if (m_url.isValid()) + adapter->load(m_url); + else + adapter->loadDefault(); + } +} + +bool QQuickWebEngineView::activeFocusOnPress() const +{ + Q_D(const QQuickWebEngineView); + return d->m_activeFocusOnPress; +} + +void QQuickWebEngineViewPrivate::runJavaScript( + const QString &script, quint32 worldId, + const std::function<void(const QVariant &)> &callback) +{ + ensureContentsAdapter(); + adapter->runJavaScript(script, worldId, callback); +} + +void QQuickWebEngineViewPrivate::didPrintPage(quint64 requestId, QSharedPointer<QByteArray> result) +{ + Q_Q(QQuickWebEngineView); + QJSValue callback = m_printCallbacks.take(requestId); + QJSValueList args; + args.append(qmlEngine(q)->toScriptValue(*(result.data()))); + callback.call(args); +} + +void QQuickWebEngineViewPrivate::didPrintPageToPdf(const QString &filePath, bool success) +{ + Q_Q(QQuickWebEngineView); + Q_EMIT q->pdfPrintingFinished(filePath, success); +} + +void QQuickWebEngineViewPrivate::updateScrollPosition(const QPointF &position) +{ + Q_Q(QQuickWebEngineView); + Q_EMIT q->scrollPositionChanged(position); +} + +void QQuickWebEngineViewPrivate::updateContentsSize(const QSizeF &size) +{ + Q_Q(QQuickWebEngineView); + Q_EMIT q->contentsSizeChanged(size); +} + +void QQuickWebEngineViewPrivate::renderProcessTerminated( + RenderProcessTerminationStatus terminationStatus, int exitCode) +{ + Q_Q(QQuickWebEngineView); + Q_EMIT q->renderProcessTerminated(static_cast<QQuickWebEngineView::RenderProcessTerminationStatus>( + renderProcessExitStatus(terminationStatus)), exitCode); +} + +void QQuickWebEngineViewPrivate::requestGeometryChange(const QRect &geometry, const QRect &frameGeometry) +{ + Q_Q(QQuickWebEngineView); + Q_EMIT q->geometryChangeRequested(geometry, frameGeometry); +} + +QObject *QQuickWebEngineViewPrivate::dragSource() const +{ + // QTBUG-57516 + // Fixme: This is just a band-aid workaround. +#if QT_CONFIG(draganddrop) + return QGuiApplicationPrivate::platformIntegration()->hasCapability(QPlatformIntegration::MultipleWindows) ? + q_ptr : nullptr; +#else + return nullptr; +#endif +} + +bool QQuickWebEngineViewPrivate::isEnabled() const +{ + const Q_Q(QQuickWebEngineView); + return q->isEnabled(); +} + +void QQuickWebEngineViewPrivate::setToolTip(const QString &toolTipText) +{ + Q_Q(QQuickWebEngineView); + QQuickWebEngineTooltipRequest *request = new QQuickWebEngineTooltipRequest(toolTipText, q); + // mark the object for gc by creating temporary jsvalue + qmlEngine(q)->newQObject(request); + Q_EMIT q->tooltipRequested(request); + if (!request->isAccepted()) + ui()->showToolTip(toolTipText); +} + +QtWebEngineCore::TouchHandleDrawableDelegate * +QQuickWebEngineViewPrivate::createTouchHandleDelegate(const QMap<int, QImage> &images) +{ + Q_Q(QQuickWebEngineView); + // lifecycle managed by Chromium's TouchHandleDrawable + QQuickWebEngineTouchHandle *handle = new QQuickWebEngineTouchHandle(); + if (m_touchHandleDelegate) { + QQmlContext *qmlContext = QQmlEngine::contextForObject(q); + QQmlContext *context = new QQmlContext(qmlContext, handle); + context->setContextObject(handle); + QObject *delegate = m_touchHandleDelegate->create(context); + Q_ASSERT(delegate); + QQuickItem *item = qobject_cast<QQuickItem *>(delegate); + item->setParentItem(q); + handle->setItem(item, false); + } else { + QQuickItem *item = ui()->createTouchHandle(); + Q_ASSERT(item); + QQmlEngine *engine = qmlEngine(item); + Q_ASSERT(engine); + QQuickWebEngineTouchHandleProvider *touchHandleProvider = + static_cast<QQuickWebEngineTouchHandleProvider *>( + engine->imageProvider(QQuickWebEngineTouchHandleProvider::identifier())); + Q_ASSERT(touchHandleProvider); + touchHandleProvider->init(images); + handle->setItem(item, true); + } + return handle; +} + +void QQuickWebEngineViewPrivate::showTouchSelectionMenu(QtWebEngineCore::TouchSelectionMenuController *menuController, const QRect &selectionBounds, const QSize &handleSize) +{ + Q_UNUSED(handleSize); + Q_Q(QQuickWebEngineView); + + const int kSpacingBetweenButtons = 2; + const int kMenuButtonMinWidth = 63; + const int kMenuButtonMinHeight = 38; + + QQuickWebEngineTouchSelectionMenuRequest *request = new QQuickWebEngineTouchSelectionMenuRequest( + selectionBounds, menuController); + qmlEngine(q)->newQObject(request); + Q_EMIT q->touchSelectionMenuRequested(request); + + if (request->isAccepted()) { + return; + } + + int buttonCount = menuController->buttonCount(); + if (buttonCount == 1) { + menuController->runContextMenu(); + return; + } + + int width = (kSpacingBetweenButtons * (buttonCount + 1)) + (kMenuButtonMinWidth * buttonCount); + int height = kMenuButtonMinHeight + kSpacingBetweenButtons; + int x = (selectionBounds.x() + selectionBounds.x() + selectionBounds.width() - width) / 2; + int y = selectionBounds.y() - height - 2; + + QRect bounds(x, y, width, height); + ui()->showTouchSelectionMenu(menuController, bounds, kSpacingBetweenButtons); +} + +void QQuickWebEngineViewPrivate::hideTouchSelectionMenu() +{ + ui()->hideTouchSelectionMenu(); +} + +void QQuickWebEngineViewPrivate::showWebAuthDialog(QWebEngineWebAuthUxRequest *request) +{ + Q_Q(QQuickWebEngineView); + Q_EMIT q->webAuthUxRequested(request); +} + +bool QQuickWebEngineView::isLoading() const +{ + Q_D(const QQuickWebEngineView); + return d->isLoading; +} + +int QQuickWebEngineView::loadProgress() const +{ + Q_D(const QQuickWebEngineView); + return d->loadProgress; +} + +QString QQuickWebEngineView::title() const +{ + Q_D(const QQuickWebEngineView); + return d->adapter->pageTitle(); +} + +bool QQuickWebEngineView::canGoBack() const +{ + Q_D(const QQuickWebEngineView); + return d->adapter->canGoBack(); +} + +bool QQuickWebEngineView::canGoForward() const +{ + Q_D(const QQuickWebEngineView); + return d->adapter->canGoForward(); +} + +void QQuickWebEngineView::runJavaScript(const QString &script, const QJSValue &callback) +{ + runJavaScript(script, QWebEngineScript::MainWorld, callback); +} + +void QQuickWebEngineView::runJavaScript(const QString &script, quint32 worldId, const QJSValue &callback) +{ + Q_D(QQuickWebEngineView); + std::function<void(const QVariant &)> wrappedCallback; + if (!callback.isUndefined()) { + wrappedCallback = [this, callback](const QVariant &result) { + QJSValueList args; + args.append(qmlEngine(this)->toScriptValue(result)); + callback.call(args); + }; + } + d->runJavaScript(script, worldId, wrappedCallback); +} + +qreal QQuickWebEngineView::zoomFactor() const +{ + Q_D(const QQuickWebEngineView); + if (!d->adapter->isInitialized()) + return d->m_zoomFactor; + return d->adapter->currentZoomFactor(); +} + +QColor QQuickWebEngineView::backgroundColor() const +{ + Q_D(const QQuickWebEngineView); + return d->m_backgroundColor; +} + +void QQuickWebEngineView::setBackgroundColor(const QColor &color) +{ + Q_D(QQuickWebEngineView); + if (color == d->m_backgroundColor) + return; + d->m_backgroundColor = color; + if (d->adapter->isInitialized()) { + d->adapter->setBackgroundColor(color); + emit backgroundColorChanged(); + } +} + +/*! + \property QQuickWebEngineView::audioMuted + \brief The state of whether the current page audio is muted. + \since 5.7 + + The default value is false. +*/ +bool QQuickWebEngineView::isAudioMuted() const +{ + const Q_D(QQuickWebEngineView); + if (d->adapter->isInitialized()) + return d->adapter->isAudioMuted(); + return d->m_defaultAudioMuted; +} + +void QQuickWebEngineView::setAudioMuted(bool muted) +{ + Q_D(QQuickWebEngineView); + bool wasAudioMuted = isAudioMuted(); + d->m_defaultAudioMuted = muted; + d->adapter->setAudioMuted(muted); + if (wasAudioMuted != isAudioMuted()) + Q_EMIT audioMutedChanged(muted); +} + +bool QQuickWebEngineView::recentlyAudible() const +{ + const Q_D(QQuickWebEngineView); + return d->adapter->recentlyAudible(); +} + +qint64 QQuickWebEngineView::renderProcessPid() const +{ + const Q_D(QQuickWebEngineView); + return d->adapter->renderProcessPid(); +} + +void QQuickWebEngineView::printToPdf(const QString& filePath, PrintedPageSizeId pageSizeId, PrintedPageOrientation orientation) +{ +#if QT_CONFIG(webengine_printing_and_pdf) + Q_D(QQuickWebEngineView); + QPageSize layoutSize(static_cast<QPageSize::PageSizeId>(pageSizeId)); + QPageLayout::Orientation layoutOrientation = static_cast<QPageLayout::Orientation>(orientation); + QPageLayout pageLayout(layoutSize, layoutOrientation, QMarginsF(0.0, 0.0, 0.0, 0.0)); + QPageRanges ranges; + d->ensureContentsAdapter(); + d->adapter->printToPDF(pageLayout, ranges, filePath); +#else + Q_UNUSED(filePath); + Q_UNUSED(pageSizeId); + Q_UNUSED(orientation); +#endif +} + +void QQuickWebEngineView::printToPdf(const QJSValue &callback, PrintedPageSizeId pageSizeId, PrintedPageOrientation orientation) +{ +#if QT_CONFIG(webengine_printing_and_pdf) + Q_D(QQuickWebEngineView); + QPageSize layoutSize(static_cast<QPageSize::PageSizeId>(pageSizeId)); + QPageLayout::Orientation layoutOrientation = static_cast<QPageLayout::Orientation>(orientation); + QPageLayout pageLayout(layoutSize, layoutOrientation, QMarginsF(0.0, 0.0, 0.0, 0.0)); + QPageRanges ranges; + + if (callback.isUndefined()) + return; + + d->ensureContentsAdapter(); + quint64 requestId = d->adapter->printToPDFCallbackResult(pageLayout, ranges); + d->m_printCallbacks.insert(requestId, callback); +#else + Q_UNUSED(pageSizeId); + Q_UNUSED(orientation); + + // Call back with null result. + QJSValueList args; + args.append(QJSValue(QByteArray().data())); + QJSValue callbackCopy = callback; + callbackCopy.call(args); +#endif +} + +void QQuickWebEngineView::replaceMisspelledWord(const QString &replacement) +{ + Q_D(QQuickWebEngineView); + d->adapter->replaceMisspelling(replacement); +} + +bool QQuickWebEngineView::isFullScreen() const +{ + Q_D(const QQuickWebEngineView); + return d->m_fullscreenMode; +} + +void QQuickWebEngineView::findText(const QString &subString, FindFlags options, const QJSValue &callback) +{ + Q_D(QQuickWebEngineView); + if (!d->adapter->isInitialized()) + return; + + d->adapter->findTextHelper()->startFinding(subString, options & FindCaseSensitively, options & FindBackward, callback); +} + +QWebEngineHistory *QQuickWebEngineView::history() const +{ + Q_D(const QQuickWebEngineView); + return d->m_history.data(); +} + +QQmlWebChannel *QQuickWebEngineView::webChannel() +{ +#if QT_CONFIG(webengine_webchannel) + Q_D(QQuickWebEngineView); + if (!d->m_webChannel) { + d->m_webChannel = new QQmlWebChannel(this); + } + return d->m_webChannel; +#endif + qWarning("WebEngine compiled without webchannel support"); + return nullptr; +} + +void QQuickWebEngineView::setWebChannel(QQmlWebChannel *webChannel) +{ +#if QT_CONFIG(webengine_webchannel) + Q_D(QQuickWebEngineView); + if (d->m_webChannel == webChannel) + return; + d->m_webChannel = webChannel; + if (d->profileInitialized()) + d->adapter->setWebChannel(webChannel, d->m_webChannelWorld); + Q_EMIT webChannelChanged(); +#else + Q_UNUSED(webChannel); + qWarning("WebEngine compiled without webchannel support"); +#endif +} + +uint QQuickWebEngineView::webChannelWorld() const +{ + Q_D(const QQuickWebEngineView); + return d->m_webChannelWorld; +} + +void QQuickWebEngineView::setWebChannelWorld(uint webChannelWorld) +{ +#if QT_CONFIG(webengine_webchannel) + Q_D(QQuickWebEngineView); + if (d->m_webChannelWorld == webChannelWorld) + return; + d->m_webChannelWorld = webChannelWorld; + if (d->profileInitialized()) + d->adapter->setWebChannel(d->m_webChannel, d->m_webChannelWorld); + Q_EMIT webChannelWorldChanged(webChannelWorld); +#else + Q_UNUSED(webChannelWorld); + qWarning("WebEngine compiled without webchannel support"); +#endif +} + +QQuickWebEngineView *QQuickWebEngineView::inspectedView() const +{ + Q_D(const QQuickWebEngineView); + return d->inspectedView; +} + +void QQuickWebEngineView::setInspectedView(QQuickWebEngineView *view) +{ + Q_D(QQuickWebEngineView); + if (d->inspectedView == view) + return; + QQuickWebEngineView *oldView = d->inspectedView; + d->inspectedView = nullptr; + if (oldView) + oldView->setDevToolsView(nullptr); + d->inspectedView = view; + if (view) + view->setDevToolsView(this); + Q_EMIT inspectedViewChanged(); +} + +QQuickWebEngineView *QQuickWebEngineView::devToolsView() const +{ + Q_D(const QQuickWebEngineView); + return d->devToolsView; +} + +QString QQuickWebEngineView::devToolsId() +{ + Q_D(QQuickWebEngineView); + d->ensureContentsAdapter(); + return d->adapter->devToolsId(); +} + +void QQuickWebEngineView::setDevToolsView(QQuickWebEngineView *devToolsView) +{ + Q_D(QQuickWebEngineView); + if (d->devToolsView == devToolsView) + return; + QQuickWebEngineView *oldView = d->devToolsView; + d->devToolsView = nullptr; + if (oldView) + oldView->setInspectedView(nullptr); + d->devToolsView = devToolsView; + if (devToolsView) + devToolsView->setInspectedView(this); + if (d->profileInitialized() && d->adapter->isInitialized()) { + if (devToolsView) + d->adapter->openDevToolsFrontend(devToolsView->d_ptr->adapter); + else + d->adapter->closeDevToolsFrontend(); + } + Q_EMIT devToolsViewChanged(); +} + +void QQuickWebEngineView::grantFeaturePermission(const QUrl &securityOrigin, QQuickWebEngineView::Feature feature, bool granted) +{ + if (!granted && ((feature >= MediaAudioCapture && feature <= MediaAudioVideoCapture) || + (feature >= DesktopVideoCapture && feature <= DesktopAudioVideoCapture))) { + d_ptr->adapter->grantMediaAccessPermission(securityOrigin, WebContentsAdapterClient::MediaNone); + return; + } + + switch (feature) { + case MediaAudioCapture: + d_ptr->adapter->grantMediaAccessPermission(securityOrigin, WebContentsAdapterClient::MediaAudioCapture); + break; + case MediaVideoCapture: + d_ptr->adapter->grantMediaAccessPermission(securityOrigin, WebContentsAdapterClient::MediaVideoCapture); + break; + case MediaAudioVideoCapture: + d_ptr->adapter->grantMediaAccessPermission(securityOrigin, WebContentsAdapterClient::MediaRequestFlags(WebContentsAdapterClient::MediaAudioCapture | WebContentsAdapterClient::MediaVideoCapture)); + break; + case DesktopVideoCapture: + d_ptr->adapter->grantMediaAccessPermission(securityOrigin, WebContentsAdapterClient::MediaDesktopVideoCapture); + break; + case DesktopAudioVideoCapture: + d_ptr->adapter->grantMediaAccessPermission( + securityOrigin, + WebContentsAdapterClient::MediaRequestFlags( + WebContentsAdapterClient::MediaDesktopAudioCapture | + WebContentsAdapterClient::MediaDesktopVideoCapture)); + break; + case Geolocation: + d_ptr->adapter->grantFeaturePermission(securityOrigin, ProfileAdapter::GeolocationPermission, + granted ? ProfileAdapter::AllowedPermission : ProfileAdapter::DeniedPermission); + break; + case Notifications: + d_ptr->adapter->grantFeaturePermission(securityOrigin, ProfileAdapter::NotificationPermission, + granted ? ProfileAdapter::AllowedPermission : ProfileAdapter::DeniedPermission); + break; + case ClipboardReadWrite: + d_ptr->adapter->grantFeaturePermission(securityOrigin, ProfileAdapter::ClipboardReadWrite, + granted ? ProfileAdapter::AllowedPermission + : ProfileAdapter::DeniedPermission); + break; + case LocalFontsAccess: + d_ptr->adapter->grantFeaturePermission(securityOrigin, ProfileAdapter::LocalFontsPermission, + granted ? ProfileAdapter::AllowedPermission : ProfileAdapter::DeniedPermission); + break; + default: + Q_UNREACHABLE(); + } +} + +void QQuickWebEngineView::setActiveFocusOnPress(bool arg) +{ + Q_D(QQuickWebEngineView); + if (d->m_activeFocusOnPress == arg) + return; + + d->m_activeFocusOnPress = arg; + emit activeFocusOnPressChanged(arg); +} + +void QQuickWebEngineView::goBackOrForward(int offset) +{ + Q_D(QQuickWebEngineView); + const int current = d->adapter->currentNavigationEntryIndex(); + const int count = d->adapter->navigationEntryCount(); + const int index = current + offset; + + if (index < 0 || index >= count) + return; + + d->adapter->navigateToIndex(index); +} + +void QQuickWebEngineView::fullScreenCancelled() +{ + Q_D(QQuickWebEngineView); + d->adapter->exitFullScreen(); +} + +void QQuickWebEngineView::geometryChange(const QRectF &newGeometry, const QRectF &oldGeometry) +{ + QQuickItem::geometryChange(newGeometry, oldGeometry); + Q_D(QQuickWebEngineView); + if (d->delegateItem) + d->delegateItem->setSize(newGeometry.size()); +} + +void QQuickWebEngineView::itemChange(ItemChange change, const ItemChangeData &value) +{ + Q_D(QQuickWebEngineView); + if (d && d->profileInitialized() && d->adapter->isInitialized() + && (change == ItemSceneChange || change == ItemVisibleHasChanged)) { + if (window()) + d->adapter->setVisible(isVisible()); + } + QQuickItem::itemChange(change, value); +} + +void QQuickWebEngineView::acceptAsNewWindow(QWebEngineNewWindowRequest *request) +{ + Q_D(QQuickWebEngineView); + if (!request || (!request->d_ptr->adapter && !request->requestedUrl().isValid()) + || request->d_ptr->isRequestHandled) { + qWarning("Trying to open an empty request, it was either already used or was invalidated." + "\nYou must complete the request synchronously within the newWindowRequested signal handler." + " If a view hasn't been adopted before returning, the request will be invalidated."); + return; + } + + auto adapter = request->d_ptr->adapter; + if (!adapter) + setUrl(request->requestedUrl()); + else if (!d->adoptWebContents(adapter.data())) + return; + + request->d_ptr->setHandled(); +} + +#if QT_CONFIG(draganddrop) +static QPointF mapToScreen(const QQuickItem *item, const QPointF &clientPos) +{ + return item->window()->position() + item->mapToScene(clientPos); +} + +void QQuickWebEngineView::dragEnterEvent(QDragEnterEvent *e) +{ + Q_D(QQuickWebEngineView); + e->accept(); + d->adapter->enterDrag(e, mapToScreen(this, e->position())); +} + +void QQuickWebEngineView::dragLeaveEvent(QDragLeaveEvent *e) +{ + Q_D(QQuickWebEngineView); + e->accept(); + d->adapter->leaveDrag(); +} + +void QQuickWebEngineView::dragMoveEvent(QDragMoveEvent *e) +{ + Q_D(QQuickWebEngineView); + Qt::DropAction dropAction = d->adapter->updateDragPosition(e, mapToScreen(this, e->position())); + if (Qt::IgnoreAction == dropAction) { + e->ignore(); + } else { + e->setDropAction(dropAction); + e->accept(); + } +} + +void QQuickWebEngineView::dropEvent(QDropEvent *e) +{ + Q_D(QQuickWebEngineView); + e->accept(); + d->adapter->endDragging(e, mapToScreen(this, e->position())); +} +#endif // QT_CONFIG(draganddrop) + +void QQuickWebEngineView::triggerWebAction(WebAction action) +{ + Q_D(QQuickWebEngineView); + switch (action) { + case Back: + d->adapter->navigateBack(); + break; + case Forward: + d->adapter->navigateForward(); + break; + case Stop: + d->adapter->stop(); + break; + case Reload: + d->adapter->reload(); + break; + case ReloadAndBypassCache: + d->adapter->reloadAndBypassCache(); + break; + case Cut: + d->adapter->cut(); + break; + case Copy: + d->adapter->copy(); + break; + case Paste: + d->adapter->paste(); + break; + case Undo: + d->adapter->undo(); + break; + case Redo: + d->adapter->redo(); + break; + case SelectAll: + d->adapter->selectAll(); + break; + case PasteAndMatchStyle: + d->adapter->pasteAndMatchStyle(); + break; + case Unselect: + d->adapter->unselect(); + break; + case OpenLinkInThisWindow: + if (d->m_contextMenuRequest->filteredLinkUrl().isValid()) + setUrl(d->m_contextMenuRequest->filteredLinkUrl()); + break; + case OpenLinkInNewWindow: + if (d->m_contextMenuRequest->filteredLinkUrl().isValid()) { + QQuickWebEngineNewWindowRequest request(QWebEngineNewWindowRequest::InNewWindow, QRect(), + d->m_contextMenuRequest->filteredLinkUrl(), true, nullptr); + Q_EMIT newWindowRequested(&request); + } + break; + case OpenLinkInNewTab: + if (d->m_contextMenuRequest->filteredLinkUrl().isValid()) { + QQuickWebEngineNewWindowRequest request(QWebEngineNewWindowRequest::InNewBackgroundTab, QRect(), + d->m_contextMenuRequest->filteredLinkUrl(), true, nullptr); + Q_EMIT newWindowRequested(&request); + } + break; + case CopyLinkToClipboard: + if (!d->m_contextMenuRequest->linkUrl().isEmpty()) { + QString urlString = + d->m_contextMenuRequest->linkUrl().toString(QUrl::FullyEncoded); + QString linkText = d->m_contextMenuRequest->linkText().toHtmlEscaped(); + QString title = d->m_contextMenuRequest->titleText(); + if (!title.isEmpty()) + title = QStringLiteral(" title=\"%1\"").arg(title.toHtmlEscaped()); + QMimeData *data = new QMimeData(); + data->setText(urlString); + QString html = QStringLiteral("<a href=\"") + urlString + QStringLiteral("\"") + title + QStringLiteral(">") + + linkText + QStringLiteral("</a>"); + data->setHtml(html); + data->setUrls(QList<QUrl>() << d->m_contextMenuRequest->linkUrl()); + qApp->clipboard()->setMimeData(data); + } + break; + case DownloadLinkToDisk: + if (d->m_contextMenuRequest->filteredLinkUrl().isValid()) + d->adapter->download(d->m_contextMenuRequest->filteredLinkUrl(), + d->m_contextMenuRequest->suggestedFileName(), + d->m_contextMenuRequest->referrerUrl(), + d->m_contextMenuRequest->referrerPolicy()); + break; + case CopyImageToClipboard: + if (d->m_contextMenuRequest->hasImageContent() + && (d->m_contextMenuRequest->mediaType() == QWebEngineContextMenuRequest::MediaTypeImage + || d->m_contextMenuRequest->mediaType() + == QWebEngineContextMenuRequest::MediaTypeCanvas)) { + d->adapter->copyImageAt(d->m_contextMenuRequest->position()); + } + break; + case CopyImageUrlToClipboard: + if (d->m_contextMenuRequest->mediaUrl().isValid() + && d->m_contextMenuRequest->mediaType() + == QWebEngineContextMenuRequest::MediaTypeImage) { + QString urlString = d->m_contextMenuRequest->mediaUrl().toString(QUrl::FullyEncoded); + QString alt = d->m_contextMenuRequest->altText(); + if (!alt.isEmpty()) + alt = QStringLiteral(" alt=\"%1\"").arg(alt.toHtmlEscaped()); + QString title = d->m_contextMenuRequest->titleText(); + if (!title.isEmpty()) + title = QStringLiteral(" title=\"%1\"").arg(title.toHtmlEscaped()); + QMimeData *data = new QMimeData(); + data->setText(urlString); + QString html = QStringLiteral("<img src=\"") + urlString + QStringLiteral("\"") + title + alt + QStringLiteral("></img>"); + data->setHtml(html); + data->setUrls(QList<QUrl>() << d->m_contextMenuRequest->mediaUrl()); + qApp->clipboard()->setMimeData(data); + } + break; + case DownloadImageToDisk: + case DownloadMediaToDisk: + if (d->m_contextMenuRequest->mediaUrl().isValid()) + d->adapter->download(d->m_contextMenuRequest->mediaUrl(), + d->m_contextMenuRequest->suggestedFileName(), + d->m_contextMenuRequest->referrerUrl(), + d->m_contextMenuRequest->referrerPolicy()); + break; + case CopyMediaUrlToClipboard: + if (d->m_contextMenuRequest->mediaUrl().isValid() + && (d->m_contextMenuRequest->mediaType() == QWebEngineContextMenuRequest::MediaTypeAudio + || d->m_contextMenuRequest->mediaType() + == QWebEngineContextMenuRequest::MediaTypeVideo)) { + QString urlString = d->m_contextMenuRequest->mediaUrl().toString(QUrl::FullyEncoded); + QString title = d->m_contextMenuRequest->titleText(); + if (!title.isEmpty()) + title = QStringLiteral(" title=\"%1\"").arg(title.toHtmlEscaped()); + QMimeData *data = new QMimeData(); + data->setText(urlString); + if (d->m_contextMenuRequest->mediaType() + == QWebEngineContextMenuRequest::MediaTypeAudio) + data->setHtml(QStringLiteral("<audio src=\"") + urlString + QStringLiteral("\"") + title + + QStringLiteral("></audio>")); + else + data->setHtml(QStringLiteral("<video src=\"") + urlString + QStringLiteral("\"") + title + + QStringLiteral("></video>")); + data->setUrls(QList<QUrl>() << d->m_contextMenuRequest->mediaUrl()); + qApp->clipboard()->setMimeData(data); + } + break; + case ToggleMediaControls: + if (d->m_contextMenuRequest->mediaUrl().isValid() + && d->m_contextMenuRequest->mediaFlags() + & QWebEngineContextMenuRequest::MediaCanToggleControls) { + bool enable = !(d->m_contextMenuRequest->mediaFlags() + & QWebEngineContextMenuRequest::MediaControls); + d->adapter->executeMediaPlayerActionAt(d->m_contextMenuRequest->position(), + WebContentsAdapter::MediaPlayerControls, enable); + } + break; + case ToggleMediaLoop: + if (d->m_contextMenuRequest->mediaUrl().isValid() + && (d->m_contextMenuRequest->mediaType() == QWebEngineContextMenuRequest::MediaTypeAudio + || d->m_contextMenuRequest->mediaType() + == QWebEngineContextMenuRequest::MediaTypeVideo)) { + bool enable = !(d->m_contextMenuRequest->mediaFlags() + & QWebEngineContextMenuRequest::MediaLoop); + d->adapter->executeMediaPlayerActionAt(d->m_contextMenuRequest->position(), + WebContentsAdapter::MediaPlayerLoop, enable); + } + break; + case ToggleMediaPlayPause: + if (d->m_contextMenuRequest->mediaUrl().isValid() + && (d->m_contextMenuRequest->mediaType() == QWebEngineContextMenuRequest::MediaTypeAudio + || d->m_contextMenuRequest->mediaType() + == QWebEngineContextMenuRequest::MediaTypeVideo)) { + bool enable = (d->m_contextMenuRequest->mediaFlags() + & QWebEngineContextMenuRequest::MediaPaused); + d->adapter->executeMediaPlayerActionAt(d->m_contextMenuRequest->position(), + WebContentsAdapter::MediaPlayerPlay, enable); + } + break; + case ToggleMediaMute: + if (d->m_contextMenuRequest->mediaUrl().isValid() + && d->m_contextMenuRequest->mediaFlags() + & QWebEngineContextMenuRequest::MediaHasAudio) { + bool enable = !(d->m_contextMenuRequest->mediaFlags() + & QWebEngineContextMenuRequest::MediaMuted); + d->adapter->executeMediaPlayerActionAt(d->m_contextMenuRequest->position(), + WebContentsAdapter::MediaPlayerMute, enable); + } + break; + case InspectElement: + d->adapter->inspectElementAt(d->m_contextMenuRequest->position()); + break; + case ExitFullScreen: + d->adapter->exitFullScreen(); + break; + case RequestClose: + d->adapter->requestClose(); + break; + case SavePage: + d->adapter->save(); + break; + case ViewSource: + d->adapter->viewSource(); + break; + case ToggleBold: + runJavaScript(QStringLiteral("document.execCommand('bold');"), QWebEngineScript::ApplicationWorld); + break; + case ToggleItalic: + runJavaScript(QStringLiteral("document.execCommand('italic');"), QWebEngineScript::ApplicationWorld); + break; + case ToggleUnderline: + runJavaScript(QStringLiteral("document.execCommand('underline');"), QWebEngineScript::ApplicationWorld); + break; + case ToggleStrikethrough: + runJavaScript(QStringLiteral("document.execCommand('strikethrough');"), QWebEngineScript::ApplicationWorld); + break; + case AlignLeft: + runJavaScript(QStringLiteral("document.execCommand('justifyLeft');"), QWebEngineScript::ApplicationWorld); + break; + case AlignCenter: + runJavaScript(QStringLiteral("document.execCommand('justifyCenter');"), QWebEngineScript::ApplicationWorld); + break; + case AlignRight: + runJavaScript(QStringLiteral("document.execCommand('justifyRight');"), QWebEngineScript::ApplicationWorld); + break; + case AlignJustified: + runJavaScript(QStringLiteral("document.execCommand('justifyFull');"), QWebEngineScript::ApplicationWorld); + break; + case Indent: + runJavaScript(QStringLiteral("document.execCommand('indent');"), QWebEngineScript::ApplicationWorld); + break; + case Outdent: + runJavaScript(QStringLiteral("document.execCommand('outdent');"), QWebEngineScript::ApplicationWorld); + break; + case InsertOrderedList: + runJavaScript(QStringLiteral("document.execCommand('insertOrderedList');"), QWebEngineScript::ApplicationWorld); + break; + case InsertUnorderedList: + runJavaScript(QStringLiteral("document.execCommand('insertUnorderedList');"), QWebEngineScript::ApplicationWorld); + break; + case ChangeTextDirectionLTR: + d->adapter->changeTextDirection(true /*left to right*/); + break; + case ChangeTextDirectionRTL: + d->adapter->changeTextDirection(false /*left to right*/); + break; + default: + // Reachable when a spell checker replacement word has been selected + break; + } +} + +QQuickWebEngineAction *QQuickWebEngineView::action(WebAction action) +{ + Q_D(QQuickWebEngineView); + if (action == QQuickWebEngineView::NoWebAction) + return nullptr; + if (d->actions[action]) { + d->updateAction(action); + return d->actions[action]; + } + + const QString text = QWebEnginePagePrivate::actionText(action); + QString iconName; + + switch (action) { + case Back: + iconName = QStringLiteral("go-previous"); + break; + case Forward: + iconName = QStringLiteral("go-next"); + break; + case Stop: + iconName = QStringLiteral("process-stop"); + break; + case Reload: + iconName = QStringLiteral("view-refresh"); + break; + case ReloadAndBypassCache: + iconName = QStringLiteral("view-refresh"); + break; + case Cut: + iconName = QStringLiteral("edit-cut"); + break; + case Copy: + iconName = QStringLiteral("edit-copy"); + break; + case Paste: + iconName = QStringLiteral("edit-paste"); + break; + case Undo: + iconName = QStringLiteral("edit-undo"); + break; + case Redo: + iconName = QStringLiteral("edit-redo"); + break; + case SelectAll: + iconName = QStringLiteral("edit-select-all"); + break; + case PasteAndMatchStyle: + iconName = QStringLiteral("edit-paste"); + break; + case OpenLinkInThisWindow: + case OpenLinkInNewWindow: + case OpenLinkInNewTab: + case CopyLinkToClipboard: + case DownloadLinkToDisk: + case CopyImageToClipboard: + case CopyImageUrlToClipboard: + case DownloadImageToDisk: + case CopyMediaUrlToClipboard: + case ToggleMediaControls: + case ToggleMediaLoop: + break; + case ToggleMediaPlayPause: + iconName = QStringLiteral("media-playback-start"); + break; + case ToggleMediaMute: + iconName = QStringLiteral("audio-volume-muted"); + break; + case DownloadMediaToDisk: + case InspectElement: + break; + case ExitFullScreen: + iconName = QStringLiteral("view-fullscreen"); + break; + case RequestClose: + iconName = QStringLiteral("window-close"); + break; + case Unselect: + iconName = QStringLiteral("edit-select-none"); + break; + case SavePage: + iconName = QStringLiteral("document-save"); + break; + case OpenLinkInNewBackgroundTab: + break; + case ViewSource: + break; + case ToggleBold: + iconName = QStringLiteral("format-text-bold"); + break; + case ToggleItalic: + iconName = QStringLiteral("format-text-italic"); + break; + case ToggleUnderline: + iconName = QStringLiteral("format-text-underline"); + break; + case ToggleStrikethrough: + iconName = QStringLiteral("format-text-strikethrough"); + break; + case AlignLeft: + break; + case AlignCenter: + break; + case AlignRight: + break; + case AlignJustified: + break; + case Indent: + iconName = QStringLiteral("format-indent-more"); + break; + case Outdent: + iconName = QStringLiteral("format-indent-less"); + break; + case InsertOrderedList: + case InsertUnorderedList: + case ChangeTextDirectionLTR: + case ChangeTextDirectionRTL: + break; + case NoWebAction: + case WebActionCount: + Q_UNREACHABLE(); + break; + } + + QQuickWebEngineAction *retVal = new QQuickWebEngineAction(action, text, iconName, false, this); + + d->actions[action] = retVal; + d->updateAction(action); + return retVal; +} + +QSizeF QQuickWebEngineView::contentsSize() const +{ + Q_D(const QQuickWebEngineView); + return d->adapter->lastContentsSize(); +} + +QPointF QQuickWebEngineView::scrollPosition() const +{ + Q_D(const QQuickWebEngineView); + return d->adapter->lastScrollOffset(); +} + +void QQuickWebEngineView::componentComplete() +{ + QQuickItem::componentComplete(); + Q_D(QQuickWebEngineView); + d->initializeProfile(); +#if QT_CONFIG(accessibility) + // Enable accessibility via a dynamic QQmlProperty, instead of using private API call + // QQuickAccessibleAttached::qmlAttachedProperties(this). The qmlContext is required, otherwise + // it is not possible to reference attached properties. + QQmlContext *qmlContext = QQmlEngine::contextForObject(this); + QQmlProperty role(this, QStringLiteral("Accessible.role"), qmlContext); + role.write(QAccessible::Grouping); +#endif // QT_CONFIG(accessibility) + + QTimer::singleShot(0, this, &QQuickWebEngineView::lazyInitialize); +} + +void QQuickWebEngineView::lazyInitialize() +{ + Q_D(QQuickWebEngineView); + d->ensureContentsAdapter(); +} + +QQuickWebEngineView::LifecycleState QQuickWebEngineView::lifecycleState() const +{ + Q_D(const QQuickWebEngineView); + return static_cast<LifecycleState>(d->adapter->lifecycleState()); +} + +void QQuickWebEngineView::setLifecycleState(LifecycleState state) +{ + Q_D(QQuickWebEngineView); + d->adapter->setLifecycleState(static_cast<WebContentsAdapterClient::LifecycleState>(state)); +} + +QQuickWebEngineView::LifecycleState QQuickWebEngineView::recommendedState() const +{ + Q_D(const QQuickWebEngineView); + return static_cast<LifecycleState>(d->adapter->recommendedState()); +} + +QQuickContextMenuBuilder::QQuickContextMenuBuilder(QWebEngineContextMenuRequest *request, + QQuickWebEngineView *view, QObject *menu) + : QtWebEngineCore::RenderViewContextMenuQt(request), m_view(view), m_menu(menu) +{ +} + +void QQuickContextMenuBuilder::appendExtraItems(QQmlEngine *engine) +{ + Q_UNUSED(engine); + m_view->d_ptr->ui()->addMenuSeparator(m_menu); + if (QObject *menuExtras = m_view->d_ptr->contextMenuExtraItems->create(qmlContext(m_view))) { + menuExtras->setParent(m_menu); + QQmlListReference entries(m_menu, defaultPropertyName(m_menu)); + if (entries.isValid()) + entries.append(menuExtras); + } +} + +bool QQuickContextMenuBuilder::hasInspector() +{ + return m_view->d_ptr->adapter->hasInspector(); +} + +bool QQuickContextMenuBuilder::isFullScreenMode() +{ + return m_view->d_ptr->isFullScreenMode(); +} + +void QQuickContextMenuBuilder::addMenuItem(ContextMenuItem menuItem) +{ + QQuickWebEngineAction *action = nullptr; + + switch (menuItem) { + case ContextMenuItem::Back: + action = m_view->action(QQuickWebEngineView::Back); + break; + case ContextMenuItem::Forward: + action = m_view->action(QQuickWebEngineView::Forward); + break; + case ContextMenuItem::Reload: + action = m_view->action(QQuickWebEngineView::Reload); + break; + case ContextMenuItem::Cut: + action = m_view->action(QQuickWebEngineView::Cut); + break; + case ContextMenuItem::Copy: + action = m_view->action(QQuickWebEngineView::Copy); + break; + case ContextMenuItem::Paste: + action = m_view->action(QQuickWebEngineView::Paste); + break; + case ContextMenuItem::Undo: + action = m_view->action(QQuickWebEngineView::Undo); + break; + case ContextMenuItem::Redo: + action = m_view->action(QQuickWebEngineView::Redo); + break; + case ContextMenuItem::SelectAll: + action = m_view->action(QQuickWebEngineView::SelectAll); + break; + case ContextMenuItem::PasteAndMatchStyle: + action = m_view->action(QQuickWebEngineView::PasteAndMatchStyle); + break; + case ContextMenuItem::OpenLinkInNewWindow: + action = m_view->action(QQuickWebEngineView::OpenLinkInNewWindow); + break; + case ContextMenuItem::OpenLinkInNewTab: + action = m_view->action(QQuickWebEngineView::OpenLinkInNewTab); + break; + case ContextMenuItem::CopyLinkToClipboard: + action = m_view->action(QQuickWebEngineView::CopyLinkToClipboard); + break; + case ContextMenuItem::DownloadLinkToDisk: + action = m_view->action(QQuickWebEngineView::DownloadLinkToDisk); + break; + case ContextMenuItem::CopyImageToClipboard: + action = m_view->action(QQuickWebEngineView::CopyImageToClipboard); + break; + case ContextMenuItem::CopyImageUrlToClipboard: + action = m_view->action(QQuickWebEngineView::CopyImageUrlToClipboard); + break; + case ContextMenuItem::DownloadImageToDisk: + action = m_view->action(QQuickWebEngineView::DownloadImageToDisk); + break; + case ContextMenuItem::CopyMediaUrlToClipboard: + action = m_view->action(QQuickWebEngineView::CopyMediaUrlToClipboard); + break; + case ContextMenuItem::ToggleMediaControls: + action = m_view->action(QQuickWebEngineView::ToggleMediaControls); + break; + case ContextMenuItem::ToggleMediaLoop: + action = m_view->action(QQuickWebEngineView::ToggleMediaLoop); + break; + case ContextMenuItem::DownloadMediaToDisk: + action = m_view->action(QQuickWebEngineView::DownloadMediaToDisk); + break; + case ContextMenuItem::InspectElement: + action = m_view->action(QQuickWebEngineView::InspectElement); + break; + case ContextMenuItem::ExitFullScreen: + action = m_view->action(QQuickWebEngineView::ExitFullScreen); + break; + case ContextMenuItem::SavePage: + action = m_view->action(QQuickWebEngineView::SavePage); + break; + case ContextMenuItem::ViewSource: + action = m_view->action(QQuickWebEngineView::ViewSource); + break; + case ContextMenuItem::SpellingSuggestions: + { + QPointer<QQuickWebEngineView> thisRef(m_view); + for (int i = 0; i < m_contextData->spellCheckerSuggestions().size() && i < 4; i++) { + action = new QQuickWebEngineAction(m_menu); + QString replacement = m_contextData->spellCheckerSuggestions().at(i); + QObject::connect(action, &QQuickWebEngineAction::triggered, [thisRef, replacement] { thisRef->replaceMisspelledWord(replacement); }); + action->d_ptr->m_text = replacement; + action->d_ptr->m_enabled = true; + m_view->d_ptr->ui()->addMenuItem(action, m_menu); + } + return; + } + case ContextMenuItem::Separator: + m_view->d_ptr->ui()->addMenuSeparator(m_menu); + return; + } + // Set enabled property directly with avoiding binding loops caused by its notifier signal. + action->d_ptr->m_enabled = isMenuItemEnabled(menuItem); + m_view->d_ptr->ui()->addMenuItem(action, m_menu); +} + +bool QQuickContextMenuBuilder::isMenuItemEnabled(ContextMenuItem menuItem) +{ + switch (menuItem) { + case ContextMenuItem::Back: + return m_view->canGoBack(); + case ContextMenuItem::Forward: + return m_view->canGoForward(); + case ContextMenuItem::Reload: + return true; + case ContextMenuItem::Cut: + return m_contextData->editFlags() & QWebEngineContextMenuRequest::CanCut; + case ContextMenuItem::Copy: + return m_contextData->editFlags() & QWebEngineContextMenuRequest::CanCopy; + case ContextMenuItem::Paste: + return m_contextData->editFlags() & QWebEngineContextMenuRequest::CanPaste; + case ContextMenuItem::Undo: + return m_contextData->editFlags() & QWebEngineContextMenuRequest::CanUndo; + case ContextMenuItem::Redo: + return m_contextData->editFlags() & QWebEngineContextMenuRequest::CanRedo; + case ContextMenuItem::SelectAll: + return m_contextData->editFlags() & QWebEngineContextMenuRequest::CanSelectAll; + case ContextMenuItem::PasteAndMatchStyle: + return m_contextData->editFlags() & QWebEngineContextMenuRequest::CanPaste; + case ContextMenuItem::OpenLinkInNewWindow: + case ContextMenuItem::OpenLinkInNewTab: + case ContextMenuItem::CopyLinkToClipboard: + case ContextMenuItem::DownloadLinkToDisk: + case ContextMenuItem::CopyImageToClipboard: + case ContextMenuItem::CopyImageUrlToClipboard: + case ContextMenuItem::DownloadImageToDisk: + case ContextMenuItem::CopyMediaUrlToClipboard: + case ContextMenuItem::ToggleMediaControls: + case ContextMenuItem::ToggleMediaLoop: + case ContextMenuItem::DownloadMediaToDisk: + case ContextMenuItem::InspectElement: + case ContextMenuItem::ExitFullScreen: + case ContextMenuItem::SavePage: + return true; + case ContextMenuItem::ViewSource: + return m_view->d_ptr->adapter->canViewSource(); + case ContextMenuItem::SpellingSuggestions: + case ContextMenuItem::Separator: + return true; + } + Q_UNREACHABLE(); +} + +void QQuickWebEngineView::setTouchHandleDelegate(QQmlComponent *delegate) +{ + if (d_ptr->m_touchHandleDelegate != delegate) { + d_ptr->m_touchHandleDelegate = delegate; + d_ptr->webContentsAdapter()->resetTouchSelectionController(); + emit touchHandleDelegateChanged(); + } +} + +QQmlComponent *QQuickWebEngineView::touchHandleDelegate() const +{ + return d_ptr->m_touchHandleDelegate; +} + +QWebEngineFrame QQuickWebEngineView::mainFrame() +{ + Q_D(QQuickWebEngineView); + return QWebEngineFrame(d, d->adapter->mainFrameId()); +} + +QWebEngineFrame QQuickWebEngineView::findFrameByName(const QString &name) +{ + Q_D(QQuickWebEngineView); + auto maybeId = d->adapter->findFrameIdByName(name); + return QWebEngineFrame(d, maybeId.value_or(WebContentsAdapter::kInvalidFrameId)); +} + +void QQuickWebEngineView::save(const QString &filePath, + QWebEngineDownloadRequest::SavePageFormat format) const +{ + Q_D(const QQuickWebEngineView); + d->adapter->save(filePath, format); +} + +QT_END_NAMESPACE + +#include "moc_qquickwebengineview_p.cpp" +#include "moc_qquickwebengineforeigntypes_p.cpp" diff --git a/src/webenginequick/api/qquickwebengineview_p.h b/src/webenginequick/api/qquickwebengineview_p.h new file mode 100644 index 000000000..37e39dfed --- /dev/null +++ b/src/webenginequick/api/qquickwebengineview_p.h @@ -0,0 +1,591 @@ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + +#ifndef QQUICKWEBENGINEVIEW_P_H +#define QQUICKWEBENGINEVIEW_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 <QtWebEngineCore/qtwebenginecoreglobal.h> +#include <QtWebEngineCore/qwebenginequotarequest.h> +#include <QtWebEngineCore/qwebenginedesktopmediarequest.h> +#include <QtWebEngineCore/qwebenginedownloadrequest.h> +#include <QtWebEngineCore/qwebengineframe.h> +#include <QtWebEngineQuick/private/qtwebenginequickglobal_p.h> +#include <QtGui/qcolor.h> +#include <QtQml/qqmlregistration.h> +#include <QtQuick/qquickitem.h> + +QT_BEGIN_NAMESPACE + +class QQmlWebChannel; +class QQmlComponent; +class QQuickContextMenuBuilder; +class QQuickWebEngineAction; +class QQuickWebEngineAuthenticationDialogRequest; +class QQuickWebEngineClientCertificateSelection; +class QQuickWebEngineColorDialogRequest; +class QQuickWebEngineFileDialogRequest; +class QQuickWebEngineJavaScriptDialogRequest; +class QQuickWebEngineNewWindowRequest; +class QQuickWebEngineProfile; +class QQuickWebEngineSettings; +class QQuickWebEngineTooltipRequest; +class QQuickWebEngineViewPrivate; +class QWebEngineCertificateError; +class QWebEngineContextMenuRequest; +class QWebEngineFileSystemAccessRequest; +class QWebEngineFindTextResult; +class QWebEngineFullScreenRequest; +class QWebEngineHistory; +class QWebEngineLoadingInfo; +class QWebEngineNavigationRequest; +class QWebEngineNewWindowRequest; +class QWebEngineRegisterProtocolHandlerRequest; +class QQuickWebEngineScriptCollection; +class QQuickWebEngineTouchSelectionMenuRequest; +class QWebEngineWebAuthUxRequest; + +class Q_WEBENGINEQUICK_EXPORT QQuickWebEngineView : public QQuickItem { + Q_OBJECT + Q_CLASSINFO("RegisterEnumClassesUnscoped", "false") + Q_PROPERTY(QUrl url READ url WRITE setUrl NOTIFY urlChanged FINAL) + Q_PROPERTY(QUrl icon READ icon NOTIFY iconChanged FINAL) + Q_PROPERTY(bool loading READ isLoading NOTIFY loadingChanged FINAL) + Q_PROPERTY(int loadProgress READ loadProgress NOTIFY loadProgressChanged FINAL) + Q_PROPERTY(QString title READ title NOTIFY titleChanged FINAL) + Q_PROPERTY(bool canGoBack READ canGoBack NOTIFY canGoBackChanged FINAL) + Q_PROPERTY(bool canGoForward READ canGoForward NOTIFY canGoForwardChanged FINAL) + Q_PROPERTY(bool isFullScreen READ isFullScreen NOTIFY isFullScreenChanged REVISION(1,1) FINAL) + Q_PROPERTY(qreal zoomFactor READ zoomFactor WRITE setZoomFactor NOTIFY zoomFactorChanged REVISION(1,1) FINAL) + Q_PROPERTY(QQuickWebEngineProfile *profile READ profile WRITE setProfile NOTIFY profileChanged FINAL REVISION(1,1)) + Q_PROPERTY(QQuickWebEngineSettings *settings READ settings REVISION(1,1) CONSTANT FINAL) + Q_PROPERTY(QWebEngineHistory *history READ history CONSTANT FINAL REVISION(1,1)) +#if QT_CONFIG(webengine_webchannel) + Q_PROPERTY(QQmlWebChannel *webChannel READ webChannel WRITE setWebChannel NOTIFY webChannelChanged REVISION(1,1) FINAL) +#endif + Q_PROPERTY(QQuickWebEngineScriptCollection *userScripts READ userScripts FINAL REVISION(1,1)) + Q_PROPERTY(bool activeFocusOnPress READ activeFocusOnPress WRITE setActiveFocusOnPress NOTIFY activeFocusOnPressChanged REVISION(1,2) FINAL) + Q_PROPERTY(QColor backgroundColor READ backgroundColor WRITE setBackgroundColor NOTIFY backgroundColorChanged REVISION(1,2) FINAL) + Q_PROPERTY(QSizeF contentsSize READ contentsSize NOTIFY contentsSizeChanged FINAL REVISION(1,3)) + Q_PROPERTY(QPointF scrollPosition READ scrollPosition NOTIFY scrollPositionChanged FINAL REVISION(1,3)) + Q_PROPERTY(bool audioMuted READ isAudioMuted WRITE setAudioMuted NOTIFY audioMutedChanged FINAL REVISION(1,3)) + Q_PROPERTY(bool recentlyAudible READ recentlyAudible NOTIFY recentlyAudibleChanged FINAL REVISION(1,3)) + Q_PROPERTY(uint webChannelWorld READ webChannelWorld WRITE setWebChannelWorld NOTIFY webChannelWorldChanged REVISION(1,3) FINAL) + + Q_PROPERTY(QQuickWebEngineView *inspectedView READ inspectedView WRITE setInspectedView NOTIFY inspectedViewChanged REVISION(1,7) FINAL) + Q_PROPERTY(QQuickWebEngineView *devToolsView READ devToolsView WRITE setDevToolsView NOTIFY devToolsViewChanged REVISION(1,7) FINAL) + Q_PROPERTY(QString devToolsId READ devToolsId CONSTANT REVISION(6,6) FINAL) + + Q_PROPERTY(LifecycleState lifecycleState READ lifecycleState WRITE setLifecycleState NOTIFY lifecycleStateChanged REVISION(1,10) FINAL) + Q_PROPERTY(LifecycleState recommendedState READ recommendedState NOTIFY recommendedStateChanged REVISION(1,10) FINAL) + + Q_PROPERTY(qint64 renderProcessPid READ renderProcessPid NOTIFY renderProcessPidChanged FINAL REVISION(1,11)) + Q_PROPERTY(QQmlComponent *touchHandleDelegate READ touchHandleDelegate WRITE + setTouchHandleDelegate NOTIFY touchHandleDelegateChanged REVISION(0) FINAL) + Q_PROPERTY(QWebEngineFrame mainFrame READ mainFrame FINAL REVISION(6, 8)) + QML_NAMED_ELEMENT(WebEngineView) + QML_ADDED_IN_VERSION(1, 0) + QML_EXTRA_VERSION(2, 0) + +public: + QQuickWebEngineView(QQuickItem *parent = nullptr); + ~QQuickWebEngineView(); + + QUrl url() const; + void setUrl(const QUrl&); + QUrl icon() const; + bool isLoading() const; + int loadProgress() const; + QString title() const; + bool canGoBack() const; + bool canGoForward() const; + bool isFullScreen() const; + qreal zoomFactor() const; + void setZoomFactor(qreal arg); + QColor backgroundColor() const; + void setBackgroundColor(const QColor &color); + QSizeF contentsSize() const; + QPointF scrollPosition() const; + +#if QT_DEPRECATED_SINCE(6, 2) +QT_WARNING_PUSH QT_WARNING_DISABLE_DEPRECATED + enum QT_DEPRECATED NavigationRequestAction { + AcceptRequest, + // Make room in the valid range of the enum so + // we can expose extra actions. + IgnoreRequest = 0xFF + }; + Q_ENUM(NavigationRequestAction) + + enum QT_DEPRECATED NavigationType { + LinkClickedNavigation, + TypedNavigation, + FormSubmittedNavigation, + BackForwardNavigation, + ReloadNavigation, + OtherNavigation, + RedirectNavigation, + }; + Q_ENUM(NavigationType) + + enum QT_DEPRECATED LoadStatus { + LoadStartedStatus, + LoadStoppedStatus, + LoadSucceededStatus, + LoadFailedStatus + }; + Q_ENUM(LoadStatus) + + enum QT_DEPRECATED ErrorDomain { + NoErrorDomain, + InternalErrorDomain, + ConnectionErrorDomain, + CertificateErrorDomain, + HttpErrorDomain, + FtpErrorDomain, + DnsErrorDomain + }; + Q_ENUM(ErrorDomain) + + enum QT_DEPRECATED NewViewDestination { + NewViewInWindow, + NewViewInTab, + NewViewInDialog, + NewViewInBackgroundTab + }; + Q_ENUM(NewViewDestination) +QT_WARNING_POP +#endif + + enum Feature { + MediaAudioCapture, + MediaVideoCapture, + MediaAudioVideoCapture, + Geolocation, + DesktopVideoCapture, + DesktopAudioVideoCapture, + Notifications, + ClipboardReadWrite, + LocalFontsAccess, + }; + Q_ENUM(Feature) + + enum WebAction { + NoWebAction = - 1, + Back, + Forward, + Stop, + Reload, + + Cut, + Copy, + Paste, + + Undo, + Redo, + SelectAll, + ReloadAndBypassCache, + + PasteAndMatchStyle, + + OpenLinkInThisWindow, + OpenLinkInNewWindow, + OpenLinkInNewTab, + CopyLinkToClipboard, + DownloadLinkToDisk, + + CopyImageToClipboard, + CopyImageUrlToClipboard, + DownloadImageToDisk, + + CopyMediaUrlToClipboard, + ToggleMediaControls, + ToggleMediaLoop, + ToggleMediaPlayPause, + ToggleMediaMute, + DownloadMediaToDisk, + + InspectElement, + ExitFullScreen, + RequestClose, + Unselect, + SavePage, + OpenLinkInNewBackgroundTab, // Not supported in QML + ViewSource, + + ToggleBold, + ToggleItalic, + ToggleUnderline, + ToggleStrikethrough, + + AlignLeft, + AlignCenter, + AlignRight, + AlignJustified, + Indent, + Outdent, + + InsertOrderedList, + InsertUnorderedList, + + ChangeTextDirectionLTR, + ChangeTextDirectionRTL, + + WebActionCount + }; + Q_ENUM(WebAction) + + // must match WebContentsAdapterClient::JavaScriptConsoleMessageLevel + enum JavaScriptConsoleMessageLevel { + InfoMessageLevel = 0, + WarningMessageLevel, + ErrorMessageLevel + }; + Q_ENUM(JavaScriptConsoleMessageLevel) + + // must match WebContentsAdapterClient::RenderProcessTerminationStatus + enum RenderProcessTerminationStatus { + NormalTerminationStatus = 0, + AbnormalTerminationStatus, + CrashedTerminationStatus, + KilledTerminationStatus + }; + Q_ENUM(RenderProcessTerminationStatus) + + enum FindFlag { + FindBackward = 1, + FindCaseSensitively = 2, + }; + Q_DECLARE_FLAGS(FindFlags, FindFlag) + Q_FLAG(FindFlags) + + // must match QPageSize::PageSizeId + enum PrintedPageSizeId { + // Existing Qt sizes + Letter, + Legal, + Executive, + A0, + A1, + A2, + A3, + A4, + A5, + A6, + A7, + A8, + A9, + A10, + B0, + B1, + B2, + B3, + B4, + B5, + B6, + B7, + B8, + B9, + B10, + C5E, + Comm10E, + DLE, + Folio, + Ledger, + Tabloid, + Custom, + + // New values derived from PPD standard + A3Extra, + A4Extra, + A4Plus, + A4Small, + A5Extra, + B5Extra, + + JisB0, + JisB1, + JisB2, + JisB3, + JisB4, + JisB5, + JisB6, + JisB7, + JisB8, + JisB9, + JisB10, + + // AnsiA = Letter, + // AnsiB = Ledger, + AnsiC, + AnsiD, + AnsiE, + LegalExtra, + LetterExtra, + LetterPlus, + LetterSmall, + TabloidExtra, + + ArchA, + ArchB, + ArchC, + ArchD, + ArchE, + + Imperial7x9, + Imperial8x10, + Imperial9x11, + Imperial9x12, + Imperial10x11, + Imperial10x13, + Imperial10x14, + Imperial12x11, + Imperial15x11, + + ExecutiveStandard, + Note, + Quarto, + Statement, + SuperA, + SuperB, + Postcard, + DoublePostcard, + Prc16K, + Prc32K, + Prc32KBig, + + FanFoldUS, + FanFoldGerman, + FanFoldGermanLegal, + + EnvelopeB4, + EnvelopeB5, + EnvelopeB6, + EnvelopeC0, + EnvelopeC1, + EnvelopeC2, + EnvelopeC3, + EnvelopeC4, + // EnvelopeC5 = C5E, + EnvelopeC6, + EnvelopeC65, + EnvelopeC7, + // EnvelopeDL = DLE, + + Envelope9, + // Envelope10 = Comm10E, + Envelope11, + Envelope12, + Envelope14, + EnvelopeMonarch, + EnvelopePersonal, + + EnvelopeChou3, + EnvelopeChou4, + EnvelopeInvite, + EnvelopeItalian, + EnvelopeKaku2, + EnvelopeKaku3, + EnvelopePrc1, + EnvelopePrc2, + EnvelopePrc3, + EnvelopePrc4, + EnvelopePrc5, + EnvelopePrc6, + EnvelopePrc7, + EnvelopePrc8, + EnvelopePrc9, + EnvelopePrc10, + EnvelopeYou4, + + // Last item + LastPageSize = EnvelopeYou4, + + // Convenience overloads for naming consistency + AnsiA = Letter, + AnsiB = Ledger, + EnvelopeC5 = C5E, + EnvelopeDL = DLE, + Envelope10 = Comm10E + }; + Q_ENUM(PrintedPageSizeId) + + // must match QPageLayout::Orientation + enum PrintedPageOrientation { + Portrait, + Landscape + }; + Q_ENUM(PrintedPageOrientation) + + // must match WebContentsAdapterClient::LifecycleState + enum class LifecycleState { + Active, + Frozen, + Discarded, + }; + Q_ENUM(LifecycleState) + + // QmlParserStatus + void componentComplete() override; + + QQuickWebEngineProfile *profile(); + void setProfile(QQuickWebEngineProfile *); + QQuickWebEngineScriptCollection *userScripts(); + + QQuickWebEngineSettings *settings(); + QQmlWebChannel *webChannel(); + void setWebChannel(QQmlWebChannel *); + QWebEngineHistory *history() const; + uint webChannelWorld() const; + void setWebChannelWorld(uint); + Q_REVISION(1,8) Q_INVOKABLE QQuickWebEngineAction *action(WebAction action); + + Q_INVOKABLE void acceptAsNewWindow(QWebEngineNewWindowRequest *request); + + bool isAudioMuted() const; + void setAudioMuted(bool muted); + bool recentlyAudible() const; + + qint64 renderProcessPid() const; + + bool activeFocusOnPress() const; + + void setInspectedView(QQuickWebEngineView *); + QQuickWebEngineView *inspectedView() const; + void setDevToolsView(QQuickWebEngineView *); + QQuickWebEngineView *devToolsView() const; + QString devToolsId(); + + LifecycleState lifecycleState() const; + void setLifecycleState(LifecycleState state); + + LifecycleState recommendedState() const; + + QQmlComponent *touchHandleDelegate() const; + void setTouchHandleDelegate(QQmlComponent *delegagte); + + QWebEngineFrame mainFrame(); + Q_REVISION(6, 8) Q_INVOKABLE QWebEngineFrame findFrameByName(const QString &name); + +public Q_SLOTS: + void runJavaScript(const QString&, const QJSValue & = QJSValue()); + Q_REVISION(1,3) void runJavaScript(const QString&, quint32 worldId, const QJSValue & = QJSValue()); + void loadHtml(const QString &html, const QUrl &baseUrl = QUrl()); + void goBack(); + void goForward(); + Q_REVISION(1,1) void goBackOrForward(int index); + void reload(); + Q_REVISION(1,1) void reloadAndBypassCache(); + void stop(); + Q_REVISION(1,1) void findText(const QString &subString, FindFlags options = { }, const QJSValue &callback = QJSValue()); + Q_REVISION(1,1) void fullScreenCancelled(); + Q_REVISION(1,1) void grantFeaturePermission(const QUrl &securityOrigin, QQuickWebEngineView::Feature, bool granted); + Q_REVISION(1,2) void setActiveFocusOnPress(bool arg); + Q_REVISION(1,2) void triggerWebAction(WebAction action); + Q_REVISION(1,3) void printToPdf(const QString &filePath, PrintedPageSizeId pageSizeId = PrintedPageSizeId::A4, PrintedPageOrientation orientation = PrintedPageOrientation::Portrait); + Q_REVISION(1,3) void printToPdf(const QJSValue &callback, PrintedPageSizeId pageSizeId = PrintedPageSizeId::A4, PrintedPageOrientation orientation = PrintedPageOrientation::Portrait); + Q_REVISION(1,4) void replaceMisspelledWord(const QString &replacement); + Q_REVISION(6, 6) void save(const QString &filePath, + QWebEngineDownloadRequest::SavePageFormat format = + QWebEngineDownloadRequest::MimeHtmlSaveFormat) const; + +private Q_SLOTS: + void lazyInitialize(); + +Q_SIGNALS: + void titleChanged(); + void urlChanged(); + void iconChanged(); + void loadingChanged(const QWebEngineLoadingInfo &loadingInfo); + void loadProgressChanged(); + void linkHovered(const QUrl &hoveredUrl); + void navigationRequested(QWebEngineNavigationRequest *request); + void javaScriptConsoleMessage(QQuickWebEngineView::JavaScriptConsoleMessageLevel level, + const QString &message, int lineNumber, const QString &sourceID); + Q_REVISION(1,1) void certificateError(const QWebEngineCertificateError &error); + Q_REVISION(1,1) void fullScreenRequested(const QWebEngineFullScreenRequest &request); + Q_REVISION(1,1) void isFullScreenChanged(); + Q_REVISION(1, 1) + void featurePermissionRequested(const QUrl &securityOrigin, + QQuickWebEngineView::Feature feature); + Q_REVISION(1,1) void zoomFactorChanged(qreal arg); + Q_REVISION(1,1) void profileChanged(); + Q_REVISION(1,1) void webChannelChanged(); + Q_REVISION(1,2) void activeFocusOnPressChanged(bool); + Q_REVISION(1,2) void backgroundColorChanged(); + Q_REVISION(1, 2) + void renderProcessTerminated(QQuickWebEngineView::RenderProcessTerminationStatus terminationStatus, + int exitCode); + Q_REVISION(1,2) void windowCloseRequested(); + Q_REVISION(1,3) void contentsSizeChanged(const QSizeF& size); + Q_REVISION(1,3) void scrollPositionChanged(const QPointF& position); + Q_REVISION(1,3) void audioMutedChanged(bool muted); + Q_REVISION(1,3) void recentlyAudibleChanged(bool recentlyAudible); + Q_REVISION(1,3) void webChannelWorldChanged(uint); + Q_REVISION(1,4) void contextMenuRequested(QWebEngineContextMenuRequest *request); + Q_REVISION(1,4) void authenticationDialogRequested(QQuickWebEngineAuthenticationDialogRequest *request); + Q_REVISION(1,4) void javaScriptDialogRequested(QQuickWebEngineJavaScriptDialogRequest *request); + Q_REVISION(1,4) void colorDialogRequested(QQuickWebEngineColorDialogRequest *request); + Q_REVISION(1,4) void fileDialogRequested(QQuickWebEngineFileDialogRequest *request); + Q_REVISION(1,5) void pdfPrintingFinished(const QString &filePath, bool success); +#if QT_DEPRECATED_SINCE(6, 5) + QT_DEPRECATED_VERSION_X_6_5("Requesting host quota is no longer supported.") + Q_REVISION(1, 7) void quotaRequested(const QWebEngineQuotaRequest &request); +#endif + Q_REVISION(1,7) void geometryChangeRequested(const QRect &geometry, const QRect &frameGeometry); + Q_REVISION(1,7) void inspectedViewChanged(); + Q_REVISION(1,7) void devToolsViewChanged(); + Q_REVISION(1,7) void registerProtocolHandlerRequested(const QWebEngineRegisterProtocolHandlerRequest &request); + Q_REVISION(1,8) void printRequested(); + Q_REVISION(1,9) void selectClientCertificate(QQuickWebEngineClientCertificateSelection *clientCertSelection); + Q_REVISION(1,10) void tooltipRequested(QQuickWebEngineTooltipRequest *request); + Q_REVISION(1, 10) void lifecycleStateChanged(QQuickWebEngineView::LifecycleState state); + Q_REVISION(1, 10) void recommendedStateChanged(QQuickWebEngineView::LifecycleState state); + Q_REVISION(1,10) void findTextFinished(const QWebEngineFindTextResult &result); + Q_REVISION(1,11) void renderProcessPidChanged(qint64 pid); + Q_REVISION(1,11) void canGoBackChanged(); + Q_REVISION(1,11) void canGoForwardChanged(); + Q_REVISION(1,12) void newWindowRequested(QQuickWebEngineNewWindowRequest *request); + Q_REVISION(6,3) void touchSelectionMenuRequested(QQuickWebEngineTouchSelectionMenuRequest *request); + Q_REVISION(6,4) void touchHandleDelegateChanged(); + Q_REVISION(6,4) void fileSystemAccessRequested(const QWebEngineFileSystemAccessRequest &request); + Q_REVISION(6, 7) void webAuthUxRequested(QWebEngineWebAuthUxRequest *request); + Q_REVISION(6,7) void desktopMediaRequested(const QWebEngineDesktopMediaRequest &request); + +protected: + void geometryChange(const QRectF &newGeometry, const QRectF &oldGeometry) override; + void itemChange(ItemChange, const ItemChangeData &) override; +#if QT_CONFIG(draganddrop) + void dragEnterEvent(QDragEnterEvent *e) override; + void dragLeaveEvent(QDragLeaveEvent *e) override; + void dragMoveEvent(QDragMoveEvent *e) override; + void dropEvent(QDropEvent *e) override; +#endif // QT_CONFIG(draganddrop) + +private: + Q_DECLARE_PRIVATE(QQuickWebEngineView) + QScopedPointer<QQuickWebEngineViewPrivate> d_ptr; + + friend class QQuickContextMenuBuilder; + friend class FaviconProviderHelper; + friend class FaviconImageRequester; +#if QT_CONFIG(accessibility) + friend class QQuickWebEngineViewAccessible; +#endif // QT_CONFIG(accessibility) +}; + +QT_END_NAMESPACE + +QML_DECLARE_TYPE(QQuickWebEngineView) + +#endif // QQUICKWEBENGINEVIEW_P_H diff --git a/src/webenginequick/api/qquickwebengineview_p_p.h b/src/webenginequick/api/qquickwebengineview_p_p.h new file mode 100644 index 000000000..eed8342eb --- /dev/null +++ b/src/webenginequick/api/qquickwebengineview_p_p.h @@ -0,0 +1,204 @@ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + +#ifndef QQUICKWEBENGINEVIEW_P_P_H +#define QQUICKWEBENGINEVIEW_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 "qquickwebenginetouchhandle_p.h" +#include "qquickwebengineview_p.h" +#include "render_view_context_menu_qt.h" +#include "touch_handle_drawable_client.h" +#include "ui_delegates_manager_p.h" +#include "web_contents_adapter_client.h" + +#include <QtCore/qcompilerdetection.h> +#include <QtCore/qpointer.h> +#include <QtCore/qscopedpointer.h> +#include <QtCore/qsharedpointer.h> +#include <QtCore/qstring.h> + +namespace QtWebEngineCore { +class RenderWidgetHostViewQtDelegateItem; +class TouchSelectionMenuController; +class UIDelegatesManager; +class WebContentsAdapter; +} + +QT_BEGIN_NAMESPACE +class QQmlComponent; +class QQuickWebEngineScriptCollection; +class QQuickWebEngineSettings; +class QQuickWebEngineView; +class QWebEngineContextMenuRequest; +class QWebEngineFindTextResult; +class QWebEngineHistory; + +class Q_WEBENGINEQUICK_EXPORT QQuickWebEngineViewPrivate : public QtWebEngineCore::WebContentsAdapterClient +{ +public: + Q_DECLARE_PUBLIC(QQuickWebEngineView) + QQuickWebEngineView *q_ptr; + QQuickWebEngineViewPrivate(); + ~QQuickWebEngineViewPrivate(); + void releaseProfile() override; + void initializeProfile(); + QtWebEngineCore::UIDelegatesManager *ui(); + + QtWebEngineCore::RenderWidgetHostViewQtDelegate* CreateRenderWidgetHostViewQtDelegate(QtWebEngineCore::RenderWidgetHostViewQtDelegateClient *client) override; + QtWebEngineCore::RenderWidgetHostViewQtDelegate* CreateRenderWidgetHostViewQtDelegateForPopup(QtWebEngineCore::RenderWidgetHostViewQtDelegateClient *client) override; + void initializationFinished() override; + void lifecycleStateChanged(LifecycleState state) override; + void recommendedStateChanged(LifecycleState state) override; + void visibleChanged(bool visible) override; + void titleChanged(const QString&) override; + void urlChanged() override; + void iconChanged(const QUrl&) override; + void loadProgressChanged(int progress) override; + void didUpdateTargetURL(const QUrl&) override; + void selectionChanged() override; + void zoomUpdateIsNeeded() override; + void recentlyAudibleChanged(bool recentlyAudible) override; + void renderProcessPidChanged(qint64 pid) override; + QRectF viewportRect() const override; + QColor backgroundColor() const override; + void loadStarted(QWebEngineLoadingInfo info) override; + void loadCommitted() override; + void loadFinished(QWebEngineLoadingInfo info) override; + void focusContainer() override; + void unhandledKeyEvent(QKeyEvent *event) override; + QSharedPointer<QtWebEngineCore::WebContentsAdapter> + adoptNewWindow(QSharedPointer<QtWebEngineCore::WebContentsAdapter> newWebContents, + WindowOpenDisposition disposition, bool userGesture, const QRect &, + const QUrl &targetUrl) override; + bool isBeingAdopted() override; + void close() override; + void windowCloseRejected() override; + void requestFullScreenMode(const QUrl &origin, bool fullscreen) override; + bool isFullScreenMode() const override; + void contextMenuRequested(QWebEngineContextMenuRequest *request) override; + void navigationRequested(int navigationType, const QUrl &url, bool &accepted, bool isMainFrame, bool hasFrameData) override; + void javascriptDialog(QSharedPointer<QtWebEngineCore::JavaScriptDialogController>) override; + void runFileChooser(QSharedPointer<QtWebEngineCore::FilePickerController>) override; + void desktopMediaRequested(QtWebEngineCore::DesktopMediaController *) override; + void showColorDialog(QSharedPointer<QtWebEngineCore::ColorChooserController>) override; + void runJavaScript(const QString &script, quint32 worldId, + const std::function<void(const QVariant &)> &callback) override; + void didFetchDocumentMarkup(quint64, const QString&) override { } + void didFetchDocumentInnerText(quint64, const QString&) override { } + void didPrintPage(quint64 requestId, QSharedPointer<QByteArray>) override; + void didPrintPageToPdf(const QString &filePath, bool success) override; + bool passOnFocus(bool reverse) override; + void javaScriptConsoleMessage(JavaScriptConsoleMessageLevel level, const QString& message, int lineNumber, const QString& sourceID) override; + void authenticationRequired(QSharedPointer<QtWebEngineCore::AuthenticationDialogController>) override; + void runMediaAccessPermissionRequest(const QUrl &securityOrigin, MediaRequestFlags requestFlags) override; + void runMouseLockPermissionRequest(const QUrl &securityOrigin) override; + void runRegisterProtocolHandlerRequest(QWebEngineRegisterProtocolHandlerRequest) override; + void runFileSystemAccessRequest(QWebEngineFileSystemAccessRequest) override; + QObject *accessibilityParentObject() override; + QWebEngineSettings *webEngineSettings() const override; + void allowCertificateError(const QWebEngineCertificateError &error) override; + void selectClientCert(const QSharedPointer<QtWebEngineCore::ClientCertSelectController> + &selectController) override; + void runFeaturePermissionRequest(QtWebEngineCore::ProfileAdapter::PermissionType permission, const QUrl &securityOrigin) override; + void renderProcessTerminated(RenderProcessTerminationStatus terminationStatus, int exitCode) override; + void requestGeometryChange(const QRect &geometry, const QRect &frameGeometry) override; + void updateScrollPosition(const QPointF &position) override; + void updateContentsSize(const QSizeF &size) override; + void updateNavigationActions() override; + void updateEditActions() override; + QObject *dragSource() const override; + bool isEnabled() const override; + void setToolTip(const QString &toolTipText) override; + QtWebEngineCore::TouchHandleDrawableDelegate *createTouchHandleDelegate(const QMap<int, QImage> &images) override; + void showTouchSelectionMenu(QtWebEngineCore::TouchSelectionMenuController *, const QRect &, const QSize &) override; + void hideTouchSelectionMenu() override; + const QObject *holdingQObject() const override; + ClientType clientType() override { return QtWebEngineCore::WebContentsAdapterClient::QmlClient; } + + QtWebEngineCore::ProfileAdapter *profileAdapter() override; + QtWebEngineCore::WebContentsAdapter *webContentsAdapter() override; + void printRequested() override; + void findTextFinished(const QWebEngineFindTextResult &result) override; + void showAutofillPopup(QtWebEngineCore::AutofillPopupController *controller, + const QRect &bounds, bool autoselectFirstSuggestion) override; + void hideAutofillPopup() override; + void showWebAuthDialog(QWebEngineWebAuthUxRequest *request) override; + + void updateAction(QQuickWebEngineView::WebAction) const; + bool adoptWebContents(QtWebEngineCore::WebContentsAdapter *webContents); + void setProfile(QQuickWebEngineProfile *profile); + void updateAdapter(); + void ensureContentsAdapter(); + void setFullScreenMode(bool); + + static void bindViewAndDelegateItem(QQuickWebEngineViewPrivate *viewPrivate, QtWebEngineCore::RenderWidgetHostViewQtDelegateItem *delegateItem); + void delegateItemChanged(QtWebEngineCore::RenderWidgetHostViewQtDelegateItem *oldDelegateItem, + QtWebEngineCore::RenderWidgetHostViewQtDelegateItem *newDelegateItem); + + QQuickWebEngineProfile *m_profile; + QSharedPointer<QtWebEngineCore::WebContentsAdapter> adapter; + QScopedPointer<QWebEngineHistory> m_history; + QScopedPointer<QQuickWebEngineSettings> m_settings; + QQmlComponent *contextMenuExtraItems; + QUrl m_url; + QString m_html; + QUrl iconUrl; + int loadProgress; + bool m_fullscreenMode; + bool isLoading; + bool m_activeFocusOnPress; + QMap<quint64, QJSValue> m_printCallbacks; + QQmlWebChannel *m_webChannel; + QPointer<QQuickWebEngineView> inspectedView; + QPointer<QQuickWebEngineView> devToolsView; + uint m_webChannelWorld; + bool m_defaultAudioMuted; + bool m_isBeingAdopted; + mutable QQuickWebEngineAction *actions[QQuickWebEngineView::WebActionCount]; + QtWebEngineCore::RenderWidgetHostViewQtDelegateItem *delegateItem = nullptr; + + bool profileInitialized() const; + QQuickWebEngineScriptCollection *getUserScripts(); + +private: + QScopedPointer<QtWebEngineCore::UIDelegatesManager> m_uIDelegatesManager; + QColor m_backgroundColor; + qreal m_zoomFactor; + bool m_profileInitialized; + QWebEngineContextMenuRequest *m_contextMenuRequest; + QScopedPointer<QQuickWebEngineScriptCollection> m_scriptCollection; + QQmlComponent *m_touchHandleDelegate; +}; + +class QQuickContextMenuBuilder : public QtWebEngineCore::RenderViewContextMenuQt +{ +public: + QQuickContextMenuBuilder(QWebEngineContextMenuRequest *data, QQuickWebEngineView *view, + QObject *menu); + void appendExtraItems(QQmlEngine *engine); + +private: + virtual bool hasInspector() override; + virtual bool isFullScreenMode() override; + + virtual void addMenuItem(ContextMenuItem menuItem) override; + virtual bool isMenuItemEnabled(ContextMenuItem menuItem) override; + + QQuickWebEngineView *m_view; + QObject *m_menu; +}; + +QT_END_NAMESPACE + +#endif // QQUICKWEBENGINEVIEW_P_P_H diff --git a/src/webenginequick/api/qtwebenginequickglobal.cpp b/src/webenginequick/api/qtwebenginequickglobal.cpp new file mode 100644 index 000000000..e24ef643b --- /dev/null +++ b/src/webenginequick/api/qtwebenginequickglobal.cpp @@ -0,0 +1,59 @@ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + +#include <QtCore/qcoreapplication.h> +#include <QtQuick/qquickwindow.h> +#include <QtWebEngineQuick/qtwebenginequickglobal.h> + +namespace QtWebEngineCore +{ + extern void initialize(); +} + +QT_BEGIN_NAMESPACE + +namespace QtWebEngineQuick { + +/*! + \namespace QtWebEngineQuick + \inmodule QtWebEngineQuick + \ingroup qtwebengine-namespaces + \keyword QtWebEngine Namespace + + \brief Helper functions for the \QWE (Qt Quick) module. + + The \l[CPP]{QtWebEngineQuick} namespace is part of the \QWE module. +*/ + +/*! + \fn QtWebEngineQuick::initialize() + + Sets up an OpenGL Context that can be shared between threads. This has to be done before + QGuiApplication is created and before window's QPlatformOpenGLContext is created. + + This has the same effect as setting the Qt::AA_ShareOpenGLContexts + attribute with QCoreApplication::setAttribute before constructing + QGuiApplication. +*/ +void initialize() +{ + auto api = QQuickWindow::graphicsApi(); + if (!QCoreApplication::startingUp()) { + if (api == QSGRendererInterface::OpenGL || (api != QSGRendererInterface::Vulkan + && api != QSGRendererInterface::Metal && api != QSGRendererInterface::Direct3D11)) { + qWarning("QtWebEngineQuick::initialize() called with QCoreApplication object already created and should be call before. "\ + "This is depreciated and may fail in the future."); + } + QtWebEngineCore::initialize(); + return; + } + + // call initialize the same way as widgets do + qAddPreRoutine(QtWebEngineCore::initialize); + if (api != QSGRendererInterface::OpenGL && api != QSGRendererInterface::Vulkan + && api != QSGRendererInterface::Metal && api != QSGRendererInterface::Direct3D11) + QQuickWindow::setGraphicsApi(QSGRendererInterface::OpenGL); +} +} // namespace QtWebEngineQuick + +QT_END_NAMESPACE diff --git a/src/webenginequick/api/qtwebenginequickglobal.h b/src/webenginequick/api/qtwebenginequickglobal.h new file mode 100644 index 000000000..1580bf6db --- /dev/null +++ b/src/webenginequick/api/qtwebenginequickglobal.h @@ -0,0 +1,29 @@ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + +#ifndef QTWEBENGINEQUICKGLOBAL_H +#define QTWEBENGINEQUICKGLOBAL_H + +#include <QtCore/qglobal.h> +#include <QtWebEngineQuick/qtwebenginequick-config.h> + +QT_BEGIN_NAMESPACE + +#ifndef QT_STATIC +# if defined(QT_BUILD_WEBENGINE_LIB) +# define Q_WEBENGINEQUICK_EXPORT Q_DECL_EXPORT +# else +# define Q_WEBENGINEQUICK_EXPORT Q_DECL_IMPORT +# endif +#else +# define Q_WEBENGINEQUICK_EXPORT +#endif + +namespace QtWebEngineQuick +{ + Q_WEBENGINEQUICK_EXPORT void initialize(); +} + +QT_END_NAMESPACE + +#endif // QTWEBENGINEQUICKGLOBAL_H diff --git a/src/webenginequick/api/qtwebenginequickglobal_p.h b/src/webenginequick/api/qtwebenginequickglobal_p.h new file mode 100644 index 000000000..256bcd590 --- /dev/null +++ b/src/webenginequick/api/qtwebenginequickglobal_p.h @@ -0,0 +1,22 @@ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + +#ifndef QTWEBENGINEQUICKGLOBAL_P_H +#define QTWEBENGINEQUICKGLOBAL_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 <QtWebEngineQuick/qtwebenginequickglobal.h> +#include <QtCore/private/qglobal_p.h> +#include <QtWebEngineQuick/private/qtwebenginequick-config_p.h> + +#endif // QTWEBENGINEQUICKGLOBAL_P_H |