diff options
Diffstat (limited to 'src/webenginequick')
91 files changed, 17057 insertions, 0 deletions
diff --git a/src/webenginequick/CMakeLists.txt b/src/webenginequick/CMakeLists.txt new file mode 100644 index 000000000..b7de1c2af --- /dev/null +++ b/src/webenginequick/CMakeLists.txt @@ -0,0 +1,78 @@ +# Copyright (C) 2022 The Qt Company Ltd. +# SPDX-License-Identifier: BSD-3-Clause + +add_subdirectory(ui) + +qt_internal_add_qml_module(WebEngineQuick + URI "QtWebEngine" + VERSION "${PROJECT_VERSION}" + CLASS_NAME QtWebEnginePlugin + DEPENDENCIES + QtQuick/auto + QtWebChannel/auto + PLUGIN_TARGET qtwebenginequickplugin + NO_GENERATE_PLUGIN_SOURCE + NO_PLUGIN_OPTIONAL + SOURCES + api/qquickwebengineaction.cpp api/qquickwebengineaction_p.h + api/qquickwebengineaction_p_p.h + api/qquickwebengineclientcertificateselection.cpp api/qquickwebengineclientcertificateselection_p.h + api/qquickwebenginedialogrequests.cpp api/qquickwebenginedialogrequests_p.h + api/qquickwebenginedownloadrequest.cpp api/qquickwebenginedownloadrequest_p.h + api/qquickwebenginefaviconprovider.cpp + api/qquickwebenginefaviconprovider_p_p.h + api/qquickwebenginenewwindowrequest.cpp api/qquickwebenginenewwindowrequest_p.h + api/qquickwebengineprofile.cpp api/qquickwebengineprofile.h api/qquickwebengineprofile_p.h + api/qquickwebenginescriptcollection.cpp api/qquickwebenginescriptcollection_p.h api/qquickwebenginescriptcollection_p_p.h + api/qquickwebenginesettings.cpp api/qquickwebenginesettings_p.h + api/qquickwebenginesingleton.cpp api/qquickwebenginesingleton_p.h + api/qquickwebenginetouchhandleprovider.cpp + api/qquickwebenginetouchhandleprovider_p_p.h + api/qquickwebenginetouchhandle.cpp api/qquickwebenginetouchhandle_p.h + api/qquickwebenginetouchselectionmenurequest.cpp + api/qquickwebenginetouchselectionmenurequest_p.h + api/qquickwebenginetouchselectionmenurequest_p_p.h + api/qquickwebengineview.cpp api/qquickwebengineview_p.h + api/qquickwebengineview_p_p.h + api/qquickwebengineforeigntypes_p.h + api/qtwebenginequickglobal.cpp api/qtwebenginequickglobal.h + api/qtwebenginequickglobal_p.h + render_widget_host_view_qt_delegate_quickwindow.cpp render_widget_host_view_qt_delegate_quickwindow_p.h + ui_delegates_manager.cpp ui_delegates_manager_p.h + DEFINES + QT_BUILD_WEBENGINE_LIB + INCLUDE_DIRECTORIES + ../core + api + LIBRARIES + Qt::CorePrivate + Qt::GuiPrivate + Qt::QuickPrivate + Qt::WebEngineCorePrivate + PUBLIC_LIBRARIES + Qt::Core + Qt::Gui + Qt::Qml + Qt::Quick + Qt::WebEngineCore + NO_GENERATE_CPP_EXPORTS +) + +qt_internal_extend_target(WebEngineQuick CONDITION QT_FEATURE_webengine_webchannel + PUBLIC_LIBRARIES + Qt::WebChannelQuick +) + +qt_internal_extend_target(WebEngineQuick CONDITION QT_FEATURE_accessibility + SOURCES + qquickwebengine_accessible.cpp qquickwebengine_accessible_p.h +) + +qt_internal_extend_target(qtwebenginequickplugin + SOURCES + plugin.cpp + LIBRARIES + Qt::CorePrivate + Qt::WebEngineQuickPrivate +) + 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..58dee066f --- /dev/null +++ b/src/webenginequick/api/qquickwebengineforeigntypes_p.h @@ -0,0 +1,270 @@ +// 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> +#include <QtWebEngineCore/qwebenginepermission.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("") +}; + +struct ForeginWebEngineWebAuthPinRequest +{ + Q_GADGET + QML_FOREIGN(QWebEngineWebAuthPinRequest) + QML_NAMED_ELEMENT(WebEngineWebAuthPinRequest) + QML_ADDED_IN_VERSION(6, 8) + QML_UNCREATABLE("") +}; + +// To prevent the same type from being exported twice into qmltypes +// (for value type and for the enums) +class QWebEnginePermissionDerived : public QWebEnginePermission +{ + Q_GADGET +}; + +namespace ForeignWebEnginePermissionNamespace +{ + Q_NAMESPACE + QML_FOREIGN_NAMESPACE(QWebEnginePermissionDerived) + QML_NAMED_ELEMENT(WebEnginePermission) + QML_ADDED_IN_VERSION(6, 8) +} + +struct ForeignWebEnginePermission +{ + Q_GADGET + QML_FOREIGN(QWebEnginePermission) + QML_VALUE_TYPE(webEnginePermission) + QML_ADDED_IN_VERSION(6, 8) + 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..d3373d0b9 --- /dev/null +++ b/src/webenginequick/api/qquickwebengineprofile.cpp @@ -0,0 +1,1268 @@ +// 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 <QtWebEngineCore/private/qwebenginepermission_p.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. +*/ + +/*! + \enum QQuickWebEngineProfile::PersistentPermissionsPolicy + + \since 6.8 + + This enum describes the policy for permission persistence: + + \value NoPersistentPermissions + The application will ask for permissions every time they're needed, regardless of + whether they've been granted before or not. This is intended for backwards compatibility + with existing applications, and otherwise not recommended. + \value PersistentPermissionsInMemory + A request will be made only the first time a permission is needed. Any subsequent + requests will be automatically granted or denied, depending on the initial user choice. + This carries over to all pages that use the same QQuickWebEngineProfile instance, until the + application is shut down. This is the setting applied if \c off-the-record is set + or no persistent data path is available. + \value PersistentPermissionsOnDisk + Works the same way as \c PersistentPermissionsInMemory, but the permissions are saved to + and restored from disk. This is the default setting. +*/ + +/*! + \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 oldCookiePolicy = d->profileAdapter()->persistentCookiesPolicy(); + ProfileAdapter::PersistentPermissionsPolicy oldPermissionsPolicy = d->profileAdapter()->persistentPermissionsPolicy(); + d->profileAdapter()->setStorageName(name); + emit storageNameChanged(); + emit persistentStoragePathChanged(); + emit cachePathChanged(); + if (d->profileAdapter()->httpCacheType() != oldCacheType) + emit httpCacheTypeChanged(); + if (d->profileAdapter()->persistentCookiesPolicy() != oldCookiePolicy) + emit persistentCookiesPolicyChanged(); + if (d->profileAdapter()->persistentPermissionsPolicy() != oldPermissionsPolicy) + emit persistentPermissionsPolicyChanged(); +} + +/*! + \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 oldCookiePolicy = d->profileAdapter()->persistentCookiesPolicy(); + ProfileAdapter::PersistentPermissionsPolicy oldPermissionsPolicy = d->profileAdapter()->persistentPermissionsPolicy(); + d->profileAdapter()->setOffTheRecord(offTheRecord); + emit offTheRecordChanged(); + if (d->profileAdapter()->httpCacheType() != oldCacheType) + emit httpCacheTypeChanged(); + if (d->profileAdapter()->persistentCookiesPolicy() != oldCookiePolicy) + emit persistentCookiesPolicyChanged(); + if (d->profileAdapter()->persistentPermissionsPolicy() != oldPermissionsPolicy) + emit persistentPermissionsPolicyChanged(); +} + +/*! + \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 persistence: + + \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 enumeration WebEngineProfile::persistentPermissionsPolicy + + \since 6.8 + + This enumeration describes the policy for permission persistence: + + \value WebEngineProfile.NoPersistentPermissions + The application will ask for permissions every time they're needed, regardless of + whether they've been granted before or not. This is intended for backwards compatibility + with existing applications, and otherwise not recommended. + \value WebEngineProfile.PersistentPermissionsInMemory + A request will be made only the first time a permission is needed. Any subsequent + requests will be automatically granted or denied, depending on the initial user choice. + This carries over to all pages using the same QWebEngineProfile instance, until the + application is shut down. This is the setting applied if \c off-the-record is set + or no persistent data path is available. + \value WebEngineProfile.PersistentPermissionsOnDisk + Works the same way as \c PersistentPermissionsInMemory, but the permissions are saved to + and restored from disk. This is the default setting. +*/ + +/*! + \property QQuickWebEngineProfile::persistentPermissionsPolicy + \since 6.8 + + Describes the policy of permission persistence. + If the profile is off-the-record, NoPersistentCookies is returned. +*/ + +QQuickWebEngineProfile::PersistentPermissionsPolicy QQuickWebEngineProfile::persistentPermissionsPolicy() const +{ + Q_D(const QQuickWebEngineProfile); + return QQuickWebEngineProfile::PersistentPermissionsPolicy(d->profileAdapter()->persistentPermissionsPolicy()); +} + +void QQuickWebEngineProfile::setPersistentPermissionsPolicy(QQuickWebEngineProfile::PersistentPermissionsPolicy newPersistentPermissionsPolicy) +{ + Q_D(QQuickWebEngineProfile); + ProfileAdapter::PersistentPermissionsPolicy oldPolicy = d->profileAdapter()->persistentPermissionsPolicy(); + d->profileAdapter()->setPersistentPermissionsPolicy(ProfileAdapter::PersistentPermissionsPolicy(newPersistentPermissionsPolicy)); + if (d->profileAdapter()->persistentPermissionsPolicy() != oldPolicy) + emit persistentPermissionsPolicyChanged(); +} + +/*! + \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(); +} + +/*! + \fn QQuickWebEngineProfile::getPermission(const QUrl &securityOrigin, QWebEnginePermission::Feature feature) const + + Returns a QWebEnginePermission object corresponding to a single permission for the provided \a securityOrigin and + \a feature. The object may be used to query for the current state of the permission, or to change it. It is not required + for a permission to already exist; the returned object may also be used to pre-grant a permission if a website is + known to use it. + + \note This may only be used for permanent feature types. Calling it with a transient \a feature will return an invalid object. + \since 6.8 + \sa listPermissions(), QWebEnginePermission::Feature + */ + +/*! + \qmlmethod void WebEngineProfile::getPermission(url securityOrigin, WebEnginePermission.Feature feature) const + + Returns a webEnginePermission object corresponding to a single permission for the provided \a securityOrigin and + \a feature. The object may be used to query for the current state of the permission, or to change it. It is not required + for a permission to already exist; the returned object may also be used to pre-grant a permission if a website is + known to use it. + + \note This may only be used for permanent feature types. Calling it with a transient \a feature will return an invalid object. + \since 6.8 + \sa listPermissions() + */ +QWebEnginePermission QQuickWebEngineProfile::getPermission(const QUrl &securityOrigin, QWebEnginePermission::Feature feature) const +{ + Q_D(const QQuickWebEngineProfile); + + if (feature == QWebEnginePermission::Unsupported) { + qWarning("Attempting to get unsupported permission. Returned object will be in an invalid state."); + return QWebEnginePermission(new QWebEnginePermissionPrivate()); + } + + if (QWebEnginePermission::isTransient(feature)) { + qWarning() << "Attempting to get permission for feature" << feature << ". Returned object will be in an invalid state."; + return QWebEnginePermission(new QWebEnginePermissionPrivate()); + } + + auto *pvt = new QWebEnginePermissionPrivate(securityOrigin, feature, nullptr, d->profileAdapter()); + return QWebEnginePermission(pvt); +} + +/*! + \qmlmethod list<webEnginePermission> WebEngineProfile::listPermissions() const + + Returns a \l list of webEnginePermission objects, each one representing a single permission currently + present in the permissions store. The returned list contains all previously granted/denied permissions for this profile, + except for those of a transient feature type. + + \since 6.8 + \sa getPermission() + */ + +/*! + Returns a QList of QWebEnginePermission objects, each one representing a single permission currently + present in the permissions store. The returned list contains all previously granted/denied permissions for this profile, + except for those of a transient feature type. + + \since 6.8 + \sa getPermission() + */ +QList<QWebEnginePermission> QQuickWebEngineProfile::listPermissions() const +{ + Q_D(const QQuickWebEngineProfile); + if (persistentPermissionsPolicy() == NoPersistentPermissions) + return QList<QWebEnginePermission>(); + return d->profileAdapter()->listPermissions(); +} + +/*! + \qmlmethod list<webEnginePermission> WebEngineProfile::listPermissions(url securityOrigin) const + + Returns a \l list of webEnginePermission objects, each one representing a single permission currently + present in the permissions store. The returned list contains all previously granted/denied permissions associated with a + specific \a securityOrigin for this profile, except for those of a transient feature type. + + \note Since permissions are granted on a per-origin basis, the provided \a securityOrigin will be stripped to its + origin form, and the returned list will contain all permissions for the origin. Thus, passing https://www.example.com/some/page.html + is the same as passing just https://www.example.com/. + \since 6.8 + \sa getPermission() + */ + +/*! + Returns a QList of QWebEnginePermission objects, each one representing a single permission currently + present in the permissions store. The returned list contains all previously granted/denied permissions associated with a + specific \a securityOrigin for this profile, except for those of a transient feature type. + + \note Since permissions are granted on a per-origin basis, the provided \a securityOrigin will be stripped to its + origin form, and the returned list will contain all permissions for the origin. Thus, passing https://www.example.com/some/page.html + is the same as passing just https://www.example.com/. + \since 6.8 + \sa getPermission() + */ +QList<QWebEnginePermission> QQuickWebEngineProfile::listPermissions(const QUrl &securityOrigin) const +{ + Q_D(const QQuickWebEngineProfile); + if (persistentPermissionsPolicy() == NoPersistentPermissions) + return QList<QWebEnginePermission>(); + return d->profileAdapter()->listPermissions(securityOrigin); +} + +/*! + \qmlmethod list<webEnginePermission> WebEngineProfile::listPermissions(WebEnginePermission.Feature feature) const + + Returns a \l list of webEnginePermission objects, each one representing a single permission currently + present in the permissions store. The returned list contains all previously granted/denied permissions of the \a feature + type for this profile. If the feature is of a transient or unsupported type, the list will be empty. + + \since 6.8 + \sa getPermission() + */ + +/*! + Returns a QList of QWebEnginePermission objects, each one representing a single permission currently + present in the permissions store. The returned list contains all previously granted/denied permissions of the \a feature + type for this profile. If the feature is of a transient or unsupported type, the list will be empty. + + \since 6.8 + \sa getPermission(), QWebEnginePermission::Feature + */ +QList<QWebEnginePermission> QQuickWebEngineProfile::listPermissions(QWebEnginePermission::Feature feature) const +{ + Q_D(const QQuickWebEngineProfile); + if (persistentPermissionsPolicy() == NoPersistentPermissions) + return QList<QWebEnginePermission>(); + + if (feature == QWebEnginePermission::Unsupported) { + qWarning("Attempting to get permission list for an unsupported type. Returned list will be empty."); + return QList<QWebEnginePermission>(); + } + + if (QWebEnginePermission::isTransient(feature)) { + qWarning() << "Attempting to get permission list for feature" << feature << ". Returned list will be empty."; + return QList<QWebEnginePermission>(); + } + + return d->profileAdapter()->listPermissions(QUrl(), feature); +} + +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..186a11d7b --- /dev/null +++ b/src/webenginequick/api/qquickwebengineprofile.h @@ -0,0 +1,174 @@ +// 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 <QtWebEngineCore/qwebenginepermission.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(PersistentPermissionsPolicy persistentPermissionsPolicy READ persistentPermissionsPolicy WRITE setPersistentPermissionsPolicy NOTIFY persistentPermissionsPolicyChanged 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) + + enum PersistentPermissionsPolicy : quint8 { + NoPersistentPermissions, + PersistentPermissionsInMemory, + PersistentPermissionsOnDisk, + }; + Q_ENUM(PersistentPermissionsPolicy) + + 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); + + PersistentPermissionsPolicy persistentPermissionsPolicy() const; + void setPersistentPermissionsPolicy(QQuickWebEngineProfile::PersistentPermissionsPolicy); + + 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; + + Q_REVISION(6,8) Q_INVOKABLE QWebEnginePermission getPermission(const QUrl &securityOrigin, QWebEnginePermission::Feature feature) const; + Q_REVISION(6,8) Q_INVOKABLE QList<QWebEnginePermission> listPermissions() const; + Q_REVISION(6,8) Q_INVOKABLE QList<QWebEnginePermission> listPermissions(const QUrl &securityOrigin) const; + Q_REVISION(6,8) Q_INVOKABLE QList<QWebEnginePermission> listPermissions(QWebEnginePermission::Feature feature) 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(); + Q_REVISION(6,8) void persistentPermissionsPolicyChanged(); + 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..5dc093a44 --- /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{WebEnginePermission::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{WebEnginePermission::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..852d00c76 --- /dev/null +++ b/src/webenginequick/api/qquickwebengineview.cpp @@ -0,0 +1,2629 @@ +// 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/qwebenginepermission.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 <QtWebEngineCore/private/qwebenginepermission_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); +} + +#if QT_DEPRECATED_SINCE(6, 8) +QT_WARNING_PUSH +QT_WARNING_DISABLE_DEPRECATED +static QQuickWebEngineView::Feature toDeprecatedFeature(QWebEnginePermission::Feature feature) +{ + switch (feature) { + case QWebEnginePermission::Feature::Notifications: + return QQuickWebEngineView::Notifications; + case QWebEnginePermission::Feature::Geolocation: + return QQuickWebEngineView::Geolocation; + case QWebEnginePermission::Feature::ClipboardReadWrite: + return QQuickWebEngineView::ClipboardReadWrite; + case QWebEnginePermission::Feature::LocalFontsAccess: + return QQuickWebEngineView::LocalFontsAccess; + case QWebEnginePermission::Feature::MediaAudioCapture: + return QQuickWebEngineView::MediaAudioCapture; + case QWebEnginePermission::Feature::MediaVideoCapture: + return QQuickWebEngineView::MediaVideoCapture; + case QWebEnginePermission::Feature::MediaAudioVideoCapture: + return QQuickWebEngineView::MediaAudioVideoCapture; + case QWebEnginePermission::Feature::DesktopVideoCapture: + return QQuickWebEngineView::DesktopVideoCapture; + case QWebEnginePermission::Feature::DesktopAudioVideoCapture: + return QQuickWebEngineView::DesktopAudioVideoCapture; + case QWebEnginePermission::Feature::MouseLock: + case QWebEnginePermission::Feature::Unsupported: + break; + } + + Q_UNREACHABLE(); + return QQuickWebEngineView::Feature(-1); +} +QT_WARNING_POP +#endif // QT_DEPRECATED_SINCE(6, 8) + +void QQuickWebEngineViewPrivate::runFeaturePermissionRequest(QWebEnginePermission::Feature feature, const QUrl &url) +{ + Q_Q(QQuickWebEngineView); + switch (feature) { + case QWebEnginePermission::Notifications: + case QWebEnginePermission::Geolocation: + case QWebEnginePermission::ClipboardReadWrite: + case QWebEnginePermission::LocalFontsAccess: + Q_EMIT q->permissionRequested(createFeaturePermissionObject(url, feature)); +#if QT_DEPRECATED_SINCE(6, 8) + QT_WARNING_PUSH + QT_WARNING_DISABLE_DEPRECATED + Q_EMIT q->featurePermissionRequested(url, toDeprecatedFeature(feature)); + QT_WARNING_POP +#endif // QT_DEPRECATED_SINCE(6, 8) + return; + case QWebEnginePermission::MouseLock: + case QWebEnginePermission::MediaAudioCapture: + case QWebEnginePermission::MediaVideoCapture: + case QWebEnginePermission::MediaAudioVideoCapture: + case QWebEnginePermission::DesktopAudioVideoCapture: + case QWebEnginePermission::DesktopVideoCapture: + case QWebEnginePermission::Unsupported: + Q_UNREACHABLE(); + return; + } +} + +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::zoomFactorChanged(qreal factor) +{ + Q_Q(QQuickWebEngineView); + Q_EMIT q->zoomFactorChanged(factor); +} + +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; + QWebEnginePermission::Feature feature; + if (requestFlags.testFlag(WebContentsAdapterClient::MediaAudioCapture) && requestFlags.testFlag(WebContentsAdapterClient::MediaVideoCapture)) + feature = QWebEnginePermission::MediaAudioVideoCapture; + else if (requestFlags.testFlag(WebContentsAdapterClient::MediaAudioCapture)) + feature = QWebEnginePermission::MediaAudioCapture; + else if (requestFlags.testFlag(WebContentsAdapterClient::MediaVideoCapture)) + feature = QWebEnginePermission::MediaVideoCapture; + else if (requestFlags.testFlag(WebContentsAdapterClient::MediaDesktopAudioCapture) && + requestFlags.testFlag(WebContentsAdapterClient::MediaDesktopVideoCapture)) + feature = QWebEnginePermission::DesktopAudioVideoCapture; + else // if (requestFlags.testFlag(WebContentsAdapterClient::MediaDesktopVideoCapture)) + feature = QWebEnginePermission::DesktopVideoCapture; + Q_EMIT q->permissionRequested(createFeaturePermissionObject(securityOrigin, feature)); + +#if QT_DEPRECATED_SINCE(6, 8) + QT_WARNING_PUSH + QT_WARNING_DISABLE_DEPRECATED + QQuickWebEngineView::Feature deprecatedFeature; + + if (requestFlags.testFlag(WebContentsAdapterClient::MediaAudioCapture) + && requestFlags.testFlag(WebContentsAdapterClient::MediaVideoCapture)) + deprecatedFeature = QQuickWebEngineView::MediaAudioVideoCapture; + else if (requestFlags.testFlag(WebContentsAdapterClient::MediaAudioCapture)) + deprecatedFeature = QQuickWebEngineView::MediaAudioCapture; + else if (requestFlags.testFlag(WebContentsAdapterClient::MediaVideoCapture)) + deprecatedFeature = QQuickWebEngineView::MediaVideoCapture; + else if (requestFlags.testFlag(WebContentsAdapterClient::MediaDesktopAudioCapture) + && requestFlags.testFlag(WebContentsAdapterClient::MediaDesktopVideoCapture)) + deprecatedFeature = QQuickWebEngineView::DesktopAudioVideoCapture; + else // if (requestFlags.testFlag(WebContentsAdapterClient::MediaDesktopVideoCapture)) + deprecatedFeature = QQuickWebEngineView::DesktopVideoCapture; + + Q_EMIT q->featurePermissionRequested(securityOrigin, deprecatedFeature); + QT_WARNING_POP +#endif // QT_DEPRECATED_SINCE(6, 8) +} + +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::printRequestedByFrame(quint64 frameId) +{ + Q_Q(QQuickWebEngineView); + QTimer::singleShot(0, q, [this, q, frameId]() { + Q_EMIT q->printRequestedByFrame(QWebEngineFrame(this, frameId)); + }); +} + +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(); + } 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, quint64 frameId, + const std::function<void(const QVariant &)> &callback) +{ + ensureContentsAdapter(); + adapter->runJavaScript(script, worldId, frameId, callback); +} + +void QQuickWebEngineViewPrivate::printToPdf(const QString &filePath, const QPageLayout &layout, + const QPageRanges &ranges, quint64 frameId) +{ + adapter->printToPDF(layout, ranges, filePath, frameId); +} + +void QQuickWebEngineViewPrivate::printToPdf( + std::function<void(QSharedPointer<QByteArray>)> &&callback, const QPageLayout &layout, + const QPageRanges &ranges, quint64 frameId) +{ + adapter->printToPDFCallbackResult(std::move(callback), layout, ranges, /*colorMode*/ true, + /*useCustomMargins*/ true, frameId); +} + +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); +} + +QWebEnginePermission QQuickWebEngineViewPrivate::createFeaturePermissionObject(const QUrl &securityOrigin, QWebEnginePermission::Feature feature) +{ + auto *returnPrivate = new QWebEnginePermissionPrivate(securityOrigin, feature, adapter, profileAdapter()); + return QWebEnginePermission(returnPrivate); +} + +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, WebContentsAdapter::kUseMainFrameId, 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->printToPdf(filePath, pageLayout, ranges, WebContentsAdapter::kUseMainFrameId); +#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(); + std::function wrappedCallback = [this, callback](QSharedPointer<QByteArray> result) { + QJSValueList args; + args.append(qmlEngine(this)->toScriptValue(*result)); + callback.call(args); + }; + + d->printToPdf(std::move(wrappedCallback), pageLayout, ranges, + WebContentsAdapter::kUseMainFrameId); +#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(); +} + +#if QT_DEPRECATED_SINCE(6, 8) +QT_WARNING_PUSH QT_WARNING_DISABLE_DEPRECATED +void QQuickWebEngineView::grantFeaturePermission(const QUrl &securityOrigin, QQuickWebEngineView::Feature feature, bool granted) +{ + Q_D(QQuickWebEngineView); + QWebEnginePermission::Feature f; + + switch (feature) { + case QQuickWebEngineView::Notifications: + f = QWebEnginePermission::Notifications; + break; + case QQuickWebEngineView::Geolocation: + f = QWebEnginePermission::Geolocation; + break; + case QQuickWebEngineView::MediaAudioCapture: + f = QWebEnginePermission::MediaAudioCapture; + break; + case QQuickWebEngineView::MediaVideoCapture: + f = QWebEnginePermission::MediaVideoCapture; + break; + case QQuickWebEngineView::MediaAudioVideoCapture: + f = QWebEnginePermission::MediaAudioVideoCapture; + break; + case QQuickWebEngineView::DesktopVideoCapture: + f = QWebEnginePermission::DesktopVideoCapture; + break; + case QQuickWebEngineView::DesktopAudioVideoCapture: + f = QWebEnginePermission::DesktopAudioVideoCapture; + break; + case QQuickWebEngineView::ClipboardReadWrite: + f = QWebEnginePermission::ClipboardReadWrite; + break; + case QQuickWebEngineView::LocalFontsAccess: + f = QWebEnginePermission::LocalFontsAccess; + break; + default: + Q_UNREACHABLE(); + } + + d->adapter->setFeaturePermission(securityOrigin, f, granted ? QWebEnginePermission::Granted : QWebEnginePermission::Denied); +} +QT_WARNING_POP +#endif // QT_DEPRECATED_SINCE(6, 8) + +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..ea09dff9f --- /dev/null +++ b/src/webenginequick/api/qquickwebengineview_p.h @@ -0,0 +1,620 @@ +// 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 <QtWebEngineCore/qwebenginepermission.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 +#if QT_DEPRECATED_SINCE(6, 8) +QT_WARNING_PUSH QT_WARNING_DISABLE_DEPRECATED + enum QT_DEPRECATED_VERSION_X_6_8( + "WebEnginePage::Feature has been deprecated. " + "The updated permissions API uses WebEnginePermission::Feature.") + Feature { + MediaAudioCapture, + MediaVideoCapture, + MediaAudioVideoCapture, + Geolocation, + DesktopVideoCapture, + DesktopAudioVideoCapture, + Notifications, + ClipboardReadWrite, + LocalFontsAccess, + }; + Q_ENUM(Feature) +QT_WARNING_POP +#endif + + 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(); +#if QT_DEPRECATED_SINCE(6, 8) +#if !defined(Q_MOC_RUN) +QT_WARNING_PUSH +QT_WARNING_DISABLE_DEPRECATED +#endif // !defined(Q_MOC_RUN) + QT_DEPRECATED_VERSION_X_6_8("Setting permissions through WebEngineView has been deprecated. Please use WebEnginePermission instead.") + Q_REVISION(1,1) void grantFeaturePermission(const QUrl &securityOrigin, QQuickWebEngineView::Feature, bool granted); +#if !defined(Q_MOC_RUN) +QT_WARNING_POP +#endif // !defined(Q_MOC_RUN) +#endif // QT_DEPRECATED_SINCE(6, 8) + 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(); +#if QT_DEPRECATED_SINCE(6, 8) +#if !defined(Q_MOC_RUN) +QT_WARNING_PUSH +QT_WARNING_DISABLE_DEPRECATED +#endif // !defined(Q_MOC_RUN) + QT_MOC_COMPAT QT_DEPRECATED_VERSION_X_6_8("The signal has been deprecated; please use permissionRequested instead.") + Q_REVISION(1, 1) + void featurePermissionRequested(const QUrl &securityOrigin, + QQuickWebEngineView::Feature feature); +#if !defined(Q_MOC_RUN) +QT_WARNING_POP +#endif // !defined(Q_MOC_RUN) +#endif // QT_DEPRECATED_SINCE(6, 8) + 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); + Q_REVISION(6, 8) void printRequestedByFrame(QWebEngineFrame frame); + Q_REVISION(6,8) void permissionRequested(QWebEnginePermission permissionRequest); + +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..e61f32bcb --- /dev/null +++ b/src/webenginequick/api/qquickwebengineview_p_p.h @@ -0,0 +1,209 @@ +// 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 zoomFactorChanged(qreal factor) 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, quint64 frameId, + const std::function<void(const QVariant &)> &callback) override; + void didFetchDocumentMarkup(quint64, const QString&) override { } + void didFetchDocumentInnerText(quint64, const QString&) override { } + void printToPdf(const QString &filePath, const QPageLayout &layout, const QPageRanges &ranges, + quint64 frameId) override; + void printToPdf(std::function<void(QSharedPointer<QByteArray>)> &&callback, + const QPageLayout &layout, const QPageRanges &ranges, quint64 frameId) 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(QWebEnginePermission::Feature feature, 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 printRequestedByFrame(quint64 frameId) 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; + QWebEnginePermission createFeaturePermissionObject(const QUrl &securityOrigin, QWebEnginePermission::Feature feature) 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; + 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 diff --git a/src/webenginequick/configure.cmake b/src/webenginequick/configure.cmake new file mode 100644 index 000000000..b256e5a1d --- /dev/null +++ b/src/webenginequick/configure.cmake @@ -0,0 +1,10 @@ +# Copyright (C) 2022 The Qt Company Ltd. +# SPDX-License-Identifier: BSD-3-Clause + +qt_feature("webenginequick-ui-delegates" PRIVATE + SECTION "WebEngine" + LABEL "UI Delegates" +) +qt_configure_add_summary_section(NAME "Qt WebEngineQuick") +qt_configure_add_summary_entry(ARGS "webenginequick-ui-delegates") +qt_configure_end_summary_section() diff --git a/src/webenginequick/doc/images/qtwebengine-architecture.png b/src/webenginequick/doc/images/qtwebengine-architecture.png Binary files differnew file mode 100644 index 000000000..979a0ad3f --- /dev/null +++ b/src/webenginequick/doc/images/qtwebengine-architecture.png diff --git a/src/webenginequick/doc/images/qtwebengine-model.png b/src/webenginequick/doc/images/qtwebengine-model.png Binary files differnew file mode 100644 index 000000000..0bbd556f1 --- /dev/null +++ b/src/webenginequick/doc/images/qtwebengine-model.png diff --git a/src/webenginequick/doc/images/qtwebengine-model.qmodel b/src/webenginequick/doc/images/qtwebengine-model.qmodel new file mode 100644 index 000000000..f3d5cb52b --- /dev/null +++ b/src/webenginequick/doc/images/qtwebengine-model.qmodel @@ -0,0 +1,626 @@ +<?xml version="1.0" encoding="UTF-8"?> +<qmt> + <project> + <uid>{b4b96dcf-b444-4b48-96a0-0ced0222fbe4}</uid> + <root-package> + <instance> + <MPackage> + <base-MObject> + <MObject> + <base-MElement> + <MElement> + <uid>{4b17cf3d-b45a-4ca8-b6c2-f0a9db0a0d9e}</uid> + </MElement> + </base-MElement> + <name>qtwebengine-model</name> + <children> + <handles> + <handles> + <qlist> + <item> + <handle> + <uid>{d0623590-2a20-468b-9ec5-51987e78ae47}</uid> + <target> + <instance type="MCanvasDiagram"> + <MCanvasDiagram> + <base-MDiagram> + <MDiagram> + <base-MObject> + <MObject> + <base-MElement> + <MElement> + <uid>{d0623590-2a20-468b-9ec5-51987e78ae47}</uid> + </MElement> + </base-MElement> + <name>qtwebengine-model</name> + </MObject> + </base-MObject> + <elements> + <qlist> + <item> + <instance type="DComponent"> + <DComponent> + <base-DObject> + <DObject> + <base-DElement> + <DElement> + <uid>{e1622bc8-530c-4d18-ba77-202bad11f1e0}</uid> + </DElement> + </base-DElement> + <object>{3507c733-97ee-4b84-835b-4d90f039ca72}</object> + <name>View</name> + <pos>x:260;y:70</pos> + <rect>x:-45;y:-30;w:90;h:60</rect> + <visual-role>0</visual-role> + </DObject> + </base-DObject> + </DComponent> + </instance> + </item> + <item> + <instance type="DComponent"> + <DComponent> + <base-DObject> + <DObject> + <base-DElement> + <DElement> + <uid>{0bb9e92a-910d-4a32-877b-fd7e37710f79}</uid> + </DElement> + </base-DElement> + <object>{ab5f0d96-cf38-430d-bef3-b7bd78952fdb}</object> + <name>Profile</name> + <pos>x:415;y:155</pos> + <rect>x:-50;y:-30;w:100;h:60</rect> + <visual-role>0</visual-role> + </DObject> + </base-DObject> + </DComponent> + </instance> + </item> + <item> + <instance type="DComponent"> + <DComponent> + <base-DObject> + <DObject> + <base-DElement> + <DElement> + <uid>{54c2f051-8fdb-48f2-b528-2caa8fd1f854}</uid> + </DElement> + </base-DElement> + <object>{999dd0f9-53f0-47bd-90ea-714c0dea50d7}</object> + <name>History</name> + <pos>x:110;y:155</pos> + <rect>x:-50;y:-30;w:100;h:60</rect> + <visual-role>0</visual-role> + </DObject> + </base-DObject> + </DComponent> + </instance> + </item> + <item> + <instance type="DComponent"> + <DComponent> + <base-DObject> + <DObject> + <base-DElement> + <DElement> + <uid>{ae2fed61-96c0-4755-aad1-2d02fbc6e36e}</uid> + </DElement> + </base-DElement> + <object>{b2ea9c4f-8b35-46c3-b2a5-3f22d72069e7}</object> + <name>Settings</name> + <pos>x:260;y:240</pos> + <rect>x:-50;y:-30;w:100;h:60</rect> + <visual-role>0</visual-role> + </DObject> + </base-DObject> + </DComponent> + </instance> + </item> + <item> + <instance type="DDependency"> + <DDependency> + <base-DRelation> + <DRelation> + <base-DElement> + <DElement> + <uid>{95fafacc-66c7-42d0-b27e-e92a69964adf}</uid> + </DElement> + </base-DElement> + <object>{e3429382-8484-481e-8690-792b1c1a257e}</object> + <a>{e1622bc8-530c-4d18-ba77-202bad11f1e0}</a> + <b>{0bb9e92a-910d-4a32-877b-fd7e37710f79}</b> + </DRelation> + </base-DRelation> + </DDependency> + </instance> + </item> + <item> + <instance type="DDependency"> + <DDependency> + <base-DRelation> + <DRelation> + <base-DElement> + <DElement> + <uid>{673bc9c1-a5ff-44ba-b9a6-d17807014a8e}</uid> + </DElement> + </base-DElement> + <object>{e505b9c3-2332-4056-b3f0-dbd71a5ccbae}</object> + <a>{e1622bc8-530c-4d18-ba77-202bad11f1e0}</a> + <b>{54c2f051-8fdb-48f2-b528-2caa8fd1f854}</b> + </DRelation> + </base-DRelation> + </DDependency> + </instance> + </item> + <item> + <instance type="DDependency"> + <DDependency> + <base-DRelation> + <DRelation> + <base-DElement> + <DElement> + <uid>{78e57691-4776-4e73-b0f0-232a1e80da10}</uid> + </DElement> + </base-DElement> + <object>{9cfdd75f-182e-4511-bf4c-19f30309318e}</object> + <a>{0bb9e92a-910d-4a32-877b-fd7e37710f79}</a> + <b>{ae2fed61-96c0-4755-aad1-2d02fbc6e36e}</b> + </DRelation> + </base-DRelation> + </DDependency> + </instance> + </item> + <item> + <instance type="DComponent"> + <DComponent> + <base-DObject> + <DObject> + <base-DElement> + <DElement> + <uid>{e76fa55e-b2df-4713-9fab-78434c3c7ed3}</uid> + </DElement> + </base-DElement> + <object>{ff72261f-19e3-4983-b10c-856f6070637b}</object> + <name>Action</name> + <pos>x:260;y:155</pos> + <rect>x:-50;y:-30;w:100;h:60</rect> + <visual-role>0</visual-role> + </DObject> + </base-DObject> + </DComponent> + </instance> + </item> + <item> + <instance type="DDependency"> + <DDependency> + <base-DRelation> + <DRelation> + <base-DElement> + <DElement> + <uid>{305524c2-f2c7-44ba-b30b-51fbfdc81063}</uid> + </DElement> + </base-DElement> + <object>{911f495e-313f-4b28-95d6-440b06a05a83}</object> + <a>{e1622bc8-530c-4d18-ba77-202bad11f1e0}</a> + <b>{e76fa55e-b2df-4713-9fab-78434c3c7ed3}</b> + </DRelation> + </base-DRelation> + </DDependency> + </instance> + </item> + <item> + <instance type="DComponent"> + <DComponent> + <base-DObject> + <DObject> + <base-DElement> + <DElement> + <uid>{28ea46b1-ce73-432f-89a6-a97821dbac59}</uid> + </DElement> + </base-DElement> + <object>{f1e3fd14-d433-4d95-8ea4-1c4b5aaf4334}</object> + <name>Script</name> + <pos>x:415;y:240</pos> + <rect>x:-45;y:-30;w:90;h:60</rect> + <visual-role>0</visual-role> + </DObject> + </base-DObject> + </DComponent> + </instance> + </item> + <item> + <instance type="DComponent"> + <DComponent> + <base-DObject> + <DObject> + <base-DElement> + <DElement> + <uid>{41e806b6-c8fd-4ae5-865d-db55feeb5570}</uid> + </DElement> + </base-DElement> + <object>{96788086-5e67-482c-ac8b-0f2a7f0729ff}</object> + <name>Cookie</name> + <pos>x:555;y:240</pos> + <rect>x:-50;y:-30;w:100;h:60</rect> + <visual-role>0</visual-role> + </DObject> + </base-DObject> + </DComponent> + </instance> + </item> + <item> + <instance type="DDependency"> + <DDependency> + <base-DRelation> + <DRelation> + <base-DElement> + <DElement> + <uid>{99a53c8d-8dc1-4ee5-83bf-ec2ff2677817}</uid> + </DElement> + </base-DElement> + <object>{dc399de7-f3b9-4071-84af-b6e5dfa3affe}</object> + <a>{0bb9e92a-910d-4a32-877b-fd7e37710f79}</a> + <b>{28ea46b1-ce73-432f-89a6-a97821dbac59}</b> + </DRelation> + </base-DRelation> + </DDependency> + </instance> + </item> + <item> + <instance type="DDependency"> + <DDependency> + <base-DRelation> + <DRelation> + <base-DElement> + <DElement> + <uid>{f3833f3d-d01b-4c7c-bfde-91d014aff654}</uid> + </DElement> + </base-DElement> + <object>{4dc013fb-ced4-4cc0-99e3-3f4a32acebf7}</object> + <a>{0bb9e92a-910d-4a32-877b-fd7e37710f79}</a> + <b>{41e806b6-c8fd-4ae5-865d-db55feeb5570}</b> + </DRelation> + </base-DRelation> + </DDependency> + </instance> + </item> + </qlist> + </elements> + <last-modified>1455888691589</last-modified> + <toolbarid>General</toolbarid> + </MDiagram> + </base-MDiagram> + </MCanvasDiagram> + </instance> + </target> + </handle> + </item> + <item> + <handle> + <uid>{3507c733-97ee-4b84-835b-4d90f039ca72}</uid> + <target> + <instance type="MComponent"> + <MComponent> + <base-MObject> + <MObject> + <base-MElement> + <MElement> + <uid>{3507c733-97ee-4b84-835b-4d90f039ca72}</uid> + </MElement> + </base-MElement> + <name>View</name> + <relations> + <handles> + <handles> + <qlist> + <item> + <handle> + <uid>{e3429382-8484-481e-8690-792b1c1a257e}</uid> + <target> + <instance type="MDependency"> + <MDependency> + <base-MRelation> + <MRelation> + <base-MElement> + <MElement> + <uid>{e3429382-8484-481e-8690-792b1c1a257e}</uid> + </MElement> + </base-MElement> + <a>{3507c733-97ee-4b84-835b-4d90f039ca72}</a> + <b>{ab5f0d96-cf38-430d-bef3-b7bd78952fdb}</b> + </MRelation> + </base-MRelation> + </MDependency> + </instance> + </target> + </handle> + </item> + <item> + <handle> + <uid>{e505b9c3-2332-4056-b3f0-dbd71a5ccbae}</uid> + <target> + <instance type="MDependency"> + <MDependency> + <base-MRelation> + <MRelation> + <base-MElement> + <MElement> + <uid>{e505b9c3-2332-4056-b3f0-dbd71a5ccbae}</uid> + </MElement> + </base-MElement> + <a>{3507c733-97ee-4b84-835b-4d90f039ca72}</a> + <b>{999dd0f9-53f0-47bd-90ea-714c0dea50d7}</b> + </MRelation> + </base-MRelation> + </MDependency> + </instance> + </target> + </handle> + </item> + <item> + <handle> + <uid>{4d826dd3-e455-46f3-8dfc-bb74551f3f00}</uid> + <target> + <instance type="MDependency"> + <MDependency> + <base-MRelation> + <MRelation> + <base-MElement> + <MElement> + <uid>{4d826dd3-e455-46f3-8dfc-bb74551f3f00}</uid> + </MElement> + </base-MElement> + <a>{3507c733-97ee-4b84-835b-4d90f039ca72}</a> + <b>{b2ea9c4f-8b35-46c3-b2a5-3f22d72069e7}</b> + </MRelation> + </base-MRelation> + </MDependency> + </instance> + </target> + </handle> + </item> + <item> + <handle> + <uid>{911f495e-313f-4b28-95d6-440b06a05a83}</uid> + <target> + <instance type="MDependency"> + <MDependency> + <base-MRelation> + <MRelation> + <base-MElement> + <MElement> + <uid>{911f495e-313f-4b28-95d6-440b06a05a83}</uid> + </MElement> + </base-MElement> + <a>{3507c733-97ee-4b84-835b-4d90f039ca72}</a> + <b>{ff72261f-19e3-4983-b10c-856f6070637b}</b> + </MRelation> + </base-MRelation> + </MDependency> + </instance> + </target> + </handle> + </item> + </qlist> + </handles> + </handles> + </relations> + </MObject> + </base-MObject> + </MComponent> + </instance> + </target> + </handle> + </item> + <item> + <handle> + <uid>{ab5f0d96-cf38-430d-bef3-b7bd78952fdb}</uid> + <target> + <instance type="MComponent"> + <MComponent> + <base-MObject> + <MObject> + <base-MElement> + <MElement> + <uid>{ab5f0d96-cf38-430d-bef3-b7bd78952fdb}</uid> + </MElement> + </base-MElement> + <name>Profile</name> + <relations> + <handles> + <handles> + <qlist> + <item> + <handle> + <uid>{9cfdd75f-182e-4511-bf4c-19f30309318e}</uid> + <target> + <instance type="MDependency"> + <MDependency> + <base-MRelation> + <MRelation> + <base-MElement> + <MElement> + <uid>{9cfdd75f-182e-4511-bf4c-19f30309318e}</uid> + </MElement> + </base-MElement> + <a>{ab5f0d96-cf38-430d-bef3-b7bd78952fdb}</a> + <b>{b2ea9c4f-8b35-46c3-b2a5-3f22d72069e7}</b> + </MRelation> + </base-MRelation> + </MDependency> + </instance> + </target> + </handle> + </item> + <item> + <handle> + <uid>{dc399de7-f3b9-4071-84af-b6e5dfa3affe}</uid> + <target> + <instance type="MDependency"> + <MDependency> + <base-MRelation> + <MRelation> + <base-MElement> + <MElement> + <uid>{dc399de7-f3b9-4071-84af-b6e5dfa3affe}</uid> + </MElement> + </base-MElement> + <a>{ab5f0d96-cf38-430d-bef3-b7bd78952fdb}</a> + <b>{f1e3fd14-d433-4d95-8ea4-1c4b5aaf4334}</b> + </MRelation> + </base-MRelation> + </MDependency> + </instance> + </target> + </handle> + </item> + <item> + <handle> + <uid>{4dc013fb-ced4-4cc0-99e3-3f4a32acebf7}</uid> + <target> + <instance type="MDependency"> + <MDependency> + <base-MRelation> + <MRelation> + <base-MElement> + <MElement> + <uid>{4dc013fb-ced4-4cc0-99e3-3f4a32acebf7}</uid> + </MElement> + </base-MElement> + <a>{ab5f0d96-cf38-430d-bef3-b7bd78952fdb}</a> + <b>{96788086-5e67-482c-ac8b-0f2a7f0729ff}</b> + </MRelation> + </base-MRelation> + </MDependency> + </instance> + </target> + </handle> + </item> + </qlist> + </handles> + </handles> + </relations> + </MObject> + </base-MObject> + </MComponent> + </instance> + </target> + </handle> + </item> + <item> + <handle> + <uid>{999dd0f9-53f0-47bd-90ea-714c0dea50d7}</uid> + <target> + <instance type="MComponent"> + <MComponent> + <base-MObject> + <MObject> + <base-MElement> + <MElement> + <uid>{999dd0f9-53f0-47bd-90ea-714c0dea50d7}</uid> + </MElement> + </base-MElement> + <name>History</name> + </MObject> + </base-MObject> + </MComponent> + </instance> + </target> + </handle> + </item> + <item> + <handle> + <uid>{b2ea9c4f-8b35-46c3-b2a5-3f22d72069e7}</uid> + <target> + <instance type="MComponent"> + <MComponent> + <base-MObject> + <MObject> + <base-MElement> + <MElement> + <uid>{b2ea9c4f-8b35-46c3-b2a5-3f22d72069e7}</uid> + </MElement> + </base-MElement> + <name>Settings</name> + </MObject> + </base-MObject> + </MComponent> + </instance> + </target> + </handle> + </item> + <item> + <handle> + <uid>{ff72261f-19e3-4983-b10c-856f6070637b}</uid> + <target> + <instance type="MComponent"> + <MComponent> + <base-MObject> + <MObject> + <base-MElement> + <MElement> + <uid>{ff72261f-19e3-4983-b10c-856f6070637b}</uid> + </MElement> + </base-MElement> + <name>Action</name> + </MObject> + </base-MObject> + </MComponent> + </instance> + </target> + </handle> + </item> + <item> + <handle> + <uid>{f1e3fd14-d433-4d95-8ea4-1c4b5aaf4334}</uid> + <target> + <instance type="MComponent"> + <MComponent> + <base-MObject> + <MObject> + <base-MElement> + <MElement> + <uid>{f1e3fd14-d433-4d95-8ea4-1c4b5aaf4334}</uid> + </MElement> + </base-MElement> + <name>Script</name> + </MObject> + </base-MObject> + </MComponent> + </instance> + </target> + </handle> + </item> + <item> + <handle> + <uid>{96788086-5e67-482c-ac8b-0f2a7f0729ff}</uid> + <target> + <instance type="MComponent"> + <MComponent> + <base-MObject> + <MObject> + <base-MElement> + <MElement> + <uid>{96788086-5e67-482c-ac8b-0f2a7f0729ff}</uid> + </MElement> + </base-MElement> + <name>Cookie</name> + </MObject> + </base-MObject> + </MComponent> + </instance> + </target> + </handle> + </item> + </qlist> + </handles> + </handles> + </children> + </MObject> + </base-MObject> + </MPackage> + </instance> + </root-package> + </project> +</qmt> diff --git a/src/webenginequick/doc/images/qtwebengine-modules-model.qmodel b/src/webenginequick/doc/images/qtwebengine-modules-model.qmodel new file mode 100644 index 000000000..c1d64b617 --- /dev/null +++ b/src/webenginequick/doc/images/qtwebengine-modules-model.qmodel @@ -0,0 +1,500 @@ +<?xml version="1.0" encoding="UTF-8"?> +<qmt> + <project> + <uid>{4a2bfe98-50e2-435d-8702-93dc2ccbd56b}</uid> + <root-package> + <instance> + <MPackage> + <base-MObject> + <MObject> + <base-MElement> + <MElement> + <uid>{11ff33c5-f533-494d-9add-55ea216b97a6}</uid> + </MElement> + </base-MElement> + <name>qtwebengine-modules-model</name> + <children> + <handles> + <handles> + <qlist> + <item> + <handle> + <uid>{9e8325b8-5731-4c87-9203-fe941456ee06}</uid> + <target> + <instance type="MCanvasDiagram"> + <MCanvasDiagram> + <base-MDiagram> + <MDiagram> + <base-MObject> + <MObject> + <base-MElement> + <MElement> + <uid>{9e8325b8-5731-4c87-9203-fe941456ee06}</uid> + </MElement> + </base-MElement> + <name>qtwebengine-modules-model</name> + </MObject> + </base-MObject> + <elements> + <qlist> + <item> + <instance type="DPackage"> + <DPackage> + <base-DObject> + <DObject> + <base-DElement> + <DElement> + <uid>{aee48ad9-14be-47bb-8ebf-1a9b44f1e219}</uid> + </DElement> + </base-DElement> + <object>{4d3871a4-ad9d-4b1a-ab68-acfce8ba5f00}</object> + <name>Qt WebEngine Module</name> + <pos>x:300;y:70</pos> + <rect>x:-275;y:-145;w:550;h:290</rect> + <auto-sized>false</auto-sized> + <visual-role>0</visual-role> + <stereotype-display>0</stereotype-display> + </DObject> + </base-DObject> + </DPackage> + </instance> + </item> + <item> + <instance type="DPackage"> + <DPackage> + <base-DObject> + <DObject> + <base-DElement> + <DElement> + <uid>{b667049f-5302-4e68-8679-c26a7c4c37af}</uid> + </DElement> + </base-DElement> + <object>{71104fca-42f0-4145-bf3a-afed38493c8b}</object> + <context>Qt WebEngine Module</context> + <name>Qt WebEngine </name> + <pos>x:300;y:15</pos> + <rect>x:-75;y:-35;w:150;h:70</rect> + <auto-sized>false</auto-sized> + <visual-role>0</visual-role> + </DObject> + </base-DObject> + </DPackage> + </instance> + </item> + <item> + <instance type="DPackage"> + <DPackage> + <base-DObject> + <DObject> + <base-DElement> + <DElement> + <uid>{6d84908c-9500-4b4f-95b8-b723ff8f2fc3}</uid> + </DElement> + </base-DElement> + <object>{8e8c6646-1175-4ee1-aa02-cd5669cdf92a}</object> + <context>Qt WebEngine Module</context> + <name> Qt WebEngine Widgets</name> + <pos>x:105;y:15</pos> + <rect>x:-75;y:-35;w:150;h:70</rect> + <auto-sized>false</auto-sized> + <visual-role>0</visual-role> + </DObject> + </base-DObject> + </DPackage> + </instance> + </item> + <item> + <instance type="DPackage"> + <DPackage> + <base-DObject> + <DObject> + <base-DElement> + <DElement> + <uid>{d1260089-4eb6-4465-ac5f-e36ba1ef2311}</uid> + </DElement> + </base-DElement> + <object>{c0946aaa-51df-48db-9ceb-351cd32089be}</object> + <context>Qt WebEngine Module</context> + <name> Qt WebEngine Process</name> + <pos>x:495;y:15</pos> + <rect>x:-75;y:-35;w:150;h:70</rect> + <visual-role>0</visual-role> + </DObject> + </base-DObject> + </DPackage> + </instance> + </item> + <item> + <instance type="DPackage"> + <DPackage> + <base-DObject> + <DObject> + <base-DElement> + <DElement> + <uid>{7e01513b-4cfc-4154-b445-a9b341b392a3}</uid> + </DElement> + </base-DElement> + <object>{6ee7f00e-5dc3-4f45-a3ca-428390b4c74c}</object> + <context>Qt WebEngine Module</context> + <name>Qt WebEngine Core</name> + <pos>x:300;y:150</pos> + <rect>x:-270;y:-60;w:540;h:120</rect> + <auto-sized>false</auto-sized> + <visual-role>0</visual-role> + </DObject> + </base-DObject> + </DPackage> + </instance> + </item> + <item> + <instance type="DPackage"> + <DPackage> + <base-DObject> + <DObject> + <base-DElement> + <DElement> + <uid>{620a2a3d-3a6c-4afc-a9ba-e2a0651b81b8}</uid> + </DElement> + </base-DElement> + <object>{ce1e329b-b2ec-465f-bbc7-3cc75160da1a}</object> + <context>Qt WebEngine Core</context> + <name>Chromium</name> + <pos>x:300;y:165</pos> + <rect>x:-260;y:-35;w:520;h:70</rect> + <auto-sized>false</auto-sized> + <visual-role>0</visual-role> + </DObject> + </base-DObject> + </DPackage> + </instance> + </item> + <item> + <instance type="DDependency"> + <DDependency> + <base-DRelation> + <DRelation> + <base-DElement> + <DElement> + <uid>{d0b02baa-0ce3-437e-a962-0896efb0b2d0}</uid> + </DElement> + </base-DElement> + <object>{342a09ff-ab96-40d2-b9f9-300d1f2a067b}</object> + <a>{6d84908c-9500-4b4f-95b8-b723ff8f2fc3}</a> + <b>{7e01513b-4cfc-4154-b445-a9b341b392a3}</b> + </DRelation> + </base-DRelation> + </DDependency> + </instance> + </item> + <item> + <instance type="DDependency"> + <DDependency> + <base-DRelation> + <DRelation> + <base-DElement> + <DElement> + <uid>{e59a5c27-7bda-44f6-8b7d-a729c2d04ff5}</uid> + </DElement> + </base-DElement> + <object>{45bf7ccd-aafc-4ec1-a846-bb2661aa9def}</object> + <a>{b667049f-5302-4e68-8679-c26a7c4c37af}</a> + <b>{7e01513b-4cfc-4154-b445-a9b341b392a3}</b> + </DRelation> + </base-DRelation> + </DDependency> + </instance> + </item> + <item> + <instance type="DDependency"> + <DDependency> + <base-DRelation> + <DRelation> + <base-DElement> + <DElement> + <uid>{8ae66be6-ad8a-442f-a85d-58e53a684249}</uid> + </DElement> + </base-DElement> + <object>{6875416f-210d-4957-b0dc-d1a92a4238ef}</object> + <a>{d1260089-4eb6-4465-ac5f-e36ba1ef2311}</a> + <b>{7e01513b-4cfc-4154-b445-a9b341b392a3}</b> + </DRelation> + </base-DRelation> + </DDependency> + </instance> + </item> + </qlist> + </elements> + <last-modified>1469021602971</last-modified> + <toolbarid>General</toolbarid> + </MDiagram> + </base-MDiagram> + </MCanvasDiagram> + </instance> + </target> + </handle> + </item> + <item> + <handle> + <uid>{4d3871a4-ad9d-4b1a-ab68-acfce8ba5f00}</uid> + <target> + <instance type="MPackage"> + <MPackage> + <base-MObject> + <MObject> + <base-MElement> + <MElement> + <uid>{4d3871a4-ad9d-4b1a-ab68-acfce8ba5f00}</uid> + </MElement> + </base-MElement> + <name>Qt WebEngine Module</name> + <children> + <handles> + <handles> + <qlist> + <item> + <handle> + <uid>{71104fca-42f0-4145-bf3a-afed38493c8b}</uid> + <target> + <instance type="MPackage"> + <MPackage> + <base-MObject> + <MObject> + <base-MElement> + <MElement> + <uid>{71104fca-42f0-4145-bf3a-afed38493c8b}</uid> + </MElement> + </base-MElement> + <name>Qt WebEngine </name> + <relations> + <handles> + <handles> + <qlist> + <item> + <handle> + <uid>{45bf7ccd-aafc-4ec1-a846-bb2661aa9def}</uid> + <target> + <instance type="MDependency"> + <MDependency> + <base-MRelation> + <MRelation> + <base-MElement> + <MElement> + <uid>{45bf7ccd-aafc-4ec1-a846-bb2661aa9def}</uid> + </MElement> + </base-MElement> + <a>{71104fca-42f0-4145-bf3a-afed38493c8b}</a> + <b>{6ee7f00e-5dc3-4f45-a3ca-428390b4c74c}</b> + </MRelation> + </base-MRelation> + </MDependency> + </instance> + </target> + </handle> + </item> + </qlist> + </handles> + </handles> + </relations> + </MObject> + </base-MObject> + </MPackage> + </instance> + </target> + </handle> + </item> + <item> + <handle> + <uid>{8e8c6646-1175-4ee1-aa02-cd5669cdf92a}</uid> + <target> + <instance type="MPackage"> + <MPackage> + <base-MObject> + <MObject> + <base-MElement> + <MElement> + <uid>{8e8c6646-1175-4ee1-aa02-cd5669cdf92a}</uid> + </MElement> + </base-MElement> + <name> Qt WebEngine Widgets</name> + <relations> + <handles> + <handles> + <qlist> + <item> + <handle> + <uid>{342a09ff-ab96-40d2-b9f9-300d1f2a067b}</uid> + <target> + <instance type="MDependency"> + <MDependency> + <base-MRelation> + <MRelation> + <base-MElement> + <MElement> + <uid>{342a09ff-ab96-40d2-b9f9-300d1f2a067b}</uid> + </MElement> + </base-MElement> + <a>{8e8c6646-1175-4ee1-aa02-cd5669cdf92a}</a> + <b>{6ee7f00e-5dc3-4f45-a3ca-428390b4c74c}</b> + </MRelation> + </base-MRelation> + </MDependency> + </instance> + </target> + </handle> + </item> + <item> + <handle> + <uid>{483712c1-3ec0-4271-b02e-b268de07897b}</uid> + <target> + <instance type="MDependency"> + <MDependency> + <base-MRelation> + <MRelation> + <base-MElement> + <MElement> + <uid>{483712c1-3ec0-4271-b02e-b268de07897b}</uid> + </MElement> + </base-MElement> + <a>{8e8c6646-1175-4ee1-aa02-cd5669cdf92a}</a> + <b>{71104fca-42f0-4145-bf3a-afed38493c8b}</b> + </MRelation> + </base-MRelation> + </MDependency> + </instance> + </target> + </handle> + </item> + </qlist> + </handles> + </handles> + </relations> + </MObject> + </base-MObject> + </MPackage> + </instance> + </target> + </handle> + </item> + <item> + <handle> + <uid>{c0946aaa-51df-48db-9ceb-351cd32089be}</uid> + <target> + <instance type="MPackage"> + <MPackage> + <base-MObject> + <MObject> + <base-MElement> + <MElement> + <uid>{c0946aaa-51df-48db-9ceb-351cd32089be}</uid> + </MElement> + </base-MElement> + <name> Qt WebEngine Process</name> + <relations> + <handles> + <handles> + <qlist> + <item> + <handle> + <uid>{6875416f-210d-4957-b0dc-d1a92a4238ef}</uid> + <target> + <instance type="MDependency"> + <MDependency> + <base-MRelation> + <MRelation> + <base-MElement> + <MElement> + <uid>{6875416f-210d-4957-b0dc-d1a92a4238ef}</uid> + </MElement> + </base-MElement> + <a>{c0946aaa-51df-48db-9ceb-351cd32089be}</a> + <b>{6ee7f00e-5dc3-4f45-a3ca-428390b4c74c}</b> + </MRelation> + </base-MRelation> + </MDependency> + </instance> + </target> + </handle> + </item> + </qlist> + </handles> + </handles> + </relations> + </MObject> + </base-MObject> + </MPackage> + </instance> + </target> + </handle> + </item> + <item> + <handle> + <uid>{6ee7f00e-5dc3-4f45-a3ca-428390b4c74c}</uid> + <target> + <instance type="MPackage"> + <MPackage> + <base-MObject> + <MObject> + <base-MElement> + <MElement> + <uid>{6ee7f00e-5dc3-4f45-a3ca-428390b4c74c}</uid> + </MElement> + </base-MElement> + <name>Qt WebEngine Core</name> + <children> + <handles> + <handles> + <qlist> + <item> + <handle> + <uid>{ce1e329b-b2ec-465f-bbc7-3cc75160da1a}</uid> + <target> + <instance type="MPackage"> + <MPackage> + <base-MObject> + <MObject> + <base-MElement> + <MElement> + <uid>{ce1e329b-b2ec-465f-bbc7-3cc75160da1a}</uid> + </MElement> + </base-MElement> + <name>Chromium</name> + </MObject> + </base-MObject> + </MPackage> + </instance> + </target> + </handle> + </item> + </qlist> + </handles> + </handles> + </children> + </MObject> + </base-MObject> + </MPackage> + </instance> + </target> + </handle> + </item> + </qlist> + </handles> + </handles> + </children> + </MObject> + </base-MObject> + </MPackage> + </instance> + </target> + </handle> + </item> + </qlist> + </handles> + </handles> + </children> + </MObject> + </base-MObject> + </MPackage> + </instance> + </root-package> + </project> +</qmt> diff --git a/src/webenginequick/doc/images/qtwebenginewidgets-model.png b/src/webenginequick/doc/images/qtwebenginewidgets-model.png Binary files differnew file mode 100644 index 000000000..c334b84c9 --- /dev/null +++ b/src/webenginequick/doc/images/qtwebenginewidgets-model.png diff --git a/src/webenginequick/doc/images/qtwebenginewidgets-model.qmodel b/src/webenginequick/doc/images/qtwebenginewidgets-model.qmodel new file mode 100644 index 000000000..aa59f7b8f --- /dev/null +++ b/src/webenginequick/doc/images/qtwebenginewidgets-model.qmodel @@ -0,0 +1,789 @@ +<?xml version="1.0" encoding="UTF-8"?> +<qmt> + <project> + <uid>{388ed80a-d45a-4746-9b42-b201bdfbe66d}</uid> + <root-package> + <instance> + <MPackage> + <base-MObject> + <MObject> + <base-MElement> + <MElement> + <uid>{cf413898-e1a1-48a2-be84-dee757d150e1}</uid> + </MElement> + </base-MElement> + <name>qtwebenginewidgets-model</name> + <children> + <handles> + <handles> + <qlist> + <item> + <handle> + <uid>{cb7c93b6-ed69-4e54-bca7-23edd2432e88}</uid> + <target> + <instance type="MCanvasDiagram"> + <MCanvasDiagram> + <base-MDiagram> + <MDiagram> + <base-MObject> + <MObject> + <base-MElement> + <MElement> + <uid>{cb7c93b6-ed69-4e54-bca7-23edd2432e88}</uid> + </MElement> + </base-MElement> + <name>qtwebenginewidgets-model</name> + </MObject> + </base-MObject> + <elements> + <qlist> + <item> + <instance type="DComponent"> + <DComponent> + <base-DObject> + <DObject> + <base-DElement> + <DElement> + <uid>{9d9a12d1-d237-4d4f-9b55-bdbbc99bd2b1}</uid> + </DElement> + </base-DElement> + <object>{1a4983f6-27db-4f8c-90ed-f72df621c50f}</object> + <name>View</name> + <pos>x:235;y:-280</pos> + <rect>x:-45;y:-30;w:90;h:60</rect> + <visual-role>0</visual-role> + </DObject> + </base-DObject> + </DComponent> + </instance> + </item> + <item> + <instance type="DComponent"> + <DComponent> + <base-DObject> + <DObject> + <base-DElement> + <DElement> + <uid>{81687d47-fbb1-4843-a394-7d7e5e57a2ff}</uid> + </DElement> + </base-DElement> + <object>{e9446d69-de53-47ab-974e-1b8ae8b6edd7}</object> + <name>Page</name> + <pos>x:235;y:-195</pos> + <rect>x:-45;y:-30;w:90;h:60</rect> + <visual-role>0</visual-role> + </DObject> + </base-DObject> + </DComponent> + </instance> + </item> + <item> + <instance type="DComponent"> + <DComponent> + <base-DObject> + <DObject> + <base-DElement> + <DElement> + <uid>{e6d92a82-f898-448f-945e-26b508249746}</uid> + </DElement> + </base-DElement> + <object>{99e69e48-e844-4fc0-942c-aacef280c616}</object> + <name>History</name> + <pos>x:90;y:-110</pos> + <rect>x:-50;y:-30;w:100;h:60</rect> + <visual-role>0</visual-role> + </DObject> + </base-DObject> + </DComponent> + </instance> + </item> + <item> + <instance type="DComponent"> + <DComponent> + <base-DObject> + <DObject> + <base-DElement> + <DElement> + <uid>{9ba8a864-bd21-48e5-9df4-c7065d3ab474}</uid> + </DElement> + </base-DElement> + <object>{6b572233-bf3a-43a2-bfe2-e61d57a59a2e}</object> + <name>Settings</name> + <pos>x:235;y:-20</pos> + <rect>x:-50;y:-30;w:100;h:60</rect> + <visual-role>0</visual-role> + </DObject> + </base-DObject> + </DComponent> + </instance> + </item> + <item> + <instance type="DComponent"> + <DComponent> + <base-DObject> + <DObject> + <base-DElement> + <DElement> + <uid>{62872913-7080-421b-b12c-d3c094faa37d}</uid> + </DElement> + </base-DElement> + <object>{8afe2dfe-878f-4c40-9f07-c6128611f853}</object> + <name>Profile</name> + <pos>x:380;y:-110</pos> + <rect>x:-50;y:-30;w:100;h:60</rect> + <visual-role>0</visual-role> + </DObject> + </base-DObject> + </DComponent> + </instance> + </item> + <item> + <instance type="DDependency"> + <DDependency> + <base-DRelation> + <DRelation> + <base-DElement> + <DElement> + <uid>{54a21438-6274-4484-9225-97a47d3514ea}</uid> + </DElement> + </base-DElement> + <object>{8e94476c-6a26-4bbc-b134-54a7203a0242}</object> + <a>{9d9a12d1-d237-4d4f-9b55-bdbbc99bd2b1}</a> + <b>{81687d47-fbb1-4843-a394-7d7e5e57a2ff}</b> + </DRelation> + </base-DRelation> + </DDependency> + </instance> + </item> + <item> + <instance type="DDependency"> + <DDependency> + <base-DRelation> + <DRelation> + <base-DElement> + <DElement> + <uid>{b3f6b700-e506-471b-9341-78a57b55fb20}</uid> + </DElement> + </base-DElement> + <object>{48d2b9ae-8462-4c93-9772-77f2520e2bcb}</object> + <a>{81687d47-fbb1-4843-a394-7d7e5e57a2ff}</a> + <b>{e6d92a82-f898-448f-945e-26b508249746}</b> + </DRelation> + </base-DRelation> + </DDependency> + </instance> + </item> + <item> + <instance type="DDependency"> + <DDependency> + <base-DRelation> + <DRelation> + <base-DElement> + <DElement> + <uid>{5870be46-b8c5-480b-89d0-2ecd38fea9e1}</uid> + </DElement> + </base-DElement> + <object>{2ec57f83-da38-4ed1-970c-d416a5f76425}</object> + <a>{81687d47-fbb1-4843-a394-7d7e5e57a2ff}</a> + <b>{62872913-7080-421b-b12c-d3c094faa37d}</b> + </DRelation> + </base-DRelation> + </DDependency> + </instance> + </item> + <item> + <instance type="DDependency"> + <DDependency> + <base-DRelation> + <DRelation> + <base-DElement> + <DElement> + <uid>{9140249c-7a62-4e4d-846a-398e794e34c6}</uid> + </DElement> + </base-DElement> + <object>{9c6691bd-75e5-40af-a662-ecb04e60744e}</object> + <a>{62872913-7080-421b-b12c-d3c094faa37d}</a> + <b>{9ba8a864-bd21-48e5-9df4-c7065d3ab474}</b> + </DRelation> + </base-DRelation> + </DDependency> + </instance> + </item> + <item> + <instance type="DComponent"> + <DComponent> + <base-DObject> + <DObject> + <base-DElement> + <DElement> + <uid>{97fe6f5f-a947-4c62-880d-e2d9258814dd}</uid> + </DElement> + </base-DElement> + <object>{2dfae517-4615-42b9-bb33-63369291468f}</object> + <name>Script</name> + <pos>x:380;y:-20</pos> + <rect>x:-45;y:-30;w:90;h:60</rect> + <visual-role>0</visual-role> + </DObject> + </base-DObject> + </DComponent> + </instance> + </item> + <item> + <instance type="DComponent"> + <DComponent> + <base-DObject> + <DObject> + <base-DElement> + <DElement> + <uid>{3cb4f4a2-0a1d-4adb-8b72-c438a8102a2b}</uid> + </DElement> + </base-DElement> + <object>{8f64c8e2-637e-482e-8565-1bbdcd203709}</object> + <name>Action</name> + <pos>x:235;y:-110</pos> + <rect>x:-50;y:-30;w:100;h:60</rect> + <visual-role>0</visual-role> + </DObject> + </base-DObject> + </DComponent> + </instance> + </item> + <item> + <instance type="DDependency"> + <DDependency> + <base-DRelation> + <DRelation> + <base-DElement> + <DElement> + <uid>{c962daa4-09b9-411d-a0d1-d1c7b9bd1489}</uid> + </DElement> + </base-DElement> + <object>{31cff752-95b7-4994-a5fc-8794dd8a013f}</object> + <a>{62872913-7080-421b-b12c-d3c094faa37d}</a> + <b>{97fe6f5f-a947-4c62-880d-e2d9258814dd}</b> + </DRelation> + </base-DRelation> + </DDependency> + </instance> + </item> + <item> + <instance type="DDependency"> + <DDependency> + <base-DRelation> + <DRelation> + <base-DElement> + <DElement> + <uid>{a8f88107-5699-4e25-8945-1113d642fdd0}</uid> + </DElement> + </base-DElement> + <object>{acca28ee-b184-4cbe-9aaa-befeac08c3bd}</object> + <a>{81687d47-fbb1-4843-a394-7d7e5e57a2ff}</a> + <b>{3cb4f4a2-0a1d-4adb-8b72-c438a8102a2b}</b> + </DRelation> + </base-DRelation> + </DDependency> + </instance> + </item> + <item> + <instance type="DComponent"> + <DComponent> + <base-DObject> + <DObject> + <base-DElement> + <DElement> + <uid>{6208171a-1515-424a-bb4e-5f115b4c21fa}</uid> + </DElement> + </base-DElement> + <object>{b19ba8d3-84ca-4718-b62c-575aa5d95c95}</object> + <name>Cookie</name> + <pos>x:525;y:-20</pos> + <rect>x:-50;y:-30;w:100;h:60</rect> + <visual-role>0</visual-role> + </DObject> + </base-DObject> + </DComponent> + </instance> + </item> + <item> + <instance type="DDependency"> + <DDependency> + <base-DRelation> + <DRelation> + <base-DElement> + <DElement> + <uid>{57732b45-63fc-4d87-91fe-c9e9cbdd69ee}</uid> + </DElement> + </base-DElement> + <object>{b98164e7-ff69-40e7-ac1b-fe4985f451e7}</object> + <a>{62872913-7080-421b-b12c-d3c094faa37d}</a> + <b>{6208171a-1515-424a-bb4e-5f115b4c21fa}</b> + </DRelation> + </base-DRelation> + </DDependency> + </instance> + </item> + </qlist> + </elements> + <last-modified>1455889165432</last-modified> + <toolbarid>General</toolbarid> + </MDiagram> + </base-MDiagram> + </MCanvasDiagram> + </instance> + </target> + </handle> + </item> + <item> + <handle> + <uid>{1a4983f6-27db-4f8c-90ed-f72df621c50f}</uid> + <target> + <instance type="MComponent"> + <MComponent> + <base-MObject> + <MObject> + <base-MElement> + <MElement> + <uid>{1a4983f6-27db-4f8c-90ed-f72df621c50f}</uid> + </MElement> + </base-MElement> + <name>View</name> + <relations> + <handles> + <handles> + <qlist> + <item> + <handle> + <uid>{8e94476c-6a26-4bbc-b134-54a7203a0242}</uid> + <target> + <instance type="MDependency"> + <MDependency> + <base-MRelation> + <MRelation> + <base-MElement> + <MElement> + <uid>{8e94476c-6a26-4bbc-b134-54a7203a0242}</uid> + </MElement> + </base-MElement> + <a>{1a4983f6-27db-4f8c-90ed-f72df621c50f}</a> + <b>{e9446d69-de53-47ab-974e-1b8ae8b6edd7}</b> + </MRelation> + </base-MRelation> + </MDependency> + </instance> + </target> + </handle> + </item> + </qlist> + </handles> + </handles> + </relations> + </MObject> + </base-MObject> + </MComponent> + </instance> + </target> + </handle> + </item> + <item> + <handle> + <uid>{e9446d69-de53-47ab-974e-1b8ae8b6edd7}</uid> + <target> + <instance type="MComponent"> + <MComponent> + <base-MObject> + <MObject> + <base-MElement> + <MElement> + <uid>{e9446d69-de53-47ab-974e-1b8ae8b6edd7}</uid> + </MElement> + </base-MElement> + <name>Page</name> + <relations> + <handles> + <handles> + <qlist> + <item> + <handle> + <uid>{48d2b9ae-8462-4c93-9772-77f2520e2bcb}</uid> + <target> + <instance type="MDependency"> + <MDependency> + <base-MRelation> + <MRelation> + <base-MElement> + <MElement> + <uid>{48d2b9ae-8462-4c93-9772-77f2520e2bcb}</uid> + </MElement> + </base-MElement> + <a>{e9446d69-de53-47ab-974e-1b8ae8b6edd7}</a> + <b>{99e69e48-e844-4fc0-942c-aacef280c616}</b> + </MRelation> + </base-MRelation> + </MDependency> + </instance> + </target> + </handle> + </item> + <item> + <handle> + <uid>{2ec57f83-da38-4ed1-970c-d416a5f76425}</uid> + <target> + <instance type="MDependency"> + <MDependency> + <base-MRelation> + <MRelation> + <base-MElement> + <MElement> + <uid>{2ec57f83-da38-4ed1-970c-d416a5f76425}</uid> + </MElement> + </base-MElement> + <a>{e9446d69-de53-47ab-974e-1b8ae8b6edd7}</a> + <b>{8afe2dfe-878f-4c40-9f07-c6128611f853}</b> + </MRelation> + </base-MRelation> + </MDependency> + </instance> + </target> + </handle> + </item> + <item> + <handle> + <uid>{30d6d5e4-eb6b-4816-817d-5a921f823dae}</uid> + <target> + <instance type="MDependency"> + <MDependency> + <base-MRelation> + <MRelation> + <base-MElement> + <MElement> + <uid>{30d6d5e4-eb6b-4816-817d-5a921f823dae}</uid> + </MElement> + </base-MElement> + <a>{e9446d69-de53-47ab-974e-1b8ae8b6edd7}</a> + <b>{6b572233-bf3a-43a2-bfe2-e61d57a59a2e}</b> + </MRelation> + </base-MRelation> + </MDependency> + </instance> + </target> + </handle> + </item> + <item> + <handle> + <uid>{0011e11e-283e-4ad9-94b0-749d4465eac8}</uid> + <target> + <instance type="MDependency"> + <MDependency> + <base-MRelation> + <MRelation> + <base-MElement> + <MElement> + <uid>{0011e11e-283e-4ad9-94b0-749d4465eac8}</uid> + </MElement> + </base-MElement> + <a>{e9446d69-de53-47ab-974e-1b8ae8b6edd7}</a> + <b>{2dfae517-4615-42b9-bb33-63369291468f}</b> + </MRelation> + </base-MRelation> + </MDependency> + </instance> + </target> + </handle> + </item> + <item> + <handle> + <uid>{c354a766-0dba-439d-9f6c-538772784181}</uid> + <target> + <instance type="MDependency"> + <MDependency> + <base-MRelation> + <MRelation> + <base-MElement> + <MElement> + <uid>{c354a766-0dba-439d-9f6c-538772784181}</uid> + </MElement> + </base-MElement> + <a>{e9446d69-de53-47ab-974e-1b8ae8b6edd7}</a> + <b>{8f64c8e2-637e-482e-8565-1bbdcd203709}</b> + </MRelation> + </base-MRelation> + </MDependency> + </instance> + </target> + </handle> + </item> + <item> + <handle> + <uid>{acca28ee-b184-4cbe-9aaa-befeac08c3bd}</uid> + <target> + <instance type="MDependency"> + <MDependency> + <base-MRelation> + <MRelation> + <base-MElement> + <MElement> + <uid>{acca28ee-b184-4cbe-9aaa-befeac08c3bd}</uid> + </MElement> + </base-MElement> + <a>{e9446d69-de53-47ab-974e-1b8ae8b6edd7}</a> + <b>{8f64c8e2-637e-482e-8565-1bbdcd203709}</b> + </MRelation> + </base-MRelation> + </MDependency> + </instance> + </target> + </handle> + </item> + </qlist> + </handles> + </handles> + </relations> + </MObject> + </base-MObject> + </MComponent> + </instance> + </target> + </handle> + </item> + <item> + <handle> + <uid>{99e69e48-e844-4fc0-942c-aacef280c616}</uid> + <target> + <instance type="MComponent"> + <MComponent> + <base-MObject> + <MObject> + <base-MElement> + <MElement> + <uid>{99e69e48-e844-4fc0-942c-aacef280c616}</uid> + </MElement> + </base-MElement> + <name>History</name> + <relations> + <handles> + <handles> + <qlist> + <item> + <handle> + <uid>{bca413d3-d869-44ce-a68d-38e8ba6de291}</uid> + <target> + <instance type="MDependency"> + <MDependency> + <base-MRelation> + <MRelation> + <base-MElement> + <MElement> + <uid>{bca413d3-d869-44ce-a68d-38e8ba6de291}</uid> + </MElement> + </base-MElement> + <a>{99e69e48-e844-4fc0-942c-aacef280c616}</a> + <b>{6b572233-bf3a-43a2-bfe2-e61d57a59a2e}</b> + </MRelation> + </base-MRelation> + </MDependency> + </instance> + </target> + </handle> + </item> + </qlist> + </handles> + </handles> + </relations> + </MObject> + </base-MObject> + </MComponent> + </instance> + </target> + </handle> + </item> + <item> + <handle> + <uid>{6b572233-bf3a-43a2-bfe2-e61d57a59a2e}</uid> + <target> + <instance type="MComponent"> + <MComponent> + <base-MObject> + <MObject> + <base-MElement> + <MElement> + <uid>{6b572233-bf3a-43a2-bfe2-e61d57a59a2e}</uid> + </MElement> + </base-MElement> + <name>Settings</name> + </MObject> + </base-MObject> + </MComponent> + </instance> + </target> + </handle> + </item> + <item> + <handle> + <uid>{8afe2dfe-878f-4c40-9f07-c6128611f853}</uid> + <target> + <instance type="MComponent"> + <MComponent> + <base-MObject> + <MObject> + <base-MElement> + <MElement> + <uid>{8afe2dfe-878f-4c40-9f07-c6128611f853}</uid> + </MElement> + </base-MElement> + <name>Profile</name> + <relations> + <handles> + <handles> + <qlist> + <item> + <handle> + <uid>{9c6691bd-75e5-40af-a662-ecb04e60744e}</uid> + <target> + <instance type="MDependency"> + <MDependency> + <base-MRelation> + <MRelation> + <base-MElement> + <MElement> + <uid>{9c6691bd-75e5-40af-a662-ecb04e60744e}</uid> + </MElement> + </base-MElement> + <a>{8afe2dfe-878f-4c40-9f07-c6128611f853}</a> + <b>{6b572233-bf3a-43a2-bfe2-e61d57a59a2e}</b> + </MRelation> + </base-MRelation> + </MDependency> + </instance> + </target> + </handle> + </item> + <item> + <handle> + <uid>{31cff752-95b7-4994-a5fc-8794dd8a013f}</uid> + <target> + <instance type="MDependency"> + <MDependency> + <base-MRelation> + <MRelation> + <base-MElement> + <MElement> + <uid>{31cff752-95b7-4994-a5fc-8794dd8a013f}</uid> + </MElement> + </base-MElement> + <a>{8afe2dfe-878f-4c40-9f07-c6128611f853}</a> + <b>{2dfae517-4615-42b9-bb33-63369291468f}</b> + </MRelation> + </base-MRelation> + </MDependency> + </instance> + </target> + </handle> + </item> + <item> + <handle> + <uid>{b98164e7-ff69-40e7-ac1b-fe4985f451e7}</uid> + <target> + <instance type="MDependency"> + <MDependency> + <base-MRelation> + <MRelation> + <base-MElement> + <MElement> + <uid>{b98164e7-ff69-40e7-ac1b-fe4985f451e7}</uid> + </MElement> + </base-MElement> + <a>{8afe2dfe-878f-4c40-9f07-c6128611f853}</a> + <b>{b19ba8d3-84ca-4718-b62c-575aa5d95c95}</b> + </MRelation> + </base-MRelation> + </MDependency> + </instance> + </target> + </handle> + </item> + </qlist> + </handles> + </handles> + </relations> + </MObject> + </base-MObject> + </MComponent> + </instance> + </target> + </handle> + </item> + <item> + <handle> + <uid>{2dfae517-4615-42b9-bb33-63369291468f}</uid> + <target> + <instance type="MComponent"> + <MComponent> + <base-MObject> + <MObject> + <base-MElement> + <MElement> + <uid>{2dfae517-4615-42b9-bb33-63369291468f}</uid> + </MElement> + </base-MElement> + <name>Script</name> + </MObject> + </base-MObject> + </MComponent> + </instance> + </target> + </handle> + </item> + <item> + <handle> + <uid>{8f64c8e2-637e-482e-8565-1bbdcd203709}</uid> + <target> + <instance type="MComponent"> + <MComponent> + <base-MObject> + <MObject> + <base-MElement> + <MElement> + <uid>{8f64c8e2-637e-482e-8565-1bbdcd203709}</uid> + </MElement> + </base-MElement> + <name>Action</name> + </MObject> + </base-MObject> + </MComponent> + </instance> + </target> + </handle> + </item> + <item> + <handle> + <uid>{b19ba8d3-84ca-4718-b62c-575aa5d95c95}</uid> + <target> + <instance type="MComponent"> + <MComponent> + <base-MObject> + <MObject> + <base-MElement> + <MElement> + <uid>{b19ba8d3-84ca-4718-b62c-575aa5d95c95}</uid> + </MElement> + </base-MElement> + <name>Cookie</name> + </MObject> + </base-MObject> + </MComponent> + </instance> + </target> + </handle> + </item> + </qlist> + </handles> + </handles> + </children> + </MObject> + </base-MObject> + </MPackage> + </instance> + </root-package> + </project> +</qmt> diff --git a/src/webenginequick/doc/snippets/minimal/main.cpp b/src/webenginequick/doc/snippets/minimal/main.cpp new file mode 100644 index 000000000..e17493a36 --- /dev/null +++ b/src/webenginequick/doc/snippets/minimal/main.cpp @@ -0,0 +1,18 @@ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause + +//! [Minimal Example] +#include <QGuiApplication> +#include <QQmlApplicationEngine> +#include <QtWebEngineQuick/qtwebenginequickglobal.h> + +int main(int argc, char *argv[]) +{ + QCoreApplication::setAttribute(Qt::AA_ShareOpenGLContexts); + QtWebEngineQuick::initialize(); + QGuiApplication app(argc, argv); + QQmlApplicationEngine engine; + engine.load(QUrl(QStringLiteral("qrc:/main.qml"))); + return app.exec(); +} +//! [Minimal Example] diff --git a/src/webenginequick/doc/snippets/minimal/main.qml b/src/webenginequick/doc/snippets/minimal/main.qml new file mode 100644 index 000000000..87a8757df --- /dev/null +++ b/src/webenginequick/doc/snippets/minimal/main.qml @@ -0,0 +1,18 @@ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause + +//! [Minimal Example] +import QtQuick +import QtQuick.Window +import QtWebEngine + +Window { + width: 1024 + height: 750 + visible: true + WebEngineView { + anchors.fill: parent + url: "https://www.qt.io" + } +} +//! [Minimal Example] diff --git a/src/webenginequick/doc/snippets/qtwebengine_build_snippet.qdoc b/src/webenginequick/doc/snippets/qtwebengine_build_snippet.qdoc new file mode 100644 index 000000000..f8fbbd669 --- /dev/null +++ b/src/webenginequick/doc/snippets/qtwebengine_build_snippet.qdoc @@ -0,0 +1,11 @@ +// Copyright (C) 2017 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only + +//! [0] +QT += webenginequick +//! [0] + +//! [2] +find_package(Qt6 REQUIRED COMPONENTS WebEngineQuick) +target_link_libraries(target PRIVATE Qt6::WebEngineQuick) +//! [2] diff --git a/src/webenginequick/doc/snippets/qtwebengine_webengineaction.qml b/src/webenginequick/doc/snippets/qtwebengine_webengineaction.qml new file mode 100644 index 000000000..2fd5f490b --- /dev/null +++ b/src/webenginequick/doc/snippets/qtwebengine_webengineaction.qml @@ -0,0 +1,123 @@ +// Copyright (C) 2018 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause + +import QtQuick +import QtQuick.Window +import QtWebEngine +import QtQuick.Controls +import QtQuick.Layouts + +ApplicationWindow { + id: window + visible: true + width: 800 + height: 600 + title: qsTr("WebEngineAction Example") + + header: ToolBar { + RowLayout { + anchors.fill: parent +//! [0] + ToolButton { + property int itemAction: WebEngineView.Back + text: webEngineView.action(itemAction).text + enabled: webEngineView.action(itemAction).enabled + onClicked: webEngineView.action(itemAction).trigger() + icon.name: webEngineView.action(itemAction).iconName + display: AbstractButton.TextUnderIcon + } +//! [0] + ToolButton { + property int itemAction: WebEngineView.Forward + text: webEngineView.action(itemAction).text + enabled: webEngineView.action(itemAction).enabled + onClicked: webEngineView.action(itemAction).trigger() + icon.name: webEngineView.action(itemAction).iconName + display: AbstractButton.TextUnderIcon + } + + ToolButton { + property int itemAction: webEngineView.loading ? WebEngineView.Stop : WebEngineView.Reload + text: webEngineView.action(itemAction).text + enabled: webEngineView.action(itemAction).enabled + onClicked: webEngineView.action(itemAction).trigger() + icon.name: webEngineView.action(itemAction).iconName + display: AbstractButton.TextUnderIcon + } + + TextField { + Layout.fillWidth: true + + text: webEngineView.url + selectByMouse: true + onEditingFinished: webEngineView.url = utils.fromUserInput(text) + } + + ToolButton { + id: settingsButton + text: "Settings" + icon.name: "settings-configure" + display: AbstractButton.TextUnderIcon + onClicked: settingsMenu.open() + checked: settingsMenu.visible + + Menu { + id: settingsMenu + y: settingsButton.height + + MenuItem { + id: customContextMenuOption + checkable: true + checked: true + + text: "Custom context menu" + } + } + } + } + } + + WebEngineView { + id: webEngineView + url: "https://qt.io" + anchors.fill: parent + + Component.onCompleted: { + profile.downloadRequested.connect(function(download){ + download.accept(); + }) + } + +//! [1] + property Menu contextMenu: Menu { + Repeater { + model: [ + WebEngineView.Back, + WebEngineView.Forward, + WebEngineView.Reload, + WebEngineView.SavePage, + WebEngineView.Copy, + WebEngineView.Paste, + WebEngineView.Cut, + WebEngineView.ChangeTextDirectionLTR, + WebEngineView.ChangeTextDirectionRTL, + ] + MenuItem { + text: webEngineView.action(modelData).text + enabled: webEngineView.action(modelData).enabled + onClicked: webEngineView.action(modelData).trigger() + icon.name: webEngineView.action(modelData).iconName + display: MenuItem.TextBesideIcon + } + } + } + + onContextMenuRequested: function(request) { + if (customContextMenuOption.checked) { + request.accepted = true; + contextMenu.popup(); + } + } +//! [1] + } +} diff --git a/src/webenginequick/doc/snippets/qtwebengine_webengineview_newviewrequested.qml b/src/webenginequick/doc/snippets/qtwebengine_webengineview_newviewrequested.qml new file mode 100644 index 000000000..6b10df752 --- /dev/null +++ b/src/webenginequick/doc/snippets/qtwebengine_webengineview_newviewrequested.qml @@ -0,0 +1,37 @@ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause + +import QtQuick +import QtQuick.Window +import QtWebEngine + +//! [0] +QtObject { + id: windowParent + // Create the initial browsing windows and open the startup page. + Component.onCompleted: { + var firstWindow = windowComponent.createObject(windowParent); + firstWindow.webView.loadHtml('<input type="button" value="Click!" onclick="window.open("http://qt.io")">'); + } + + property Component windowComponent: Window { + // Destroy on close to release the Window's QML resources. + // Because it was created with a parent, it won't be garbage-collected. + onClosing: destroy() + visible: true + + property WebEngineView webView: webView_ + WebEngineView { + id: webView_ + anchors.fill: parent + + // Handle the signal. Dynamically create the window and + // use its WebEngineView as the destination of our request. + onNewWindowRequested: function(request) { + var newWindow = windowComponent.createObject(windowParent); + newWindow.webView.acceptAsNewWindow(request); + } + } + } +} +//! [0] diff --git a/src/webenginequick/doc/src/context_menu_request.qdoc b/src/webenginequick/doc/src/context_menu_request.qdoc new file mode 100644 index 000000000..e7d732d5e --- /dev/null +++ b/src/webenginequick/doc/src/context_menu_request.qdoc @@ -0,0 +1,194 @@ +// Copyright (C) 2020 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only + +/*! + \qmltype ContextMenuRequest + //! \instantiates QQuickWebEngineContextMenuRequest + \inqmlmodule QtWebEngine + \since QtWebEngine 1.4 + + \brief A request for showing a context menu. + + A ContextMenuRequest is passed as an argument of the + WebEngineView::contextMenuRequested signal. It provides further + information about the context of the request. The \l position + property provides the origin of the request. + + The \l accepted property of the request indicates whether the request + is handled by the user code or the default context menu should + be displayed. + + The following code uses a custom menu to handle the request: + + \code + WebEngineView { + id: view + // ... + onContextMenuRequested: function(request) { + request.accepted = true; + myMenu.x = request.x; + myMenu.y = request.y; + myMenu.trigger.connect(view.triggerWebAction); + myMenu.popup(); + } + // ... + } + \endcode +*/ + +/*! + \qmlproperty point ContextMenuRequest::position + \readonly + + The position of the user action from where the context + menu request originates. +*/ + +/*! + \qmlproperty string ContextMenuRequest::selectedText + \readonly + + The selected text the context menu was created for. +*/ + +/*! + \qmlproperty string ContextMenuRequest::linkText + \readonly + + The text of the link if the context menu was requested for a link. +*/ + +/*! + \qmlproperty url ContextMenuRequest::linkUrl + \readonly + + The URL of the link if the selected web page content is a link. + It is not guaranteed to be a valid URL. +*/ + +/*! + \qmlproperty url ContextMenuRequest::mediaUrl + \readonly + + The URL of media if the selected web content is a media element. +*/ + +/*! + \qmlproperty enumeration ContextMenuRequest::mediaType + \readonly + + The type of the media element or \c MediaTypeNone if + the selected web page content is not a media element. + + \value ContextMenuRequest.MediaTypeNone + Not a media. + \value ContextMenuRequest.MediaTypeImage + An image. + \value ContextMenuRequest.MediaTypeVideo + A video. + \value ContextMenuRequest.MediaTypeAudio + An audio element. + \value ContextMenuRequest.MediaTypeCanvas + A canvas. + \value ContextMenuRequest.MediaTypeFile + A file. + \value ContextMenuRequest.MediaTypePlugin + A plugin. +*/ + +/*! + \qmlproperty bool ContextMenuRequest::isContentEditable + \readonly + + Indicates whether the selected web content is editable. +*/ + +/*! + \qmlproperty string ContextMenuRequest::misspelledWord + \readonly + + If the context is a word considered misspelled by the spell-checker, + returns the misspelled word. +*/ + +/*! + \qmlproperty stringlist ContextMenuRequest::spellCheckerSuggestions + \readonly + + If the context is a word considered misspelled by the spell-checker, + returns a list of suggested replacements. +*/ + +/*! + \qmlproperty bool ContextMenuRequest::accepted + + Indicates whether the context menu request has been + handled by the signal handler. + + If the property is \c false after any signal handlers + for WebEngineView::contextMenuRequested have been executed, + a default context menu will be shown. + To prevent this, set \c{request.accepted} to \c true. + + The default is \c false. + + \note The default content of the context menu depends on the + web element for which the request was actually generated. +*/ + +/*! + \qmlproperty flags ContextMenuRequest::mediaFlags + \readonly + \since QtWebEngine 1.7 + + The current media element's status and its available operations. + \c MediaNone if the selected web page content is not a media element. + + \value ContextMenuRequest.MediaInError + An error occurred. + \value ContextMenuRequest.MediaPaused + Media is paused. + \value ContextMenuRequest.MediaMuted + Media is muted. + \value ContextMenuRequest.MediaLoop + Media can be looped. + \value ContextMenuRequest.MediaCanSave + Media can be saved. + \value ContextMenuRequest.MediaHasAudio + Media has audio. + \value ContextMenuRequest.MediaCanToggleControls + Media can show controls. + \value ContextMenuRequest.MediaControls + Media controls are shown. + \value ContextMenuRequest.MediaCanPrint + Media is printable. + \value ContextMenuRequest.MediaCanRotate + Media is rotatable. +*/ + +/*! + \qmlproperty flags ContextMenuRequest::editFlags + \readonly + \since QtWebEngine 1.7 + + The available edit operations in the current context or \c CanDoNone if no actions are available. + + \value ContextMenuRequest.CanUndo + Undo is available. + \value ContextMenuRequest.CanRedo + Redo is available. + \value ContextMenuRequest.CanCut + Cut is available. + \value ContextMenuRequest.CanCopy + Copy is available. + \value ContextMenuRequest.CanPaste + Paste is available. + \value ContextMenuRequest.CanDelete + Delete is available. + \value ContextMenuRequest.CanSelectAll + Select All is available. + \value ContextMenuRequest.CanTranslate + Translate is available. + \value ContextMenuRequest.CanEditRichly + Context is richly editable. +*/ diff --git a/src/webenginequick/doc/src/fullscreen_request.qdoc b/src/webenginequick/doc/src/fullscreen_request.qdoc new file mode 100644 index 000000000..60da2748c --- /dev/null +++ b/src/webenginequick/doc/src/fullscreen_request.qdoc @@ -0,0 +1,58 @@ +// Copyright (C) 2020 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only + +/*! + \qmltype FullScreenRequest + \instantiates QWebEngineFullScreenRequest + \inqmlmodule QtWebEngine + \since QtWebEngine 1.1 + + \brief A utility type for the WebEngineView::fullScreenRequested() signal. + + \sa WebEngineView::fullScreenRequested() +*/ + +/*! + \qmlproperty url FullScreenRequest::origin + \readonly + The URL of the web page that issued the fullscreen request. +*/ + +/*! + \qmlproperty bool FullScreenRequest::toggleOn + \readonly + + Returns \c{true} if the application should toggle fullscreen mode on, \c{false} otherwise. + + \sa accept() +*/ + +/*! + \qmlmethod void FullScreenRequest::accept() + + Call this method to accept the fullscreen request. It sets the WebEngineView::isFullScreen + property to be equal to toggleOn. + + \qml + ApplicationWindow { + id: window + WebEngineView { + onFullScreenRequested: function(request) { + if (request.toggleOn) + window.showFullScreen() + else + window.showNormal() + request.accept() + } + } + } + \endqml + + \sa toggleOn +*/ + +/*! + \qmlmethod void FullScreenRequest::reject() + Rejects a fullscreen request. +*/ + diff --git a/src/webenginequick/doc/src/loading_info.qdoc b/src/webenginequick/doc/src/loading_info.qdoc new file mode 100644 index 000000000..c97799e24 --- /dev/null +++ b/src/webenginequick/doc/src/loading_info.qdoc @@ -0,0 +1,64 @@ +// Copyright (C) 2021 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only + +/*! + \qmltype WebEngineLoadingInfo + \instantiates QWebEngineLoadingInfo + \inqmlmodule QtWebEngine + \since QtWebEngine 1.0 + + \brief A utility type for the WebEngineView::loadingChanged signal. + + Contains information about a request for loading a web page, such as the URL and + current loading status (started, succeeded, failed). + + \sa WebEngineView::loadingChanged +*/ +/*! + \qmlproperty url WebEngineLoadingInfo::url + \brief Holds the URL of the load request. + */ +/*! + \qmlproperty enumeration WebEngineLoadingInfo::status + + This enumeration represents the load status of a web page load request: + + \value WebEngineView.LoadStartedStatus Page is currently loading. + \value WebEngineView.LoadStoppedStatus + Loading the page was stopped by the stop() method or by the loader + code or network stack in Chromium. + \value WebEngineView.LoadSucceededStatus + Page has been loaded with success. + \value WebEngineView.LoadFailedStatus Page could not be loaded. + + \sa WebEngineView::loadingChanged +*/ +/*! + \qmlproperty string WebEngineLoadingInfo::errorString + \brief Holds the error message. +*/ +/*! + \qmlproperty enumeration WebEngineLoadingInfo::errorDomain + This enumeration holds the type of a load request error: + + \value WebEngineLoadingInfo.NoErrorDomain + Error type is not known. + \value WebEngineLoadingInfo.InternalErrorDomain + Content cannot be interpreted by \QWE. + \value WebEngineLoadingInfo.ConnectionErrorDomain + Error results from a faulty network connection. + \value WebEngineLoadingInfo.CertificateErrorDomain + Error is related to the SSL/TLS certificate. + \value WebEngineLoadingInfo.HttpErrorDomain + Error is related to the HTTP connection. + \value WebEngineLoadingInfo.FtpErrorDomain + Error is related to the FTP connection. + \value WebEngineLoadingInfo.DnsErrorDomain + Error is related to the DNS connection. + \value WebEngineLoadingInfo.HttpStatusCodeDomain + Error is the HTTP response status code, even in case of success e.g. the server replied with status 200. +*/ +/*! + \qmlproperty int WebEngineLoadingInfo::errorCode + \brief Holds the error code. +*/ diff --git a/src/webenginequick/doc/src/navigation_history.qdoc b/src/webenginequick/doc/src/navigation_history.qdoc new file mode 100644 index 000000000..94876799d --- /dev/null +++ b/src/webenginequick/doc/src/navigation_history.qdoc @@ -0,0 +1,113 @@ +// Copyright (C) 2020 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only + +/*! + \qmltype WebEngineHistoryModel + \instantiates QWebEngineHistoryModel + \inqmlmodule QtWebEngine + \since QtWebEngine 1.1 + + \brief A data model that represents the history of a web engine page. + + The WebEngineHistoryModel type exposes the \e title, \e url, \e icon, and \e offset roles. + The \e title, \e url and \e icon specify the title, URL, and favicon of the visited page. + The \e offset specifies + the position of the page in respect to the current page (0). A positive number indicates that + the page was visited after the current page, whereas a negative number indicates that the page + was visited before the current page. + + This type is uncreatable, but it can be accessed by using the + \l{WebEngineView::history}{WebEngineView.history} property. + + \sa WebEngineHistory +*/ + +/*! + \qmltype WebEngineHistory + \instantiates QWebEngineHistory + \inqmlmodule QtWebEngine + \since QtWebEngine 1.1 + + \brief Provides data models that represent the history of a web engine page. + + The WebEngineHistory type can be accessed by using the + \l{WebEngineView::history}{WebEngineView.history} property. + + The WebEngineHistory type provides the following WebEngineHistoryModel data model objects: + + \list + \li \c backItems, which contains the URLs of visited pages. + \li \c forwardItems, which contains the URLs of the pages that were visited after visiting + the current page. + \li \c items, which contains the URLs of the back and forward items, as well as the URL of + the current page. + \endlist + + The easiest way to use these models is to use them in a ListView as illustrated by the + following code snippet: + + \code + ListView { + id: historyItemsList + anchors.fill: parent + model: webEngineView.history.items + delegate: + Text { + color: "black" + text: model.title + " - " + model.url + " (" + model.offset + ")" + } + } + \endcode + + The ListView shows the content of the corresponding model. The delegate is responsible for the + format of the list items. The appearance of each item of the list in the delegate can be defined + separately (it is not web engine specific). + + The model roles \e title, \e url, and \e icon specify the title, URL, and favicon of the + visited page. The \e offset + role specifies the position of the page in respect to the current page (0). A positive number + indicates that the page was visited after the current page, whereas a negative number indicates + that the page was visited before the current page. + + The data models can also be used to create a menu, as illustrated by the following code + snippet: + + \quotefromfile webenginequick/quicknanobrowser/BrowserWindow.qml + \skipto ToolBar + \printuntil onObjectRemoved + \printuntil } + \printuntil } + \printuntil } + + For the complete example, see \l{WebEngine Quick Nano Browser}. + + \sa WebEngineHistoryModel +*/ + +/*! + \qmlproperty WebEngineHistoryModel WebEngineHistory::items + \readonly + + URLs of back items, forward items, and the current item in the history. +*/ + +/*! + \qmlproperty WebEngineHistoryModel WebEngineHistory::backItems + \readonly + + URLs of visited pages. +*/ + +/*! + \qmlproperty WebEngineHistoryModel WebEngineHistory::forwardItems + \readonly + + URLs of the pages that were visited after visiting the current page. +*/ + +/*! + \qmlmethod void WebEngineHistory::clear() + \since QtWebEngine 1.11 + + Clears the history. +*/ diff --git a/src/webenginequick/doc/src/qtwebengine-examples.qdoc b/src/webenginequick/doc/src/qtwebengine-examples.qdoc new file mode 100644 index 000000000..eebf18ba1 --- /dev/null +++ b/src/webenginequick/doc/src/qtwebengine-examples.qdoc @@ -0,0 +1,15 @@ +// Copyright (C) 2017 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only + +/*! + \group webengine-examples + \title Qt WebEngine Quick Examples + \brief Examples demonstrating the \QWE usage. + + These examples and demonstrations show a range of different uses for \l{Qt WebEngine}, + from displaying Web pages within a QML user interface to an implementation of + a basic function Web browser. + + For widget-based applications, Qt provides an integrated Web browser component based on + Chromium, the popular open source browser engine. +*/ diff --git a/src/webenginequick/doc/src/qtwebengine-module.qdoc b/src/webenginequick/doc/src/qtwebengine-module.qdoc new file mode 100644 index 000000000..6f50cc2f4 --- /dev/null +++ b/src/webenginequick/doc/src/qtwebengine-module.qdoc @@ -0,0 +1,25 @@ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only + +/*! + \module QtWebEngineQuick + \title Qt WebEngine Quick C++ Classes + \brief Exposes C++ functionality to Qt Quick. + \ingroup modules + \ingroup qtwebengine-modules + \qtvariable webenginequick + \qtcmakepackage WebEngineQuick + + The \QWE Quick module exposes C++ functionality to Qt Quick. + + \if !defined(qtforpython) + To link against the module, add the following to your qmake project file: + + \snippet qtwebengine_build_snippet.qdoc 0 + + For build with CMake use the \c find_package() command to locate the needed module components + in the Qt6 package and \c target_link_libraries() to link against the module: + + \snippet qtwebengine_build_snippet.qdoc 2 + \endif +*/ diff --git a/src/webenginequick/doc/src/qtwebengine-qmlmodule.qdoc b/src/webenginequick/doc/src/qtwebengine-qmlmodule.qdoc new file mode 100644 index 000000000..ecf3a4a6e --- /dev/null +++ b/src/webenginequick/doc/src/qtwebengine-qmlmodule.qdoc @@ -0,0 +1,29 @@ +// Copyright (C) 2018 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only + +/*! + \qmlmodule QtWebEngine + \title Qt WebEngine QML Types + \brief Provides QML types for rendering web content within a QML application. + \ingroup qtwebengine-modules + \ingroup qmlmodules + + To link against the module using build with qmake, + add the following QT variable to your qmake .pro file: + + \snippet qtwebengine_build_snippet.qdoc 0 + + For build with CMake use the \c find_package() command to locate the needed module components + in the Qt6 package and \c target_link_libraries() to link against the module: + + \snippet qtwebengine_build_snippet.qdoc 2 + + The minimal amount of code needed to load and display an HTML page using the QML engine + requires a proper initialization: + + \snippet minimal/main.cpp Minimal Example + + Where the content of main.qml is simply: + + \snippet minimal/main.qml Minimal Example +*/ diff --git a/src/webenginequick/doc/src/quota_request.qdoc b/src/webenginequick/doc/src/quota_request.qdoc new file mode 100644 index 000000000..01f4ec286 --- /dev/null +++ b/src/webenginequick/doc/src/quota_request.qdoc @@ -0,0 +1,36 @@ +// Copyright (C) 2020 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only + +/*! + \qmltype QuotaRequest + \instantiates QWebEngineQuotaRequest + \inqmlmodule QtWebEngine + \since QtWebEngine 1.7 + \deprecated [6.5] Requesting host quota is no longer supported by Chromium. + + The behavior of navigator.webkitPersistentStorage + is identical to navigator.webkitTemporaryStorage. + + For further details, see https://crbug.com/1233525 + + \sa WebEngineView::quotaRequested() +*/ + +/*! + \qmlproperty url QuotaRequest::origin + \readonly +*/ + +/*! + \qmlproperty qint64 QuotaRequest::requestedSize + \readonly +*/ + +/*! + \qmlmethod void QuotaRequest::accept() +*/ + +/*! + \qmlmethod void QuotaRequest::reject() +*/ + diff --git a/src/webenginequick/doc/src/register_protocol_handler_request.qdoc b/src/webenginequick/doc/src/register_protocol_handler_request.qdoc new file mode 100644 index 000000000..d69f4d264 --- /dev/null +++ b/src/webenginequick/doc/src/register_protocol_handler_request.qdoc @@ -0,0 +1,42 @@ +// Copyright (C) 2020 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only + +/*! + \qmltype RegisterProtocolHandlerRequest + \instantiates QWebEngineRegisterProtocolHandlerRequest + \inqmlmodule QtWebEngine + \since QtWebEngine 1.7 + \brief The RegisterProtocolHandlerRequest type enables accepting + or rejecting requests from the \l registerProtocolHandler API. + + \sa WebEngineView::registerProtocolHandlerRequested() +*/ + +/*! + \qmlproperty url RegisterProtocolHandlerRequest::origin + \brief The URL template for the protocol handler. + + This is the second parameter from the \l registerProtocolHandler call. +*/ + +/*! + \qmlproperty string RegisterProtocolHandlerRequest::scheme + \brief The URL scheme for the protocol handler. + + This is the first parameter from the \l registerProtocolHandler call. +*/ + +/*! + \qmlmethod void RegisterProtocolHandlerRequest::accept() + \brief Accepts the request. + + Subsequent calls to accept() and reject() are ignored. +*/ + +/*! + \qmlmethod void RegisterProtocolHandlerRequest::reject() + \brief Accepts the request. + + Subsequent calls to accept() and reject() are ignored. +*/ + diff --git a/src/webenginequick/doc/src/touch_selection_menu_request.qdoc b/src/webenginequick/doc/src/touch_selection_menu_request.qdoc new file mode 100644 index 000000000..9ca6ed36b --- /dev/null +++ b/src/webenginequick/doc/src/touch_selection_menu_request.qdoc @@ -0,0 +1,79 @@ +// Copyright (C) 2021 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only + +/*! + \qmltype TouchSelectionMenuRequest + //! \instantiates QQuickWebEngineTouchSelectionMenuRequest + \inqmlmodule QtWebEngine + \since QtWebEngine 6.3 + + \brief A request for showing a touch selection menu. + + A TouchSelectionMenuRequest is passed as an argument of the + WebEngineView::touchSelectionMenuRequest signal. It provides further + information about the context of the request. The \l selectionBounds + property provides the origin of the request. + + The \l accepted property of the request indicates whether the request + is handled by the user code or the default touch selection menu should + be displayed. + + The following code uses a custom menu to handle the request: + + \code + WebEngineView { + id: view + // ... + onTouchSelectionMenuRequested: function(request) { + request.accepted = true; + myMenu.x = request.selectionBounds.x; + myMenu.y = request.selectionBounds.y; + myMenu.trigger.connect(view.triggerWebAction); + myMenu.popup(); + } + // ... + } + \endcode +*/ + +/*! + \qmlproperty rect TouchSelectionMenuRequest::selectionBounds + \readonly + + The position of the bound rectangle from the touch text + selection. +*/ + +/*! + \qmlproperty bool TouchSelectionMenuRequest::accepted + + Indicates whether the touch selection menu request has + been handled 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. + + \note The default content of the touch selection menu depends + on the web element for which the request was actually generated. +*/ + + +/*! + \qmlproperty flags QQuickWebEngineTouchSelectionMenuRequest::touchSelectionCommandFlags + \readonly + \since QtWebEngine 6.3 + + \note In the default touch selection menu, showing the context menu + is always available as a separate action. + + \value QQuickWebEngineTouchSelectionMenuRequest.Cut + Cut is available. + \value QQuickWebEngineTouchSelectionMenuRequest.Copy + Copy is available. + \value QQuickWebEngineTouchSelectionMenuRequest.Paste + Paste is available. +*/ diff --git a/src/webenginequick/doc/src/webengine_certificate_error.qdoc b/src/webenginequick/doc/src/webengine_certificate_error.qdoc new file mode 100644 index 000000000..93bad9fb1 --- /dev/null +++ b/src/webenginequick/doc/src/webengine_certificate_error.qdoc @@ -0,0 +1,108 @@ +// Copyright (C) 2020 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only + +/*! + \qmltype WebEngineCertificateError + \instantiates QWebEngineCertificateError + \inqmlmodule QtWebEngine + \since QtWebEngine 1.1 + + \brief A utility type for ignoring certificate errors or rejecting erroneous certificates. + + This QML type contains information about a certificate error that occurred. The \l type + property holds the reason that the error occurred and the \l description property holds a + short localized description of the error. The \l url property holds the URL that triggered + the error. + + The certificate can be rejected by calling \l rejectCertificate(), which will stop loading the + web engine request. By default, an invalid certificate will be automatically rejected. + + The certificate error can be ignored by calling \l acceptCertificate(), which will + resume loading the request. + + It is possible to defer the decision of rejecting a certificate by calling \l defer(), + which is useful when waiting for user input. + + \sa WebEngineView::certificateError +*/ +/*! + \qmlmethod void WebEngineCertificateError::defer() + + This function should be called when there is a need to postpone the decision whether to ignore a + certificate error, for example, while waiting for user input. When called, the function pauses the + URL request until acceptCertificate() or rejectCertificate() is called. + */ +/*! + \qmlmethod void WebEngineCertificateError::acceptCertificate() + + The certificate error is ignored, and the web engine view continues to load the requested URL. + */ +/*! + \qmlmethod void WebEngineCertificateError::rejectCertificate() + + The certificate is rejected, and the web engine view stops loading the requested URL. + */ +/*! + \qmlproperty url WebEngineCertificateError::url + \readonly + + The URL that triggered the error. + */ +/*! + \qmlproperty enumeration WebEngineCertificateError::type + \readonly + + The type of the error. + + \value WebEngineCertificateError.SslPinnedKeyNotInCertificateChain + The certificate did not match the built-in public keys pinned for + the host name. + \value WebEngineCertificateError.CertificateCommonNameInvalid + The certificate's common name did not match the host name. + \value WebEngineCertificateError.CertificateDateInvalid + The certificate is not valid at the current date and time. + \value WebEngineCertificateError.CertificateAuthorityInvalid + The certificate is not signed by a trusted authority. + \value WebEngineCertificateError.CertificateContainsErrors + The certificate contains errors. + \value WebEngineCertificateError.CertificateNoRevocationMechanism + The certificate has no mechanism for determining if it has been + revoked. + \value WebEngineCertificateError.CertificateUnableToCheckRevocation + Revocation information for the certificate is not available. + \value WebEngineCertificateError.CertificateRevoked + The certificate has been revoked. + \value WebEngineCertificateError.CertificateInvalid + The certificate is invalid. + \value WebEngineCertificateError.CertificateWeakSignatureAlgorithm + The certificate is signed using a weak signature algorithm. + \value WebEngineCertificateError.CertificateNonUniqueName + The host name specified in the certificate is not unique. + \value WebEngineCertificateError.CertificateWeakKey + The certificate contains a weak key. + \value WebEngineCertificateError.CertificateNameConstraintViolation + The certificate claimed DNS names that are in violation of name + constraints. + \value WebEngineCertificateError.CertificateValidityTooLong + The certificate has a validity period that is too long. + (Added in 5.7) + \value WebEngineCertificateError.CertificateTransparencyRequired + Certificate Transparency was required for this connection, but the server + did not provide CT information that complied with the policy. (Added in 5.8) + \value WebEngineCertificateError.CertificateKnownInterceptionBlocked + The certificate is known to be used for interception by an entity other + the device owner. (Added in 5.15) + +*/ +/*! + \qmlproperty string WebEngineCertificateError::description + \readonly + + A short localized human-readable description of the error. +*/ +/*! + \qmlproperty bool WebEngineCertificateError::overridable + \readonly + + A boolean that indicates whether the certificate error can be overridden and ignored. +*/ diff --git a/src/webenginequick/doc/src/webengine_download_request.qdoc b/src/webenginequick/doc/src/webengine_download_request.qdoc new file mode 100644 index 000000000..96d84e0a3 --- /dev/null +++ b/src/webenginequick/doc/src/webengine_download_request.qdoc @@ -0,0 +1,278 @@ +// Copyright (C) 2020 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only + +/*! + \qmltype WebEngineDownloadRequest + \instantiates QWebEngineDownloadRequest + \inqmlmodule QtWebEngine + \brief Provides information about a download. + + WebEngineDownloadRequest models a download throughout its life cycle, starting + with a pending download request and finishing with a completed download. It + can be used, for example, to get information about new downloads, to monitor + progress, and to pause, resume, and cancel downloads. + + Downloads are usually triggered by user interaction on a web page. It is the + WebEngineProfile's responsibility to notify the application of new download + requests, which it does by emitting the + \l{WebEngineProfile::downloadRequested}{downloadRequested} signal together + with a newly created WebEngineDownloadRequest. The application can then examine + this item and decide whether to accept it or not. A signal handler must + explicitly call accept() on the item for \QWE to actually start + downloading and writing data to disk. If no signal handler calls accept(), + then the download request will be automatically rejected and nothing will be + written to disk. + + \note Some properties, like the \l path under which the file will be saved, + can only be changed before calling accept(). + + \section2 Object Life Cycle + + All items are guaranteed to be valid during the emission of the + \l{WebEngineProfile::downloadRequested}{downloadRequested} signal. If + accept() is \e not called by any signal handler, then the item will be + deleted \e immediately after signal emission. This means that the + application \b{must not} keep references to rejected download items. + + \section2 Web Page Downloads + + In addition to normal file downloads, which consist simply of retrieving + some raw bytes from the network and writing them to disk, \QWE also + supports saving complete web pages, which involves parsing the page's HTML, + downloading any dependent resources, and potentially packaging everything + into a special file format (\l savePageFormat). To check if a download is + for a file or a web page, use \l isSavePageDownload. + + \sa WebEngineProfile, WebEngineProfile::downloadRequested, + WebEngineProfile::downloadFinished +*/ + +/*! + \qmlmethod void WebEngineDownloadRequest::accept() + + Accepts the download request, which will start the download. + + If the item is in the \c DownloadRequested state, then it will transition + into the \c DownloadInProgress state and the downloading will begin. If the + item is in any other state, then nothing will happen. + + \sa state +*/ + +/*! + \qmlmethod void WebEngineDownloadRequest::cancel() + + Cancels the download. + + If the item is in the \c DownloadInProgress state, then it will transition + into the \c DownloadCancelled state, the downloading will stop, and + partially downloaded files will be deleted from disk. + + If the item is in the \c DownloadCompleted state, then nothing will happen. + If the item is in any other state, then it will transition into the \c + DownloadCancelled state without further effect. + + \sa state +*/ + +/*! + \qmlmethod void WebEngineDownloadRequest::pause() + + Pauses the download. + + Has no effect if the state is not \c DownloadInProgress. Does not change the + state. + + \sa resume, isPaused +*/ + +/*! + \qmlmethod void WebEngineDownloadRequest::resume() + + Resumes the download if it was paused or interrupted. + + Has no effect if the state is not \c DownloadInProgress or \c + DownloadInterrupted. Does not change the state. + + \sa pause, isPaused +*/ + +/*! + \qmlproperty int WebEngineDownloadRequest::id + + Holds the download item's ID. +*/ + +/*! + \qmlproperty enumeration WebEngineDownloadRequest::state + + Describes the state of the download: + + \value WebEngineDownloadRequest.DownloadRequested + Download has been requested, but it has not been accepted yet. + \value WebEngineDownloadRequest.DownloadInProgress + Download is in progress. + \value WebEngineDownloadRequest.DownloadCompleted + Download completed successfully. + \value WebEngineDownloadRequest.DownloadCancelled + Download was cancelled by the user. + \value WebEngineDownloadRequest.DownloadInterrupted + Download has been interrupted (by the server or because of lost connectivity). +*/ + +/*! + \qmlproperty int WebEngineDownloadRequest::totalBytes + + Holds the total amount of data to download in bytes. + + \c -1 means the total size is unknown. +*/ + +/*! + \qmlproperty int WebEngineDownloadRequest::receivedBytes + + Holds the amount of data in bytes that has been downloaded so far. +*/ + +/*! + \qmlproperty url WebEngineDownloadRequest::url + \readonly + + Returns the download's origin URL. +*/ + +/*! + \qmlproperty string WebEngineDownloadRequest::mimeType + + Holds the MIME type of the download. +*/ + +/*! + \qmlproperty string WebEngineDownloadRequest::downloadDirectory + + Holds the full target path without file name where data is being downloaded to. + + The download directory can only be set in the + \l{WebEngineProfile::downloadRequested}{downloadRequested} handler before + the download is accepted. + + \sa WebEngineProfile::downloadRequested(), accept() +*/ + +/*! + \qmlproperty string WebEngineDownloadRequest::downloadFileName + + Holds the name of the file to which data is being downloaded. + + The download file name can only be set in the + \l{WebEngineProfile::downloadRequested}{downloadRequested} handler before + the download is accepted. + + \sa WebEngineProfile::downloadRequested(), accept() +*/ + +/*! + \qmlproperty string WebEngineDownloadRequest::suggestedFileName + + Returns the suggested file name. +*/ + +/*! + \qmlproperty enumeration WebEngineDownloadRequest::savePageFormat + + Describes the format that is used to save a web page. + + \value WebEngineDownloadRequest.UnknownSaveFormat + This is not a request for downloading a complete web page. + \value WebEngineDownloadRequest.SingleHtmlSaveFormat + The page is saved as a single HTML page. Resources such as images + are not saved. + \value WebEngineDownloadRequest.CompleteHtmlSaveFormat + The page is saved as a complete HTML page, for example a directory + containing the single HTML page and the resources. + \value WebEngineDownloadRequest.MimeHtmlSaveFormat + The page is saved as a complete web page in the MIME HTML format. +*/ + +/*! + \qmlproperty bool WebEngineDownloadRequest::isSavePageDownload + \readonly + + Whether this is a download request for saving a web page or a file. + + \sa savePageFormat +*/ + +/*! + \qmlproperty enumeration WebEngineDownloadRequest::interruptReason + \readonly + + Returns the reason why the download was interrupted: + + \value WebEngineDownloadRequest.NoReason Unknown reason or not interrupted. + \value WebEngineDownloadRequest.FileFailed General file operation failure. + \value WebEngineDownloadRequest.FileAccessDenied The file cannot be written locally, due to access restrictions. + \value WebEngineDownloadRequest.FileNoSpace Insufficient space on the target drive. + \value WebEngineDownloadRequest.FileNameTooLong The directory or file name is too long. + \value WebEngineDownloadRequest.FileTooLarge The file size exceeds the file system limitation. + \value WebEngineDownloadRequest.FileVirusInfected The file is infected with a virus. + \value WebEngineDownloadRequest.FileTransientError Temporary problem (for example the file is in use, + out of memory, or too many files are opened at once). + \value WebEngineDownloadRequest.FileBlocked The file was blocked due to local policy. + \value WebEngineDownloadRequest.FileSecurityCheckFailed An attempt to check the safety of the download + failed due to unexpected reasons. + \value WebEngineDownloadRequest.FileTooShort An attempt was made to seek past the end of a file when + opening a file (as part of resuming a previously interrupted download). + \value WebEngineDownloadRequest.FileHashMismatch The partial file did not match the expected hash. + + \value WebEngineDownloadRequest.NetworkFailed General network failure. + \value WebEngineDownloadRequest.NetworkTimeout The network operation has timed out. + \value WebEngineDownloadRequest.NetworkDisconnected The network connection has been terminated. + \value WebEngineDownloadRequest.NetworkServerDown The server has gone down. + \value WebEngineDownloadRequest.NetworkInvalidRequest The network request was invalid (for example, the + original or redirected URL is invalid, has an unsupported scheme, or is disallowed by policy). + + \value WebEngineDownloadRequest.ServerFailed General server failure. + \value WebEngineDownloadRequest.ServerBadContent The server does not have the requested data. + \value WebEngineDownloadRequest.ServerUnauthorized The server did not authorize access to the resource. + \value WebEngineDownloadRequest.ServerCertProblem A problem with the server certificate occurred. + \value WebEngineDownloadRequest.ServerForbidden Access forbidden by the server. + \value WebEngineDownloadRequest.ServerUnreachable Unexpected server response (might indicate that + the responding server may not be the intended server). + \value WebEngineDownloadRequest.UserCanceled The user canceled the download. + + \sa interruptReasonString +*/ + +/*! + \qmlproperty string WebEngineDownloadRequest::interruptReasonString + Returns a human-readable description of the reason for interrupting the download. + + \sa interruptReason +*/ + +/*! + \qmlproperty bool WebEngineDownloadRequest::isFinished + \readonly + + Whether this download is finished (completed, cancelled, or non-resumable interrupted state). + */ + +/*! + \qmlproperty bool WebEngineDownloadRequest::isPaused + \readonly + + Whether this download is paused. + + \sa pause, resume + */ + +/*! + \qmlproperty WebEngineView WebEngineDownloadRequest::view + \readonly + + Returns the view the download was requested on. If the download was not triggered by content in a view, + \c nullptr is returned. + + \sa WebEngineView +*/ diff --git a/src/webenginequick/doc/src/webengine_permission.qdoc b/src/webenginequick/doc/src/webengine_permission.qdoc new file mode 100644 index 000000000..f59f57fa0 --- /dev/null +++ b/src/webenginequick/doc/src/webengine_permission.qdoc @@ -0,0 +1,137 @@ +// Copyright (C) 2024 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only + +/*! + \qmltype webEnginePermission + \instantiates QWebEnginePermission + \inqmlmodule QtWebEngine + \brief An object used to access and modify the state of a single permission that's been + granted or denied to a specific origin URL. + + The typical usage pattern is as follows: + \list 1 + \li A website requests a specific feature, triggering the WebEngineView::permissionRequested signal; + \li The signal handler triggers a prompt asking the user whether they want to grant the permission; + \li When the user has made their decision, the application calls \l grant() or \l deny(); + \endlist + + Alternatively, an application interested in modifying already granted permissions may use WebEngineProfile::listPermissions() + to get a list of existing permissions associated with a profile, or WebEngineProfile::getPermission() to get + a webEnginePermission object for a specific permission. + + The \l origin property can be used to query which origin the webEnginePermission is associated with, while the + \l feature property describes the associated feature. A website origin is the combination of its scheme, hostname, + and port. Permissions are granted on a per-origin basis; thus, if the web page \c{https://www.example.com:12345/some/page.html} + requests a permission, it will be granted to the origin \c{https://www.example.com:12345/}. + + The usability lifetime of a webEnginePermission is tied either to its associated WebEngineView + (for transient feature types), or WebEngineProfile (for permanent feature types). A transient permission is one which + needs to be explicitly granted or denied every time it's needed (e.g. webcam/screen sharing permission), whereas a permanent + one might be stored inside the current profile, depending on the value of WebEngineProfile::persistentPermissionsPolicy. + You can check whether a webEnginePermission is in a valid state using its \l isValid() property. For invalid objects, calls to \l grant(), + \l deny(), or \l reset() will do nothing, and their \l state() will always be WebEnginePermission.Invalid. + + The feature types Qt WebEngine supports are described in \l feature. + + \sa WebEngineView::permissionRequested, WebEngineProfile::getPermission(), + WebEngineProfile::listPermissions() +*/ + +/*! + \qmlproperty url webEnginePermission::origin + \brief The URL of the permission's associated origin. + + A website origin is the combination of its scheme, hostname, and port. Permissions are granted on a + per-origin basis; thus, if the web page \c{https://www.example.com:12345/some/page.html} + requests a permission, it will be granted to the origin \c{https://www.example.com:12345/}. +*/ + +/*! + \qmlproperty enumeration webEnginePermission::feature + \brief The feature type associated with this permission. + + \value WebEnginePermission.MediaAudioCapture Access to a microphone, or another audio source. This feature is transient. + \value WebEnginePermission.MediaVideoCapture Access to a webcam, or another video source. This feature is transient. + \value WebEnginePermission.MediaAudioVideoCapture Combination of \l MediaAudioCapture and \l MediaVideoCapture. This feature is transient. + \value WebEnginePermission.DesktopVideoCapture Access to the contents of the user's screen. This feature is transient. + \value WebEnginePermission.DesktopAudioVideoCapture Access to the contents of the user's screen, and application audio. This feature is transient. + \value WebEnginePermission.MouseLock Locks the pointer inside an element on the web page. This feature is transient. + \value WebEnginePermission.Notifications Allows the website to send notifications to the user. + \value WebEnginePermission.Geolocation Access to the user's physical location. + \value WebEnginePermission.ClipboardReadWrite Access to the user's clipboard. + \value WebEnginePermission.LocalFontsAccess Access to the fonts installed on the user's machine. Only available on desktops. + \value WebEnginePermission.Unsupported An unsupported feature type. + + \note Transient feature types are ones that will never be remembered by the underlying storage, and will trigger + a permission request every time a website tries to use them. +*/ + +/*! + \qmlproperty enumeration webEnginePermission::state + \brief The current state of the permission. + + \value WebEnginePermission.Invalid Object is in an invalid state, and any attempts to modify the described permission will fail. + \value WebEnginePermission.Ask Either the permission has not been requested before, or the feature() is transient. + \value WebEnginePermission.Granted Permission has already been granted. + \value WebEnginePermission.Denied Permission has already been denied. + + If a permission for the specified \l feature and \l origin has already been granted or denied, + the return value is WebEnginePermission.Granted, or WebEnginePermission.Denied, respectively. + When this is the first time the permission is requested, or if the \l feature is transient, + the return value is WebEnginePermission.Ask. If the object is in an invalid state, the returned + value is WebEnginePermission.Invalid. + + \sa isValid, isTransient +*/ + +/*! + \qmlproperty bool webEnginePermission::isValid + \brief Indicates whether attempts to change the permission's state will be successful. + + An invalid webEnginePermission is either: + \list + \li One whose \l feature is unsupported; + \li One whose \l feature is transient, and the associated page/view has been destroyed; + \li One whose \l feature is permanent, but the associated profile has been destroyed; + \li One whose \l origin is invalid. + \endlist + + \sa isTransient +*/ + +/*! + \qmlmethod void webEnginePermission::grant() + + Allows the associated origin to access the requested feature. Does nothing when \l isValid evaluates to false. + + \sa deny, reset, isValid +*/ + +/*! + \qmlmethod void webEnginePermission::deny() + + Stops the associated origin from accessing the requested feature. Does nothing when \l isValid evaluates to false. + + \sa grant, reset, isValid +*/ + +/*! + \qmlmethod void webEnginePermission::reset() + + Removes the permission from the profile's underlying storage. By default, permissions are stored on disk (except for + off-the-record profiles, where permissions are stored in memory and are destroyed with the profile). + This means that an already granted/denied permission will not be requested twice, but will get automatically + granted/denied every subsequent time a website requests it. Calling reset() allows the query to be asked + again the next time the website requests it. + + Does nothing when \l isValid evaluates to false. + + \sa grant, deny, isValid, WebEngineProfile::persistentPermissionsPolicy +*/ + +/*! + \qmlmethod void webEnginePermission::isTransient(WebEnginePermission.Feature feature) + + Returns whether \a feature is transient, meaning that a permission will be requested + every time the associated functionality is used by a web page. +*/ diff --git a/src/webenginequick/doc/src/webengineframe.qdoc b/src/webenginequick/doc/src/webengineframe.qdoc new file mode 100644 index 000000000..8f852501e --- /dev/null +++ b/src/webenginequick/doc/src/webengineframe.qdoc @@ -0,0 +1,129 @@ +// Copyright (C) 2024 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only + +/*! + \qmltype webEngineFrame + \instantiates QQuickWebEngineFrame + \brief webEngineFrame provides information about and control over a page frame. + \since 6.8 + \ingroup qmlvaluetypes + \inqmlmodule QtWebEngine + + A web engine frame represents a single frame within a web page, such as those created by + \c <frame> or \c <iframe> HTML elements. + An active \l WebEngineView has one or more frames arranged in a tree structure. The top-level + frame, the root of this tree, can be accessed through the view's \l {WebEngineView::mainFrame} + {mainFrame} property. + + A frame's lifetime is, at most, as long as the \l WebEngineView object that produced it. + However, frames may be created and deleted spontaneously and dynamically, for example through + navigation and script execution. +*/ + +/*! + \qmlproperty bool webEngineFrame::isValid + + Returns \c{true} if this object represents an existing frame; \c{false} otherwise. + + Once a frame is invalid, it never becomes valid again. +*/ + +/*! + \qmlproperty string webEngineFrame::name + + Returns the frame name; that is, what would be returned by \c window.name in JavaScript. + + If the frame could not be found, returns an empty string. + + \sa htmlName +*/ + +/*! + \qmlproperty string webEngineFrame::htmlName + + Returns the value of the frame's \c name HTML attribute, or an empty string if it has none. + + If the frame could not be found, returns an empty string. + + \sa name +*/ + +/*! + \qmlproperty url webEngineFrame::url + + Returns the URL of the content currently loaded in this frame. + + If the frame could not be found, returns an empty URL. +*/ + +/*! + \qmlproperty size webEngineFrame::size + + Returns the size of the frame within the viewport. + + If the frame could not be found, returns a default size with dimensions (-1, -1). +*/ + +/*! + \qmlproperty bool webEngineFrame::isMainFrame + + Returns \c{true} if this object represents the page's main frame; \c{false} otherwise. +*/ + +/*! + \qmlmethod void webEngineFrame::runJavaScript(string script, variant callback) + \qmlmethod void webEngineFrame::runJavaScript(string script, uint worldId, variant callback) + + Runs the JavaScript code contained in \a script on this frame, without checking + whether the DOM of the page has been constructed. + + To avoid conflicts with other scripts executed on the page, the world in + which the script is run is specified by \a worldId. The world ID values are + the same as provided by QWebEngineScript::ScriptWorldId, and between \c 0 + and \c 256. If you leave out the \c world ID, the script is run in the + \c MainWorld. + + The \a callback parameter is optional. If a callback function is provided, it will be + invoked after the script finishes running. + \code + frame.runJavaScript("document.title", function(result) { console.log(result); }); + \endcode + + Only plain data can be returned from JavaScript as the result value. + Supported data types include all of the JSON data types as well as, for + example, \c{Date} and \c{ArrayBuffer}. Unsupported data types include, for + example, \c{Function} and \c{Promise}. + + The script will run in the same \e world as other scripts that are + part of the loaded site. + + \warning Do not execute lengthy routines in the callback function, because it might block the + rendering of the web content. + + For more information about injecting scripts, see \l {Script Injection}. + For an alternative way to inject scripts, see WebEngineView::userScripts. +*/ + +/*! + \qmlmethod void webEngineFrame::printToPdf(string filePath) + + Prints the frame's current content to a PDF document and stores it + under \a filePath. The resulting document will have A4 page size and + portrait orientation. + + This method issues an asynchronous request for printing the web page into a + PDF and returns immediately. To be informed about the result of the + request, connect to the signal \l WebEngineView::pdfPrintingFinished(). + + \sa WebEngineView::pdfPrintingFinished() +*/ + +/*! + \qmlmethod void webEngineFrame::printToPdf(variant callback) + + Prints the frame's current content to a PDF document and returns it in a byte array. The + resulting document will have A4 page size and portrait orientation. + + The \a callback must take a string parameter. This string will contain the document's data upon + successful printing and an empty string otherwise. +*/ diff --git a/src/webenginequick/doc/src/webenginescript.qdoc b/src/webenginequick/doc/src/webenginescript.qdoc new file mode 100644 index 000000000..9708ffbf8 --- /dev/null +++ b/src/webenginequick/doc/src/webenginescript.qdoc @@ -0,0 +1,98 @@ +// Copyright (C) 2022 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only + +/*! + \qmltype WebEngineScript + \instantiates QWebEngineScript + \brief Enables the programmatic injection of scripts in the JavaScript engine. + \since QtWebEngine 1.1 + \ingroup qmlvaluetypes + \inqmlmodule QtWebEngine + + The WebEngineScript type enables the programmatic injection of so called \e {user scripts} in + the JavaScript engine at different points, determined by injectionPoint, during the loading of + web content. + + Scripts can be executed either in the main JavaScript \e world, along with the rest of the + JavaScript coming from the web contents, or in their own isolated world. While the DOM of the + page can be accessed from any world, JavaScript variables of a function defined in one world are + not accessible from a different one. The worldId property provides some predefined IDs for this + purpose. + + The following \l Greasemonkey attributes are supported: + \c @exclude, \c @include, \c @name, \c @match, and \c @run-at. + + Use \l{WebEngineScriptCollection} to access a list of scripts attached to the web view. +*/ + +/*! + \qmlproperty string WebEngineScript::name + + The name of the script. Can be useful to retrieve a particular script from + \l{WebEngineScriptCollection::find}{WebEngineScriptCollection.find} method. +*/ + +/*! + \qmlproperty url WebEngineScript::sourceUrl + + This property holds the remote source location of the user script (if any). + + Unlike \l sourceCode, this property allows referring to user scripts that + are not already loaded in memory, for instance, when stored on disk. + + Setting this property will change the \l sourceCode of the script. + + \note At present, only file-based sources are supported. + + \sa sourceCode +*/ + +/*! + \qmlproperty string WebEngineScript::sourceCode + + This property holds the JavaScript source code of the user script. + + \sa sourceUrl +*/ + +/*! + \qmlproperty enumeration WebEngineScript::injectionPoint + + The point in the loading process at which the script will be executed. + The default value is \c Deferred. + + \value WebEngineScript.DocumentCreation + The script will be executed as soon as the document is created. This is not suitable for + any DOM operation. + \value WebEngineScript.DocumentReady + The script will run as soon as the DOM is ready. This is equivalent to the + \c DOMContentLoaded event firing in JavaScript. + \value WebEngineScript.Deferred + The script will run when the page load finishes, or 500 ms after the document is ready, + whichever comes first. +*/ + +/*! + \qmlproperty enumeration WebEngineScript::worldId + + The world ID defining which isolated world the script is executed in. + + \value WebEngineScript.MainWorld + The world used by the page's web contents. It can be useful in order to expose custom + functionality to web contents in certain scenarios. + \value WebEngineScript.ApplicationWorld + The default isolated world used for application level functionality implemented in + JavaScript. + \value WebEngineScript.UserWorld + The first isolated world to be used by scripts set by users if the application is not + making use of more worlds. As a rule of thumb, if that functionality is exposed to the + application users, each individual script should probably get its own isolated world. +*/ + +/*! + \qmlproperty int WebEngineScript::runOnSubframes + + Set this property to \c true if the script is executed on every frame in the page, or \c false + if it is only ran for the main frame. + The default value is \c{false}. +*/ diff --git a/src/webenginequick/doc/src/webengineview_lgpl.qdoc b/src/webenginequick/doc/src/webengineview_lgpl.qdoc new file mode 100644 index 000000000..f7b17fa7b --- /dev/null +++ b/src/webenginequick/doc/src/webengineview_lgpl.qdoc @@ -0,0 +1,1639 @@ +// Copyright (C) 2019 The Qt Company Ltd. +// Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies) +// Copyright (c) 2012 Hewlett-Packard Development Company, L.P. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only + +// The documentation in this file was imported from QtWebKit and is thus constrained +// by its LGPL license. + +/*! + \qmltype WebEngineView + \instantiates QQuickWebEngineView + \inherits Item + \inqmlmodule QtWebEngine + \since QtWebEngine 1.0 + \brief A WebEngineView renders web content within a QML application. + + The WebEngineView type enables QML applications to render regions of dynamic web content. It + may share the screen with other QML types, such as a TabView, or fill the screen, as specified + within the QML application. + + \section2 Initializing Web Engine + + For the web engine view to be rendered, the web engine must be initialized by using + \l QtWebEngineQuick::initialize in the application main source file, as illustrated by the + following code snippet: + + \quotefromfile minimal/main.cpp + \skipto main + \printuntil } + + \section2 Loading Web Pages + + An application can load pages into the WebEngineView, using either the \l url property or the + \l loadHtml method and navigate within the view's session history. The GET + method is always used to load URLs. + + The history is represented by a WebEngineHistory data model that is held by + the \l history property. + + The following sample QML application loads a web page using the \c url property: + + \quotefromfile minimal/main.qml + \skipto import + \printuntil /^\}/ + + The \l loading property holds whether an HTML page is currently loading. + The \l loadingChanged() signal is emitted when loading the page begins, ends, or fails. + + The title of an HTML page can be accessed with the \l title property. Additionally, a web + page may specify an icon, which can be accessed using the \l icon property. The \l zoomFactor + property enables zooming the contents of the web page by a scale factor. + + If a certificate error is raised while loading a web page, the \l certificateError() signal is + emitted. Certificate errors are handled by using the methods of the WebEngineCertificateError + type. + + \section2 Interaction + + By default, links to different pages load within the same WebEngineView object, but web sites + may request them to be opened as a new tab, window, or dialog. The \l newWindowRequested() signal + is emitted when a request to load the page in a separate web engine view is issued. The + NewViewDestination property describes how the new view should be opened. In addition, the + WebEngineNewWindowRequest utility type can be used to load web pages in separate web engine views. + + The \l findText() method can be used to search for a string on a web page, using the options + described by \l FindFlags. + + The \l setActiveFocusOnPress() method can be used to create a UI element that should not get + focus on press. This can be useful in a hybrid UI. + + The \l {WebEngineSettings::focusOnNavigationEnabled} {focusOnNavigationEnabled} setting can be + used to make the view automatically receive focus when a navigation operation occurs + (like loading or reloading a page or navigating through history). + + The \l linkHovered() signal is emitted when a mouse pointer passes over a link and thus + corresponds to the \c{mouseover} DOM event. + + Actions, such as selecting and editing content, can be performed on a web page by using the + \l triggerWebAction() method. The available actions are described by the \l WebAction property. + + The \l backgroundColorChanged() signal is emitted when the web page background color changes. + + \section2 User Scripts + + During the loading of a page, so called \e {user scripts} can be injected in the JavaScript + engine at different points. The script objects attached to the web engine view are held by the + \l userScripts property and injected by using the WebEngineScript type. Scripts can also be run + by using the runJavaScript() method in the same world as other scripts that are part of the + loaded site. + + The \l webChannel property can be used to expose a WebChannel instance in the JavaScript context + of the page it is rendering as \c qt.webChannelTransport. + + \section2 Fullscreen Mode + + A web page can request through the JavaScript API to be loaded in fullscreen mode. The + \l fullScreenRequested() signal is emitted when the web page issues the request. The + FullScreenRequest utility type can be used to toggle fullscreen requests. The + \l fullScreenCancelled method can be used to notify the browser engine when the windowing + system forces the application to leave fullscreen mode. + + \section2 Profiles + + Web engine views can be isolated from each other by using the WebEngineProfile type. A profile + contains settings, scripts, and the list of visited links shared by all views that belong to the + profile. For example, a dedicated profile could be created for a \e {private browsing} mode. The + current profile for the view is held by the \l profile property and the current settings are + held by the \l settings property. The settings are specified by using the WebEngineSettings + type. + + \section2 Platform Features + + Web pages can request access to platform features, such as geolocation or audio and video + capture devices. The \l permissionRequested() signal is emitted when a web page requests + to make use of a resource. The supported platform features are described by the QWebEnginePermission::Feature + property. + + \section2 Rendering to OpenGL Surface + + When using a QQuickRenderControl to render a Qt Quick user interface to an OpenGL surface, the + WebEngineView type is not rendered correctly. The web engine view attempts to use a global + OpenGL context created by \l QtWebEngineQuick::initialize, but there is no public API for accessing + that context in order to share it with the \c QQuickRenderControl context. + + To have the web engine view rendered correctly, it is possible to manually create a new + offscreen context that is shared with the \c QQuickRenderControl and to call the non-public + function \c qt_gl_set_global_share_context(), rather than calling \c initialize(). + If \c initialize() is called after setting a global context, it will do nothing. +*/ + +/*! + \qmlmethod void WebEngineView::goBack() + + Go backward within the browser's session history, if possible. + This function is equivalent to the \c{window.history.back()} DOM method. + + \sa canGoBack +*/ + +/*! + \qmlmethod void WebEngineView::goForward() + + Go forward within the browser's session history, if possible. + This function is equivalent to the \c{window.history.forward()} DOM method. +*/ + +/*! + \qmlmethod void WebEngineView::goBackOrForward(int offset) + \since QtWebEngine 1.1 + + If \a offset is positive, goes forward the specified number of offset + pages in the current session history. If offset is negative, it goes + back. If the offset is invalid, the page is not changed. + + \sa goBack(), goForward() +*/ + +/*! + \qmlmethod void WebEngineView::stop() + + Stops loading the current page. +*/ + +/*! + \qmlmethod void WebEngineView::reload() + + Reloads the current page. This function is equivalent to the + \c{window.location.reload()} DOM method. + + \sa reloadAndBypassCache() +*/ + +/*! + \qmlmethod void WebEngineView::reloadAndBypassCache() + \since QtWebEngine 1.1 + + Reloads the current page, ignoring any cached content. + + \sa reload() +*/ + +/*! + \qmlproperty url WebEngineView::url + + The location of the currently displayed HTML page. This writable + property offers the main interface to load a page into a web view. + It functions the same as the \c{window.location} DOM property. + + \sa loadHtml() +*/ + +/*! + \qmlproperty url WebEngineView::icon + \readonly + + An internal URL for accessing the currently displayed web site icon, + also known as favicon or shortcut icon. + This read-only URL corresponds to the image used within a mobile browser + application to represent a bookmarked page on the device's home screen. + + The following snippet uses the \c{icon} property to build an \c{Image} + component: + + \qml + Image { + id: appIcon + sourceSize: Qt.size(32, 32) + source: webView.icon != "" ? webView.icon : "fallbackFavicon.png"; + // ... + } + \endqml + + Specifying the \l {Image::sourceSize} property informs + the \QWE's favicon provider about the requested size and resizes the + icon to it. If \l {Image::sourceSize} property is not specified, + the provider provides the icon with the largest available resolution. +*/ + +/*! + \qmlproperty int WebEngineView::loadProgress + \readonly + + The amount of data from the page that has been loaded, expressed + as an integer percentage in the range from \c{0} to \c{100}. +*/ + +/*! + \qmlproperty bool WebEngineView::canGoBack + \readonly + + Returns \c{true} if there are prior session history entries, \c{false} + otherwise. +*/ + +/*! + \qmlproperty bool WebEngineView::canGoForward + \readonly + + Returns \c{true} if there are subsequent session history entries, + \c{false} otherwise. +*/ + +/*! + \qmlproperty bool WebEngineView::loading + \readonly + + Returns \c{true} if the HTML page is currently loading, \c{false} otherwise. +*/ + +/*! + \qmlproperty string WebEngineView::title + \readonly + + The title of the currently displayed HTML page. This is a + read-only value that reflects the contents of the \c{<title>} tag. +*/ + +/*! + \qmlproperty bool WebEngineView::isFullScreen + \since QtWebEngine 1.1 + \readonly + + Returns \c{true} if the web view is in fullscreen mode, \c{false} otherwise. + + \sa fullScreenRequested(), fullScreenCancelled() +*/ + +/*! + \qmlproperty WebEngineHistory WebEngineView::history + \since QtWebEngine 1.1 + \readonly + + The navigation history of the current view. + + \sa WebEngineHistory +*/ + +/*! + \qmlproperty QQmlWebChannel WebEngineView::webChannel + \since QtWebEngine 1.1 + + The web channel instance used by this view. + This channel is automatically using the internal QtWebEngine transport mechanism over Chromium IPC, + and exposed in the javascript context of the page it is rendering as \c qt.webChannelTransport. + This transport object is used when instantiating the JavaScript counterpart of QWebChannel using + the \l{Qt WebChannel JavaScript API}. + + \note The view does not take ownership for an assigned webChannel object. +*/ + +/*! + \qmlproperty WebEngineProfile WebEngineView::profile + \since QtWebEngine 1.1 + + The current profile used for the view. + + \sa WebEngineProfile +*/ + +/*! + \qmlproperty WebEngineSettings WebEngineView::settings + \readonly + \since QtWebEngine 1.1 + + Settings used by this view. + + \sa WebEngineSettings +*/ + + +/*! + \qmlproperty WebEngineScriptCollection WebEngineView::userScripts + \readonly + \since QtWebEngine 1.1 + + The user scripts' collection associated with the view. + + \sa WebEngineScriptCollection +*/ + +/*! + \qmlproperty real WebEngineView::zoomFactor + \since QtWebEngine 1.1 + + Zoom factor for the view. Valid values are within the range from \c{0.25} + to \c{5.0}. The default factor is \c{1.0}. +*/ + +/*! + \qmlproperty size WebEngineView::contentsSize + \since QtWebEngine 1.3 + + Size of the page contents. +*/ + +/*! + \qmlproperty point WebEngineView::scrollPosition + \since QtWebEngine 1.3 + + Scroll position of the page contents. +*/ + +/*! + \qmlproperty int WebEngineView::webChannelWorld + \since QtWebEngine 1.3 + + JavaScript world that the web channel instance used by this view is + installed in. The world must be a number between \c 0 and \c 256. +*/ + +/*! + \qmlmethod void WebEngineView::loadHtml(string html, url baseUrl) + Loads the specified \a html as the content of the web view. + + This method offers a lower-level alternative to the \c{url} property, + which references HTML pages via URL. + + \a baseUrl is optional and used to resolve relative URLs in the document, + such as referenced images or stylesheets. For example, if \a html + is retrieved from \c http://www.example.com/documents/overview.html, which + is the base URL, then an image referenced with the relative URL, \c diagram.png, + should be at \c{http://www.example.com/documents/diagram.png}. + + \sa url +*/ + +/*! + \qmlmethod void WebEngineView::runJavaScript(string script, variant callback) + \qmlmethod void WebEngineView::runJavaScript(string script, int worldId, variant callback) + + Runs the specified \a script in the content of the web view. + + The \a callback parameter is optional. If a callback function is provided, + it will be invoked after the script finishes running. + + \code + runJavaScript("document.title", function(result) { console.log(result); }); + \endcode + + Only plain data can be returned from JavaScript as the result value. + Supported data types include all of the JSON data types as well as, for + example, \c{Date} and \c{ArrayBuffer}. Unsupported data types include, for + example, \c{Function} and \c{Promise}. + + To avoid conflicts with other scripts executed on the page, the world in + which the script is run can be specified by \a worldId. The world ID must be + between \c 0 and \c 256. If you leave out the \c world ID, the script is + run in the \c MainWorld. + + \warning Do not execute lengthy routines in the callback function, because it might block the + rendering of the web content. + + For more information about injecting scripts, see \l {Script Injection}. + For an alternative way to inject scripts, see WebEngineView::userScripts. +*/ + +/*! + \qmlmethod void WebEngineView::findText(string subString) + \since QtWebEngine 1.1 + Finds the specified string, \a subString, in the page. + The findTextFinished() signal is emitted when a string search is completed. + + To clear the search highlight, just pass an empty string. + + \sa findTextFinished() +*/ + +/*! + \qmlmethod void WebEngineView::findText(string subString, FindFlags options) + \since QtWebEngine 1.1 + Finds the specified string, \a subString, in the page, using the given \a options. + The findTextFinished() signal is emitted when a string search is completed. + + To clear the search highlight, just pass an empty string. + + \code + findText("Qt", WebEngineView.FindBackward | WebEngineView.FindCaseSensitively); + \endcode + + \sa findTextFinished() +*/ + +/*! + \qmlmethod void WebEngineView::findText(string subString, FindFlags options, variant resultCallback) + \since QtWebEngine 1.1 + Finds the specified string, \a subString, in the page, using the given \a options. + The findTextFinished() signal is emitted when a string search is completed. + + To clear the search highlight, just pass an empty string. + + The \a resultCallback must take an integer parameter. It will be called with + the number of found occurrences of the \a subString. + + \code + findText("Qt", WebEngineView.FindCaseSensitively, function(matchCount) { + if (matchCount > 0) + console.log("'Qt' tokens found:", matchCount); + }); + \endcode + + \sa findTextFinished() +*/ + +/*! + \qmlmethod void WebEngineView::grantFeaturePermission(url securityOrigin, Feature feature, bool granted) + \since QtWebEngine 1.1 + \deprecated [6.8] Use webEnginePermission.grant() or webEnginePermission.deny() instead. + + Sets or unsets the permission, depending on \a granted, for the web site + identified by \a securityOrigin to use \a feature. + + \sa featurePermissionRequested() +*/ + + +/*! + \qmlmethod void WebEngineView::fullScreenCancelled() + \since QtWebEngine 1.1 + + Immediately sets \c{isFullScreen} property to \c{false}. It can be used to notify the + browser engine when the windowing system forces the application to leave fullscreen mode. + + \qml + ApplicationWindow { + onVisibilityChanged: { + if (webEngineView.isFullScreen && visibility != Window.FullScreen) + webEngineView.fullScreenCancelled() + } + + WebEngineView { + id: webEngineView + // ... + } + } + \endqml + + \sa isFullScreen, fullScreenRequested() +*/ + +/*! + \qmlmethod void WebEngineView::setActiveFocusOnPress(bool arg) + \since QtWebEngine 1.2 + + Sets active focus to a clicked web engine view if \a arg is \c true. By setting it to \c false, + a web engine view can be used to create a UI element that should not get focus. This can be + useful in a hybrid UI. + + \sa activeFocusOnPress, activeFocusOnPressChanged, + WebEngineSettings::focusOnNavigationEnabled +*/ + +/*! + \qmlmethod void WebEngineView::triggerWebAction(WebAction action) + \since QtWebEngine 1.2 + + Triggers the web action \a action. + + \sa WebAction +*/ + +/*! + \qmlsignal WebEngineView::featurePermissionRequested(url securityOrigin, Feature feature) + \since QtWebEngine 1.1 + \deprecated [6.8] Use \l permissionRequested() instead. + + This signal is emitted when the web site identified by \a securityOrigin requests + to make use of the resource or device identified by \a feature. + + \sa grantFeaturePermission() +*/ + +/*! + \qmlsignal WebEngineView::permissionRequested(webEnginePermission permission) + \since QtWebEngine 6.8 + + This signal is emitted when a web site requests to make use of a feature (e.g. geolocation access, + permission to send notifications). The \a permission object can queried for the requesting URL + and the \c{WebEnginePermission.Feature} it's asking for, as well as to grant or deny permission. +*/ + +/*! + \qmlsignal WebEngineView::loadingChanged(WebEngineLoadingInfo loadingInfo) + + This signal is emitted when a page load begins, ends, or fails. + + When handling the signal with \c onLoadingChanged, various read-only + parameters are available on the WebEngineLoadingInfo specified by + \a loadingInfo. + + \sa loading, LoadStatus, ErrorDomain +*/ + +/*! + \qmlsignal WebEngineView::certificateError(WebEngineCertificateError error) + \since QtWebEngine 1.1 + + This signal is emitted when an invalid certificate error, \a error, is + raised while loading a given request. + + The certificate error can be handled by using the methods of the WebEngineCertificateError + type. +*/ + +/*! + \qmlsignal WebEngineView::linkHovered(url hoveredUrl) + + Within a mouse-driven interface, this signal is emitted when a mouse + pointer passes over a link, corresponding to the \c{mouseover} DOM + event. This event may also occur in touch interfaces for \c{mouseover} + events that are not cancelled with \c{preventDefault()}. \a{hoveredUrl} + provides the link's location. +*/ + +/*! + \qmlsignal WebEngineView::javaScriptConsoleMessage(JavaScriptConsoleMessageLevel level, string message, int lineNumber, string sourceID) + This signal is emitted when a JavaScript program tries to print a \a message to the web browser's console. + + For example, in case of evaluation errors the source URL may be provided in \a sourceID as well + as the \a lineNumber. + + \a level indicates the severity of the event that triggered the message, that is, whether it + was triggered by an error or a less severe event. + + If no handler is specified, the view will log the messages into a \c js + \l{QLoggingCategory}{logging category}. + + \sa{Console Logging} +*/ + +/*! + \qmlsignal WebEngineView::newWindowRequested(WebEngineNewWindowRequest request) + \since QtWebEngine 2.0 + + This signal is emitted when \a request is issued to load a page in a separate + web engine view. This can either be because the current page requested it explicitly + through a JavaScript call to \c window.open, or because the user clicked on a link + while holding Shift, Ctrl, or a built-in combination that triggers the page to open + in a new window. + + The signal is handled by calling acceptAsNewWindow() on the destination view. + If this signal is not handled, the requested load will fail. + + An example implementation: + + \snippet qtwebengine_webengineview_newviewrequested.qml 0 + + \sa WebEngineNewWindowRequest, {WebEngine Quick Nano Browser} +*/ + +/*! + \qmlmethod void WebEngineView::acceptAsNewWindow(QWebEngineNewWindowRequest *request) + \since QtWebEngine 2.0 + + Handle the newWindowRequested signal by opening the \a request in this view. + + \sa newWindowRequested +*/ + +/*! + \qmlsignal WebEngineView::fullScreenRequested(FullScreenRequest request) + \since QtWebEngine 1.1 + + This signal is emitted when the web page issues the \a request for + fullscreen mode through the JavaScript API. + + \sa isFullScreen +*/ + +/*! + \qmlsignal WebEngineView::activeFocusOnPressChanged(bool activeFocusOnPress) + \since QtWebEngine 1.2 + + This signal is emitted when the value of \a activeFocusOnPress changes. + It specifies whether the view should gain active focus when pressed. + + \sa activeFocusOnPress, setActiveFocusOnPress() +*/ + +/*! + \qmlsignal WebEngineView::backgroundColorChanged() + \since QtWebEngine 1.2 + + This signal is emitted when the web engine view background color changes. +*/ + +/*! + \qmlsignal WebEngineView::renderProcessTerminated(RenderProcessTerminationStatus terminationStatus, int exitCode) + + \since QtWebEngine 1.2 + + This signal is emitted when the render process is terminated with a non-zero exit status. + \a terminationStatus is the termination status of the process and \a exitCode is the status code + with which the process terminated. + + \sa RenderProcessTerminationStatus +*/ + +/*! + \qmlsignal WebEngineView::windowCloseRequested() + \since QtWebEngine 1.2 + + This signal is emitted whenever the page requests the web browser window to be closed, + for example through the JavaScript \c{window.close()} call. +*/ + +/*! + \qmlproperty enumeration WebEngineView::ErrorDomain + + Describes various high-level error types: + + \value WebEngineView.NoErrorDomain + \value WebEngineView.InternalErrorDomain + Content fails to be interpreted by \QWE. + \value WebEngineView.ConnectionErrorDomain + Error results from faulty network connection. + \value WebEngineView.CertificateErrorDomain + Error related to the SSL/TLS certificate. + \value WebEngineView.HttpErrorDomain + Error related to the HTTP connection. + \value WebEngineView.FtpErrorDomain + Error related to the FTP connection. + \value WebEngineView.DnsErrorDomain + Error related to the DNS connection. +*/ + +/*! + \qmlproperty enumeration WebEngineView::JavaScriptConsoleMessageLevel + + Indicates the severity of a JavaScript console message: + + \value WebEngineView.InfoMessageLevel + Message is purely informative and can safely be ignored. + \value WebEngineView.WarningMessageLevel + Message indicates there might be a problem that may need attention. + \value WebEngineView.ErrorMessageLevel + Message indicates there has been an error. +*/ + +/*! + \qmlproperty enumeration WebEngineView::LoadStatus + + Reflects a page's load status: + + \value WebEngineView.LoadStartedStatus + Page is currently loading. + \value WebEngineView.LoadStoppedStatus + Loading the page was stopped by the stop() method or by the loader + code or network stack in Chromium. + \value WebEngineView.LoadSucceededStatus + Page has successfully loaded, and is not currently loading. + \value WebEngineView.LoadFailedStatus + Page has failed to load, and is not currently loading. +*/ + +/*! + \qmlproperty enumeration WebEngineView::FindFlags + + Describes the options available to the findText() function. The options + can be OR-ed together from the following list: + + \value WebEngineView.FindBackward + Searches backwards instead of forwards. + \value WebEngineView.FindFlags FindCaseSensitively + By default findText() works case insensitive. Specifying + this option changes the behavior to a case sensitive find operation. + + \sa findText() +*/ + +/*! + \qmlproperty enumeration WebEngineView::RenderProcessTerminationStatus + \since QtWebEngine 1.2 + + Describes the status with which the render process terminated: + + \value WebEngineView.NormalTerminationStatus + The render process terminated normally. + \value WebEngineView.AbnormalTerminationStatus + The render process terminated with a non-zero exit status. + \value WebEngineView.CrashedTerminationStatus + The render process crashed, for example because of a segmentation fault. + \value WebEngineView.KilledTerminationStatus + The render process was killed, for example by \c SIGKILL or task manager kill. +*/ + +/*! + \qmlproperty enumeration WebEngineView::WebAction + \since QtWebEngine 1.2 + + Describes the types of action that can be performed on a web page: + + \value WebEngineView.NoWebAction + No action is triggered. + \value WebEngineView.Back + Navigate back in the history of navigated links. + \value WebEngineView.Forward + Navigate forward in the history of navigated links. + \value WebEngineView.Stop + Stop loading the current page. + \value WebEngineView.Reload + Reload the current page. + \value WebEngineView.ReloadAndBypassCache + Reload the current page, but do not use any local cache. + \value WebEngineView.Cut + Cut the content currently selected into the clipboard. + \value WebEngineView.Copy + Copy the content currently selected into the clipboard. + \value WebEngineView.Paste + Paste content from the clipboard. + \value WebEngineView.Undo + Undo the last editing action. + \value WebEngineView.Redo + Redo the last editing action. + \value WebEngineView.SelectAll + Select all content. + This action is only enabled when the page's content is focused. + The focus can be forced by the JavaScript \c{window.focus()} call, or the + \l{WebEngineSettings::focusOnNavigationEnabled} {focusOnNavigationEnabled} setting + should be enabled to get automatic focus. + \value WebEngineView.PasteAndMatchStyle + Paste content from the clipboard with current style. + \value WebEngineView.OpenLinkInThisWindow + Open the current link in the current window. (Added in Qt 5.6) + \value WebEngineView.OpenLinkInNewWindow + Open the current link in a new window. Requires a handler for the + \l newWindowRequested() signal. (Added in Qt 5.6) + \value WebEngineView.OpenLinkInNewTab + Open the current link in a new tab. Requires a handler for the + \l newWindowRequested() signal. (Added in Qt 5.6) + \value WebEngineView.CopyLinkToClipboard + Copy the current link to the clipboard. (Added in Qt 5.6) + \value WebEngineView.CopyImageToClipboard + Copy the clicked image to the clipboard. (Added in Qt 5.6) + \value WebEngineView.CopyImageUrlToClipboard + Copy the clicked image's URL to the clipboard. (Added in Qt 5.6) + \value WebEngineView.CopyMediaUrlToClipboard + Copy the hovered audio or video's URL to the clipboard. (Added in Qt 5.6) + \value WebEngineView.ToggleMediaControls + Toggle between showing and hiding the controls for the hovered audio or video element. + (Added in Qt 5.6) + \value WebEngineView.ToggleMediaLoop + Toggle whether the hovered audio or video should loop on completetion or not. + (Added in Qt 5.6) + \value WebEngineView.ToggleMediaPlayPause + Toggle the play/pause state of the hovered audio or video element. (Added in Qt 5.6) + \value WebEngineView.ToggleMediaMute + Mute or unmute the hovered audio or video element. (Added in Qt 5.6) + \value WebEngineView.DownloadLinkToDisk + Download the current link to the disk. To implement download + actions, connect to the \l {QQuickWebEngineProfile::downloadRequested} + {WebEngineProfile.downloadRequested} signal. (Added in Qt 5.6) + \value WebEngineView.DownloadImageToDisk + Download the highlighted image to the disk. (Added in Qt 5.6) + \value WebEngineView.DownloadMediaToDisk + Download the hovered audio or video to the disk. (Added in Qt 5.6) + \value WebEngineView.InspectElement + Trigger any attached Web Inspector to inspect the highlighed element. + (Added in Qt 5.6) + \value WebEngineView.ExitFullScreen + Exit the fullscreen mode. (Added in Qt 5.6) + \value WebEngineView.SavePage + Save the current web page to disk. (Added in Qt 5.7) + \omitvalue WebEngineView.OpenLinkInNewBackgroundTab + \value WebEngineView.ViewSource + Show the source of the current page in a new tab. Requires a handler for the + \l newWindowRequested() signal. (Added in Qt 5.8) + + \value WebEngineView.ToggleBold + Toggles boldness for the selection or at the cursor position. + Requires \c contenteditable="true". (Added in Qt 5.10) + \value WebEngineView.ToggleItalic + Toggles italics for the selection or at the cursor position. + Requires \c contenteditable="true". (Added in Qt 5.10) + \value WebEngineView.ToggleUnderline + Toggles underlining of the selection or at the cursor position. + Requires \c contenteditable="true". (Added in Qt 5.10) + \value WebEngineView.ToggleStrikethrough + Toggles striking through the selection or at the cursor position. + Requires \c contenteditable="true". (Added in Qt 5.10) + + \value WebEngineView.AlignLeft + Aligns the lines containing the selection or the cursor to the left. + Requires \c contenteditable="true". (Added in Qt 5.10) + \value WebEngineView.AlignCenter + Aligns the lines containing the selection or the cursor at the center. + Requires \c contenteditable="true". (Added in Qt 5.10) + \value WebEngineView.AlignRight + Aligns the lines containing the selection or the cursor to the right. + Requires \c contenteditable="true". (Added in Qt 5.10) + \value WebEngineView.AlignJustified + Stretches the lines containing the selection or the cursor so that each + line has equal width. + Requires \c contenteditable="true". (Added in Qt 5.10) + \value WebEngineView.Indent + Indents the lines containing the selection or the cursor. + Requires \c contenteditable="true". (Added in Qt 5.10) + \value WebEngineView.Outdent + Outdents the lines containing the selection or the cursor. + Requires \c contenteditable="true". (Added in Qt 5.10) + + \value WebEngineView.InsertOrderedList + Inserts an ordered list at the current cursor position, deleting the current selection. + Requires \c contenteditable="true". (Added in Qt 5.10) + \value WebEngineView.InsertUnorderedList + Inserts an unordered list at the current cursor position, + deleting the current selection. + Requires \c contenteditable="true". (Added in Qt 5.10) + \value WebEngineView.ChangeTextDirectionLTR + Changes text direction to left-to-right in the focused input element. (Added in Qt 6.6) + \value WebEngineView.ChangeTextDirectionRTL + Changes text direction to right-to-left in the focused input element. (Added in Qt 6.6) + \omitvalue WebActionCount +*/ + +/*! + \qmlproperty enumeration WebEngineView::Feature + \deprecated [6.8] Replaced by WebEnginePermission.Feature. + + Describes the platform feature access categories that the user may be asked to grant or deny + access to: + + \value WebEngineView.Geolocation + Location hardware or service. + \value WebEngineView.MediaAudioCapture + Audio capture devices, such as microphones. + \value WebEngineView.MediaVideoCapture + Video devices, such as cameras. + \value WebEngineView.MediaAudioVideoCapture + Both audio and video capture devices. + \value WebEngineView.DesktopVideoCapture + Video output capture, that is, the capture of the user's display. + (Added in Qt 5.10) + \value WebEngineView.DesktopAudioVideoCapture + Both audio and video output capture. (Added in Qt 5.10) + \value WebEngineView.Notifications + Web notifications for the end-user. + \value WebEngineView.ClipboardReadWrite + Read and write access for the clipboard. If both \l{WebEngineSettings::JavascriptCanPaste} + {JavascriptCanPaste} and \l{WebEngineSettings::JavascriptCanAccessClipboard} + {JavascriptCanAccessClipboard} settings are enabled, this permission will always be granted + automatically and no feature requests will be made. + (Added in Qt 6.8) + \value WebEngineView.LocalFontsAccess + Access to the fonts installed on the user's machine. Only available on desktop platforms. + (Added in Qt 6.8) + + \sa featurePermissionRequested(), grantFeaturePermission() +*/ + +/*! + \qmlproperty enumeration WebEngineView::PrintedPageSizeId + \since QtWebEngine 1.3 + + This enum type lists the available page sizes as defined in the Postscript + PPD standard. + + The enumeration values are mapped from and must match QPageSize::PageSizeId. They are also + duplicated in QPagedPaintDevice and QPrinter. + + The defined sizes are: + + \value WebEngineView.A0 841 x 1189 mm + \value WebEngineView.A1 594 x 841 mm + \value WebEngineView.A2 420 x 594 mm + \value WebEngineView.A3 297 x 420 mm + \value WebEngineView.A4 210 x 297 mm, 8.26 x 11.69 inches + \value WebEngineView.A5 148 x 210 mm + \value WebEngineView.A6 105 x 148 mm + \value WebEngineView.A7 74 x 105 mm + \value WebEngineView.A8 52 x 74 mm + \value WebEngineView.A9 37 x 52 mm + \value WebEngineView.B0 1000 x 1414 mm + \value WebEngineView.B1 707 x 1000 mm + \value WebEngineView.B2 500 x 707 mm + \value WebEngineView.B3 353 x 500 mm + \value WebEngineView.B4 250 x 353 mm + \value WebEngineView.B5 176 x 250 mm, 6.93 x 9.84 inches + \value WebEngineView.B6 125 x 176 mm + \value WebEngineView.B7 88 x 125 mm + \value WebEngineView.B8 62 x 88 mm + \value WebEngineView.B9 44 x 62 mm + \value WebEngineView.B10 31 x 44 mm + \value WebEngineView.C5E 163 x 229 mm + \value WebEngineView.Comm10E 105 x 241 mm, U.S. Common 10 Envelope + \value WebEngineView.DLE 110 x 220 mm + \value WebEngineView.Executive 7.5 x 10 inches, 190.5 x 254 mm + \value WebEngineView.Folio 210 x 330 mm + \value WebEngineView.Ledger 431.8 x 279.4 mm + \value WebEngineView.Legal 8.5 x 14 inches, 215.9 x 355.6 mm + \value WebEngineView.Letter 8.5 x 11 inches, 215.9 x 279.4 mm + \value WebEngineView.Tabloid 279.4 x 431.8 mm + \value WebEngineView.Custom Unknown, or a user defined size. + \value WebEngineView.A10 + \value WebEngineView.A3Extra + \value WebEngineView.A4Extra + \value WebEngineView.A4Plus + \value WebEngineView.A4Small + \value WebEngineView.A5Extra + \value WebEngineView.B5Extra + \value WebEngineView.JisB0 + \value WebEngineView.JisB1 + \value WebEngineView.JisB2 + \value WebEngineView.JisB3 + \value WebEngineView.JisB4 + \value WebEngineView.JisB5 + \value WebEngineView.JisB6 + \value WebEngineView.JisB7 + \value WebEngineView.JisB8 + \value WebEngineView.JisB9 + \value WebEngineView.JisB10 + \value WebEngineView.AnsiA = \c Letter + \value WebEngineView.AnsiB = \c Ledger + \value WebEngineView.AnsiC + \value WebEngineView.AnsiD + \value WebEngineView.AnsiE + \value WebEngineView.LegalExtra + \value WebEngineView.LetterExtra + \value WebEngineView.LetterPlus + \value WebEngineView.LetterSmall + \value WebEngineView.TabloidExtra + \value WebEngineView.ArchA + \value WebEngineView.ArchB + \value WebEngineView.ArchC + \value WebEngineView.ArchD + \value WebEngineView.ArchE + \value WebEngineView.Imperial7x9 + \value WebEngineView.Imperial8x10 + \value WebEngineView.Imperial9x11 + \value WebEngineView.Imperial9x12 + \value WebEngineView.Imperial10x11 + \value WebEngineView.Imperial10x13 + \value WebEngineView.Imperial10x14 + \value WebEngineView.Imperial12x11 + \value WebEngineView.Imperial15x11 + \value WebEngineView.ExecutiveStandard + \value WebEngineView.Note + \value WebEngineView.Quarto + \value WebEngineView.Statement + \value WebEngineView.SuperA + \value WebEngineView.SuperB + \value WebEngineView.Postcard + \value WebEngineView.DoublePostcard + \value WebEngineView.Prc16K + \value WebEngineView.Prc32K + \value WebEngineView.Prc32KBig + \value WebEngineView.FanFoldUS + \value WebEngineView.FanFoldGerman + \value WebEngineView.FanFoldGermanLegal + \value WebEngineView.EnvelopeB4 + \value WebEngineView.EnvelopeB5 + \value WebEngineView.EnvelopeB6 + \value WebEngineView.EnvelopeC0 + \value WebEngineView.EnvelopeC1 + \value WebEngineView.EnvelopeC2 + \value WebEngineView.EnvelopeC3 + \value WebEngineView.EnvelopeC4 + \value WebEngineView.EnvelopeC5 = \c C5E + \value WebEngineView.EnvelopeC6 + \value WebEngineView.EnvelopeC65 + \value WebEngineView.EnvelopeC7 + \value WebEngineView.EnvelopeDL = \c DLE + \value WebEngineView.Envelope9 + \value WebEngineView.Envelope10 = \c Comm10E + \value WebEngineView.Envelope11 + \value WebEngineView.Envelope12 + \value WebEngineView.Envelope14 + \value WebEngineView.EnvelopeMonarch + \value WebEngineView.EnvelopePersonal + \value WebEngineView.EnvelopeChou3 + \value WebEngineView.EnvelopeChou4 + \value WebEngineView.EnvelopeInvite + \value WebEngineView.EnvelopeItalian + \value WebEngineView.EnvelopeKaku2 + \value WebEngineView.EnvelopeKaku3 + \value WebEngineView.EnvelopePrc1 + \value WebEngineView.EnvelopePrc2 + \value WebEngineView.EnvelopePrc3 + \value WebEngineView.EnvelopePrc4 + \value WebEngineView.EnvelopePrc5 + \value WebEngineView.EnvelopePrc6 + \value WebEngineView.EnvelopePrc7 + \value WebEngineView.EnvelopePrc8 + \value WebEngineView.EnvelopePrc9 + \value WebEngineView.EnvelopePrc10 + \value WebEngineView.EnvelopeYou4 + \value WebEngineView.LastPageSize = \c EnvelopeYou4 + + \sa WebEngineView::printToPdf() +*/ + +/*! + \qmlproperty enumeration WebEngineView::PrintedPageOrientation + \since QtWebEngine 1.3 + + Describes the orientation of a PDF document that gets created from the WebEngineView's contents. + The enumeration values are mapped from and must match QPageLayout::Orientation. + + \value WebEngineView.Portrait + The document will be created using portrait orientation. + + \value WebEngineView.Landscape + The document will be created using landscape orientation. + + \sa WebEngineView::printToPdf() +*/ + +/*! + \qmlproperty bool WebEngineView::activeFocusOnPress + \since QtWebEngine 1.2 + + Specifies whether the view should gain active focus when pressed. + The default value is \c true. +*/ + +/*! + \qmlproperty color WebEngineView::backgroundColor + \since QtWebEngine 1.2 + + Changes the color of the WebEngineView's background, behind the document's + body. Can be set to \c "transparent" or to a translucent color to see + through the document or to match the web content in a hybrid app to prevent + the white flashes that may appear during loading. + + The default value is white. +*/ + +/*! + \qmlproperty bool WebEngineView::audioMuted + \brief The state of whether the current page audio is muted. + \since QtWebEngine 1.3 + \sa recentlyAudible +*/ + +/*! + \qmlsignal WebEngineView::audioMutedChanged(bool muted) + \since QtWebEngine 1.3 + + This signal is emitted when the value of \a muted changes. The value is + specified using the \l audioMuted property. + \note Not to be confused with a specific HTML5 audio / video element being muted. + + \sa audioMuted, recentlyAudibleChanged +*/ + +/*! + \qmlproperty bool WebEngineView::recentlyAudible + \brief Returns the current page's audible state (audio was recently played, or not). + \since QtWebEngine 1.3 + \readonly + \sa audioMuted, recentlyAudibleChanged +*/ + +/*! + \qmlsignal WebEngineView::recentlyAudibleChanged(bool recentlyAudible) + \since QtWebEngine 1.3 + + This signal is emitted when the page's audible state, specified by + \a recentlyAudible, is changed, due to audio being played or stopped. + + \note The signal is also emitted when the \l audioMuted property changes. + Also if the audio is paused, this signal is emitted with an approximate \b{two-second + delay}, from the moment the audio is paused. + + If a web page contains two videos that are started in sequence, this signal + gets emitted only once, for the first video to generate sound. After both + videos are stopped, the signal is emitted upon the last sound generated. + This means that the signal is emitted both when any kind of sound is + generated and when everything is completely silent within a web page, + regardless of the number of audio streams. + + Spurious signal emissions might also happen. For example, when sound is + stopped, this signal gets emitted first with a value of \c true, and then + with a value of \c false. Further, when audio starts playing, the signal is + emitted twice with a value of \c true. + + \sa recentlyAudible +*/ + +/*! + \qmlsignal WebEngineView::pdfPrintingFinished(string filePath, bool success) + \since QtWebEngine 1.5 + + This signal is emitted when printing the web page into a PDF file has + finished. + \a filePath will contain the path the file was requested to be created + at, and \a success will be \c true if the file was successfully created and + \c false otherwise. + + \sa printToPdf() +*/ + +/*! + \qmlmethod void WebEngineView::printToPdf(const string filePath, PrintedPageSizeId pageSizeId, PrintedPageOrientation orientation) + \since QtWebEngine 1.3 + + Prints the WebEngineView's current content to a PDF document and stores it + under \a filePath. The document's size will be determined by the value of + \a pageSizeId and its orientation will be determined using \a orientation. + + This method issues an asynchronous request for printing the web page into a + PDF and returns immediately. To be informed about the result of the + request, connect to the signal pdfPrintingFinished(). + + If you leave out \a pageSizeId, it defaults to \c A4. If you leave out + \a orientation, it defaults to \c Portrait. + + \sa pdfPrintingFinished() +*/ + +/*! + \qmlmethod void WebEngineView::printToPdf(variant resultCallback, PrintedPageSizeId pageSizeId, PrintedPageOrientation orientation) + \since QtWebEngine 1.3 + + Prints the WebEngineView's current content to a PDF document and returns it in a byte array. The document's size will be determined + by the value of \a pageSizeId and its orientation will be determined using \a orientation. + + The \a resultCallback must take a string parameter. This string will contain the document's data upon successful printing and an empty + string otherwise. + + If you leave out \a pageSizeId, it defaults to \c A4. If you leave out + \a orientation, it defaults to \c Portrait. +*/ + +/*! + \qmlmethod void WebEngineView::replaceMisspelledWord(const QString &replacement) + \since QtWebEngine 1.3 + + Replace the current misspelled word with \a replacement. +*/ + +/*! + \qmlsignal WebEngineView::wasRecentlyAudibleChanged(bool wasRecentlyAudible) + \since QtWebEngine 1.3 + + This signal is emitted when the page's audible state, specified by + \a wasRecentlyAudible, is changed, due to audio being played or stopped. + + \note The signal is also emitted when calling the setAudioMuted method. +*/ + +/*! + \qmlsignal WebEngineView::authenticationDialogRequested(AuthenticationDialogRequest request) + \since QtWebEngine 1.4 + + This signal is emitted when an authentication dialog is requested. + + The \a request can be handled by using the methods of the AuthenticationDialogRequest + type. + + \note Signal handlers need to call \c{request.accepted = true} to prevent a + default dialog from showing up. Make sure to call either + AuthenticationDialogRequest::dialogAccept() or AuthenticationDialogRequest::dialogReject() + afterwards. +*/ + +/*! + \qmlsignal WebEngineView::javaScriptDialogRequested(JavaScriptDialogRequest request) + \since QtWebEngine 1.4 + + This signal is emitted when a JavaScript dialog is requested. + + The \a request can be handled by using the methods of the JavaScriptDialogRequest + type. + + \note Signal handlers need to call \c{request.accepted = true} to prevent a + default dialog from showing up. Make sure to call either + JavaScriptDialogRequest::dialogAccept() or JavaScriptDialogRequest::dialogReject() + afterwards. +*/ + +/*! + \qmlsignal WebEngineView::colorDialogRequested(ColorDialogRequest request) + \since QtWebEngine 1.4 + + This signal is emitted when a color picker dialog is requested. + + The \a request can be handled by using the methods of the ColorDialogRequest + type. + + \note Signal handlers need to call \c{request.accepted = true} to prevent a + default dialog from showing up. Make sure to call either + ColorDialogRequest::dialogAccept() or ColorDialogRequest::dialogReject() afterwards. +*/ + +/*! + \qmlsignal WebEngineView::fileDialogRequested(FileDialogRequest request) + \since QtWebEngine 1.4 + + This signal is emitted when a file picker dialog is requested. + + The \a request can be handled by using the methods of the FileDialogRequest + type. + + \note Signal handlers need to call \c{request.accepted = true} to prevent a + default dialog from showing up. Make sure to call either FileDialogRequest::dialogAccept() + or FileDialogRequest::dialogReject() afterwards. +*/ + +/*! + \qmlsignal WebEngineView::contextMenuRequested(ContextMenuRequest request) + \since QtWebEngine 1.4 + + This signal is emitted when a context menu is requested. + + The \a request can be handled by using the properties of the ContextMenuRequest + type. + + \note Signal handlers need to call \c{request.accepted = true} to prevent a + default context menu from showing up. +*/ + +/*! \qmlsignal WebEngineView::navigationRequested(WebEngineNavigationRequest request) + This signal is emitted when the navigation request \a request is issued. +*/ + +/*! + \qmlsignal WebEngineView::quotaRequested(QuotaRequest request) + \since QtWebEngine 1.7 + \deprecated [6.5] This signal is no longer emitted. + + Requesting host quota is no longer supported by Chromium. + The behavior of navigator.webkitPersistentStorage + is identical to navigator.webkitTemporaryStorage. + + For further details, see https://crbug.com/1233525 + + \sa QuotaRequest +*/ + +/*! + \qmlsignal WebEngineView::registerProtocolHandlerRequested(RegisterProtocolHandlerRequest request) + \since QtWebEngine 1.7 + + This signal is emitted when the web page tries to register a custom protocol + by issuing a \l registerProtocolHandler \a request. + + \sa RegisterProtocolHandlerRequest +*/ + +/*! + \qmlsignal WebEngineView::geometryChangeRequested(rect geometry, rect frameGeometry) + \since QtWebEngine 1.7 + + This signal is emitted whenever the document wants to change the position and size of the + page to \a frameGeometry. This can happen for example through JavaScript. + + While \a frameGeometry includes, \a geometry excludes the size of frame margins. + + \note Geometry related properties of QML Window expect a size excluding the window + decoration. You have to use \a geometry to handle this signal correctly. + + \qml + onGeometryChangeRequested: { + window.x = geometry.x + window.y = geometry.y + window.width = geometry.width + window.height = geometry.height + } + \endqml +*/ + +/*! + \qmlproperty WebEngineView WebEngineView::inspectedView + \since QtWebEngine 1.7 + + The view this view is currently inspecting, if any. Setting it + will navigate to an internal URL with the developer tools of + the view set. + + It is recommended to unset this property when developer tools + are not visible; otherwise some debug information may appear + in the inspected WebEngineView. + + \sa devToolsView +*/ + +/*! + \qmlproperty WebEngineView WebEngineView::devToolsView + \since QtWebEngine 1.7 + + The view currently hosting the developer tools for this view. + Setting it to a new view will navigate that view to an internal + URL with the developer tools, and bind it to this view. + + \sa inspectedView +*/ + +/*! + \qmlproperty WebEngineView WebEngineView::devToolsId + \since QtWebEngine 6.6 + \readonly + + The id of the developer tools host associated with this page. + + If remote debugging is enabled (see \l{Qt WebEngine Developer Tools}), the id can be used to + build the URL to connect to the developer tool websocket: + \c{ws://localhost:<debugggin-port>/devtools/page/<id>)}. The websocket can be used to to interact + with the page using the \l{https://chromedevtools.github.io/devtools-protocol/}{DevTools + Protocol}. +*/ + +/*! + \qmlmethod WebEngineAction WebEngineView::action(WebAction action) + \since 5.12 + + Returns a \l WebEngineAction for the specified \l WebAction \a action. + WebEngineView also takes care of implementing the action, + so that upon triggering the corresponding action is performed on the view. + + \code + var copyAction = webEngineView.action(WebEngineView.Copy); + \endcode + + \sa WebEngineAction +*/ + +/*! + \qmlsignal WebEngineView::printRequested + \since QtWebEngine 1.8 + + This signal is emitted when the JavaScript \c{window.print()} method is called on the main + frame, or the user pressed the print button of PDF viewer plugin. + Typically, the signal handler can simply call printToPdf(). + + Since QtWebEngine 6.8, this signal is only emitted for the main frame, instead of being emitted + for any frame that requests printing. + + \sa printToPdf +*/ + +/*! + \qmlsignal WebEngineView::printRequestedByFrame(webEngineFrame frame) + \since QtWebEngine 6.8 + + This signal is emitted when the JavaScript \c{window.print()} method is called on \a frame. + If the frame is the main frame, \c{printRequested} is emitted instead. + + \sa printRequested +*/ + +/*! + \qmlsignal WebEngineView::selectClientCertificate(WebEngineClientCertificateSelection clientCertificateSelection) + \since QtWebEngine 1.9 + + This signal is emitted when a web site requests an SSL client certificate, and one or more were + found in the system's client certificate store. + + Handling the signal is asynchronous, and loading will be waiting until a certificate is selected, + or the last copy of \a clientCertificateSelection is destroyed. + + If the signal is not handled, \a clientCertificateSelection is automatically destroyed, and loading + will continue without a client certificate. + + \sa WebEngineClientCertificateSelection +*/ + +/*! + \qmlsignal WebEngineView::tooltipRequested(TooltipRequest request) + \since QtWebEngine 1.10 + + This signal is emitted when the web page sends a \a request to show a tooltip at + a specified position. + + \note Signal handlers need to call \c{request.accepted = true} to prevent a default tooltip from showing up. + + \sa TooltipRequest +*/ + +/*! + \qmlproperty enumeration WebEngineView::LifecycleState + \since QtWebEngine 1.10 + + This enum describes the lifecycle state of the page: + + \value WebEngineView.LifecycleState.Active + Normal state. + \value WebEngineView.LifecycleState.Frozen + Low CPU usage state where most HTML task sources are suspended. + \value WebEngineView.LifecycleState.Discarded + Very low resource usage state where the entire browsing context is discarded. + + \sa lifecycleState, {Page Lifecycle API}, {WebEngine Lifecycle Example} +*/ + +/*! + \qmlproperty LifecycleState WebEngineView::lifecycleState + \since QtWebEngine 1.10 + + \brief The current lifecycle state of the page. + + The following restrictions are enforced by the setter: + + \list + \li A visible page must remain in the \c{Active} state. + \li If the page is being inspected by a \l{devToolsView} then both pages must + remain in the \c{Active} states. + \li A page in the \c{Discarded} state can only transition to the \c{Active} + state. This will cause a reload of the page. + \endlist + + These are the only hard limits on the lifecycle state, but see also + \l{recommendedState} for the recommended soft limits. + + \sa recommendedState, {Page Lifecycle API}, {WebEngine Lifecycle Example} +*/ + +/*! + \qmlproperty LifecycleState WebEngineView::recommendedState + \since QtWebEngine 1.10 + + \brief The recommended limit for the lifecycle state of the page. + + Setting the lifecycle state to a lower resource usage state than the + recommended state may cause side-effects such as stopping background audio + playback or loss of HTML form input. Setting the lifecycle state to a higher + resource state is however completely safe. + + \sa lifecycleState, {Page Lifecycle API}, {WebEngine Lifecycle Example} +*/ + +/*! + \qmltype FindTextResult + \instantiates QWebEngineFindTextResult + \inqmlmodule QtWebEngine + \since QtWebEngine 1.10 + + \brief A utility type for encapsulating the result of a string search on a page. + + \sa WebEngineView::findTextFinished() +*/ + +/*! + \qmlproperty int FindTextResult::numberOfMatches + \readonly + + \brief The number of matches found. +*/ + +/*! + \qmlproperty int FindTextResult::activeMatch + \readonly + + \brief The index of the currently highlighted match. +*/ + +/*! + \qmlsignal WebEngineView::findTextFinished(FindTextResult result) + \since QtWebEngine 1.10 + + This signal is emitted when a string search on a page is completed. \a result is + the result of the string search. + + \sa findText(), FindTextResult +*/ + +/*! + \qmlproperty qint64 WebEngineView::renderProcessPid + \brief Returns the process ID (PID) of the render process assigned to the + current page's main frame. + \since QtWebEngine 1.11 + \readonly + + If no render process is available yet, \c 0 is returned. + + \sa renderProcessPidChanged +*/ +/*! + \qmlsignal WebEngineView::renderProcessPidChanged(qint64 pid) + \since QtWebEngine 1.11 + \readonly + + If no render process is available yet, \c 0 is returned. + This signal is emitted when \a pid (process ID) of the page's underlying + render process changed. + + \sa renderProcessPid +*/ + +/*! + \qmlsignal WebEngineView::touchSelectionMenuRequested(TouchSelectionMenuRequest *request) + \since QtWebEngine 6.3 + \readonly + + This signal is emitted when a touch selection menu is requested at a specified position. + + The \a request can be handled by using the methods of the TouchSelectionMenuRequest + type. + + \note Signal handlers need to call \c{request.accepted = true} to prevent a default touch + selection menu from showing up. + + \sa TouchSelectionMenuRequest +*/ + +/*! + \qmlproperty Component WebEngineView::touchHandleDelegate + \since QtWebEngine 6.4 + + The \a touchHandleDelegate provides a template defining visual touch handles instantiated by the view + whenever touch selection handling is required. + + The handle's position, opacity, and visibility are updated automatically. + The delegate should be a QML Item or any QML type which inherits it. + + \note If no QML Item is set, the default touch handles will be shown. + + The following code uses a custom touch handle delegate: + + \code + WebEngineView { + // ... + touchHandleDelegate: Rectangle { + color: "red" + } + // ... + } + \endcode + + The touch handles can be also switched dynamically: + + \code + Component { + id: circleTouchHandle + Rectangle { + color: "blue" + radius: 50 + } + } + function showDefaultHandle(isDefault) { + if (isDefault) + webEngineView.touchHandleDelegate = circleTouchHandle + else + webEngineView.touchHandleDelegate = null + } + \endcode + + \note If no delegate is provided, Chromium's default touch handles will appear. + +*/ + +/*! + \qmlproperty webEngineFrame WebEngineView::mainFrame + \since QtWebEngine 6.8 + + The main, top-level frame of the page. All other frames on this page are accessible + as children of the main frame. + */ + +/*! + \qmlmethod webEngineFrame WebEngineView::findFrameByName(string name) + \since QtWebEngine 6.8 + + Returns the frame with the given \a name. If there are multiple frames with the same + name, which one is returned is arbitrary. If no frame was found, returns an + \l{webEngineFrame::isValid}{invalid} frame. +*/ + +/*! + \qmlmethod void WebEngineView::save(const QString &filePath, QWebEngineDownloadRequest::SavePageFormat format) + \since QtWebEngine 6.6 + + Save the current web page to disk. + + The web page is saved to \a filePath in the specified \a{format}. + + This is a shortcut for the following actions: + \list + \li Trigger the Save web action. + \li Accept the next download item and set the specified file path and save format. + \endlist + + This function issues an asynchronous download request for the web page and returns immediately. + + \sa QWebEngineDownloadRequest::SavePageFormat +*/ + +/*! + \qmlsignal WebEngineView::webAuthUxRequested(QWebEngineWebAuthUxRequest *request); + \since QtWebEngine 6.7 + + This signal is emitted when a WebAuth authenticator requires user interaction + during the authentication process. These requests are handled by displaying a dialog to the user. + + The \a request contains the information and API required to complete the WebAuth UX request. + + \sa QWebEngineWebAuthUxRequest +*/ + +/*! + \qmlsignal WebEngineView::zoomFactorChanged(qreal factor); + \since QtWebEngine 6.8 + + This signal is emitted whenever the zoom \a factor for the page changes. + + \sa zoomFactor +*/ + + \sa {WebEngine Qt Quick Custom Touch Handle Example} +*/ diff --git a/src/webenginequick/plugin.cpp b/src/webenginequick/plugin.cpp new file mode 100644 index 000000000..e06596b44 --- /dev/null +++ b/src/webenginequick/plugin.cpp @@ -0,0 +1,40 @@ +// 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 <QtQml/qqmlextensionplugin.h> +#include <QtWebEngineQuick/QQuickWebEngineProfile> + +#include <QtWebEngineQuick/private/qquickwebenginefaviconprovider_p_p.h> +#include <QtWebEngineQuick/private/qquickwebenginetouchhandleprovider_p_p.h> + +#if QT_VERSION >= QT_VERSION_CHECK(6, 4, 0) +QT_BEGIN_NAMESPACE +void Q_WEBENGINEQUICK_EXPORT qml_register_types_QtWebEngine(); +QT_END_NAMESPACE +#else +void Q_WEBENGINEQUICK_EXPORT qml_register_types_QtWebEngine(); +#endif + +QT_BEGIN_NAMESPACE + +class QtWebEnginePlugin : public QQmlExtensionPlugin +{ + Q_OBJECT + Q_PLUGIN_METADATA(IID QQmlExtensionInterface_iid) +public: + void initializeEngine(QQmlEngine *engine, const char *uri) override + { + Q_UNUSED(uri); + engine->addImageProvider(QQuickWebEngineFaviconProvider::identifier(), new QQuickWebEngineFaviconProvider); + engine->addImageProvider(QQuickWebEngineTouchHandleProvider::identifier(), new QQuickWebEngineTouchHandleProvider); + } + void registerTypes(const char *uri) override { + volatile auto registration = &qml_register_types_QtWebEngine; + Q_UNUSED(registration); + Q_UNUSED(uri); + }; +}; + +QT_END_NAMESPACE + +#include "plugin.moc" diff --git a/src/webenginequick/qquickwebengine_accessible.cpp b/src/webenginequick/qquickwebengine_accessible.cpp new file mode 100644 index 000000000..e156a5e8b --- /dev/null +++ b/src/webenginequick/qquickwebengine_accessible.cpp @@ -0,0 +1,147 @@ +// 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 "qquickwebengine_accessible_p.h" + +#include <QQuickItem> +#include <QQuickWindow> + +#include "api/qquickwebengineview_p.h" +#include "api/qquickwebengineview_p_p.h" +#include "web_contents_adapter.h" + +QT_BEGIN_NAMESPACE +QQuickWebEngineViewAccessible::QQuickWebEngineViewAccessible(QQuickWebEngineView *o) + : QAccessibleObject(o) +{} + +bool QQuickWebEngineViewAccessible::isValid() const +{ + if (!QAccessibleObject::isValid()) + return false; + + if (!engineView() || !engineView()->d_func()) + return false; + + return true; +} + +QAccessibleInterface *QQuickWebEngineViewAccessible::parent() const +{ + QQuickItem *parent = engineView()->parentItem(); + QAccessibleInterface *iface = QAccessible::queryAccessibleInterface(parent); + if (!iface) + return QAccessible::queryAccessibleInterface(engineView()->window()); + return iface; +} + +QAccessibleInterface *QQuickWebEngineViewAccessible::focusChild() const +{ + if (child(0) && child(0)->focusChild()) + return child(0)->focusChild(); + return const_cast<QQuickWebEngineViewAccessible *>(this); +} + +int QQuickWebEngineViewAccessible::childCount() const +{ + return child(0) ? 1 : 0; +} + +QAccessibleInterface *QQuickWebEngineViewAccessible::child(int index) const +{ + if (index == 0 && isValid()) + return engineView()->d_func()->adapter->browserAccessible(); + return nullptr; +} + +int QQuickWebEngineViewAccessible::indexOfChild(const QAccessibleInterface *c) const +{ + if (child(0) && c == child(0)) + return 0; + return -1; +} + +QString QQuickWebEngineViewAccessible::text(QAccessible::Text) const +{ + return QString(); +} + +QAccessible::Role QQuickWebEngineViewAccessible::role() const +{ + return QAccessible::Client; +} + +QAccessible::State QQuickWebEngineViewAccessible::state() const +{ + QAccessible::State s; + return s; +} + +QQuickWebEngineView *QQuickWebEngineViewAccessible::engineView() const +{ + return static_cast<QQuickWebEngineView*>(object()); +} + +QT_END_NAMESPACE + +namespace QtWebEngineCore { + +RenderWidgetHostViewQtDelegateQuickAccessible::RenderWidgetHostViewQtDelegateQuickAccessible(QObject *o, QQuickWebEngineView *view) + : QAccessibleObject(o) + , m_view(view) +{ +} + +bool RenderWidgetHostViewQtDelegateQuickAccessible::isValid() const +{ + if (!viewAccessible() || !viewAccessible()->isValid()) + return false; + + return QAccessibleObject::isValid(); +} + +QAccessibleInterface *RenderWidgetHostViewQtDelegateQuickAccessible::parent() const +{ + return viewAccessible()->parent(); +} + +QString RenderWidgetHostViewQtDelegateQuickAccessible::text(QAccessible::Text) const +{ + return QString(); +} + +QAccessible::Role RenderWidgetHostViewQtDelegateQuickAccessible::role() const +{ + return QAccessible::Client; +} + +QAccessible::State RenderWidgetHostViewQtDelegateQuickAccessible::state() const +{ + return viewAccessible()->state(); +} + +QAccessibleInterface *RenderWidgetHostViewQtDelegateQuickAccessible::focusChild() const +{ + return viewAccessible()->focusChild(); +} + +int RenderWidgetHostViewQtDelegateQuickAccessible::childCount() const +{ + return viewAccessible()->childCount(); +} + +QAccessibleInterface *RenderWidgetHostViewQtDelegateQuickAccessible::child(int index) const +{ + return viewAccessible()->child(index); +} + +int RenderWidgetHostViewQtDelegateQuickAccessible::indexOfChild(const QAccessibleInterface *c) const +{ + return viewAccessible()->indexOfChild(c); +} + +QQuickWebEngineViewAccessible *RenderWidgetHostViewQtDelegateQuickAccessible::viewAccessible() const +{ + return static_cast<QQuickWebEngineViewAccessible *>(QAccessible::queryAccessibleInterface(m_view)); +} +} // namespace QtWebEngineCore diff --git a/src/webenginequick/qquickwebengine_accessible_p.h b/src/webenginequick/qquickwebengine_accessible_p.h new file mode 100644 index 000000000..2f774f898 --- /dev/null +++ b/src/webenginequick/qquickwebengine_accessible_p.h @@ -0,0 +1,67 @@ +// 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 QQUICKWEBENGINE_ACCESSIBLE_H +#define QQUICKWEBENGINE_ACCESSIBLE_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists for the convenience +// of other Qt classes. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include <QtCore/qpointer.h> +#include <QtGui/qaccessibleobject.h> + +QT_BEGIN_NAMESPACE +class QQuickWebEngineView; + +class QQuickWebEngineViewAccessible : public QAccessibleObject +{ +public: + QQuickWebEngineViewAccessible(QQuickWebEngineView *o); + bool isValid() const override; + QAccessibleInterface *parent() const override; + QAccessibleInterface *focusChild() const override; + int childCount() const override; + QAccessibleInterface *child(int index) const override; + int indexOfChild(const QAccessibleInterface *) const override; + QString text(QAccessible::Text) const override; + QAccessible::Role role() const override; + QAccessible::State state() const override; + +private: + QQuickWebEngineView *engineView() const; +}; + +QT_END_NAMESPACE + +namespace QtWebEngineCore { +class RenderWidgetHostViewQtDelegateQuickAccessible : public QAccessibleObject +{ +public: + RenderWidgetHostViewQtDelegateQuickAccessible(QObject *o, QQuickWebEngineView *view); + + bool isValid() const override; + QAccessibleInterface *parent() const override; + QString text(QAccessible::Text t) const override; + QAccessible::Role role() const override; + QAccessible::State state() const override; + + QAccessibleInterface *focusChild() const override; + int childCount() const override; + QAccessibleInterface *child(int index) const override; + int indexOfChild(const QAccessibleInterface *) const override; + +private: + QQuickWebEngineViewAccessible *viewAccessible() const; + QPointer<QQuickWebEngineView> m_view; +}; +} // namespace QtWebEngineCore + +#endif // QQUICKWEBENGINE_ACCESSIBLE_H diff --git a/src/webenginequick/render_widget_host_view_qt_delegate_quickwindow.cpp b/src/webenginequick/render_widget_host_view_qt_delegate_quickwindow.cpp new file mode 100644 index 000000000..090b09281 --- /dev/null +++ b/src/webenginequick/render_widget_host_view_qt_delegate_quickwindow.cpp @@ -0,0 +1,132 @@ +// 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 "render_widget_host_view_qt_delegate_quickwindow_p.h" + +#include "api/qquickwebengineview_p_p.h" + +namespace QtWebEngineCore { + +static inline QPoint getOffset(QQuickItem *item) +{ + // get parent window (scene) offset + QPointF offset = item->mapFromScene(QPoint(0, 0)); + offset = item->mapToGlobal(offset); + // get local offset + offset -= item->mapToScene(QPoint(0, 0)); + return offset.toPoint(); +} + +static inline QPointF transformPoint(const QPointF &point, const QTransform &transform, + const QPointF &offset, const QQuickItem *parent) +{ + // make scene vector + QPointF a = point - offset; + // apply local transformation + a = transform.map(a); + // make screen coordinates + a = parent->mapFromScene(a); + a = parent->mapToGlobal(a); + return a; +} + +RenderWidgetHostViewQtDelegateQuickWindow::RenderWidgetHostViewQtDelegateQuickWindow( + RenderWidgetHostViewQtDelegateItem *realDelegate, QWindow *parent) + : QQuickWindow(parent), m_realDelegate(realDelegate), m_virtualParent(nullptr), m_rotated(false) +{ + setFlags(Qt::Tool | Qt::WindowStaysOnTopHint | Qt::FramelessWindowHint | Qt::WindowDoesNotAcceptFocus); + realDelegate->setParentItem(contentItem()); +} + +RenderWidgetHostViewQtDelegateQuickWindow::~RenderWidgetHostViewQtDelegateQuickWindow() +{ + if (m_realDelegate) { + m_realDelegate->setWidgetDelegate(nullptr); + m_realDelegate->setParentItem(nullptr); + } +} + +void RenderWidgetHostViewQtDelegateQuickWindow::setVirtualParent(QQuickItem *virtualParent) +{ + Q_ASSERT(virtualParent); + m_virtualParent = virtualParent; +} + +// rect is window geometry in form of parent window offset + offset in scene coordinates +// chromium knows nothing about local transformation +void RenderWidgetHostViewQtDelegateQuickWindow::InitAsPopup(const QRect &rect) +{ + m_rotated = m_virtualParent->rotation() > 0 || m_virtualParent->parentItem()->rotation() > 0; + if (m_rotated) { + // code below tries to cover the case where webengine view is rotated, + // the code assumes the rotation is in the form of 90, 180, 270 degrees + // to archive that we keep chromium unaware of transformation and we transform + // just the window content. + m_rect = rect; + // get parent window (scene) offset + QPointF offset = m_virtualParent->mapFromScene(QPoint(0, 0)); + offset = m_virtualParent->mapToGlobal(offset); + // get local transform + QTransform transform = m_virtualParent->itemTransform(nullptr, nullptr); + QPointF tl = transformPoint(rect.topLeft(), transform, offset, m_virtualParent); + QPointF br = transformPoint(rect.bottomRight(), transform, offset, m_virtualParent); + QRectF popupRect(tl, br); + popupRect = popupRect.normalized(); + // include offset from parent window + popupRect.moveTo(popupRect.topLeft() - offset); + setGeometry(popupRect.adjusted(0, 0, 1, 1).toRect()); + // add offset since screenRect and transformed popupRect one are different and + // we want to rotate in center. + m_realDelegate->setX(-rect.width() / 2.0 + geometry().width() / 2.0); + m_realDelegate->setY(-rect.height() / 2.0 + geometry().height() / 2.0); + m_realDelegate->setTransformOrigin(QQuickItem::Center); + m_realDelegate->setRotation(m_virtualParent->parentItem()->rotation()); + } else { + QRect geometry(rect); + geometry.moveTo(rect.topLeft() - getOffset(m_virtualParent)); + setGeometry(geometry); + } + m_realDelegate->show(); + raise(); + show(); +} + +void RenderWidgetHostViewQtDelegateQuickWindow::Resize(int width, int height) +{ + if (!m_rotated) + QQuickWindow::resize(width, height); +} + +void RenderWidgetHostViewQtDelegateQuickWindow::MoveWindow(const QPoint &screenPos) +{ + if (!m_rotated) + QQuickWindow::setPosition(screenPos - getOffset(m_virtualParent)); +} + +void RenderWidgetHostViewQtDelegateQuickWindow::SetClearColor(const QColor &color) +{ + QQuickWindow::setColor(color); +} + +bool RenderWidgetHostViewQtDelegateQuickWindow::ActiveFocusOnPress() +{ + return false; +} + +void RenderWidgetHostViewQtDelegateQuickWindow::Bind(QtWebEngineCore::WebContentsAdapterClient *client) +{ + QQuickWebEngineViewPrivate::bindViewAndDelegateItem( + static_cast<QQuickWebEngineViewPrivate *>(client), m_realDelegate.data()); +} + +void RenderWidgetHostViewQtDelegateQuickWindow::Unbind() +{ + QQuickWebEngineViewPrivate::bindViewAndDelegateItem(nullptr, m_realDelegate.data()); +} + +void RenderWidgetHostViewQtDelegateQuickWindow::Destroy() +{ + deleteLater(); +} + +} // namespace QtWebEngineCore diff --git a/src/webenginequick/render_widget_host_view_qt_delegate_quickwindow_p.h b/src/webenginequick/render_widget_host_view_qt_delegate_quickwindow_p.h new file mode 100644 index 000000000..3559bd2f0 --- /dev/null +++ b/src/webenginequick/render_widget_host_view_qt_delegate_quickwindow_p.h @@ -0,0 +1,57 @@ +// 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 RENDER_WIDGET_HOST_VIEW_QT_DELEGATE_QUICKWINDOW_H +#define RENDER_WIDGET_HOST_VIEW_QT_DELEGATE_QUICKWINDOW_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists for the convenience +// of other Qt classes. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include "render_widget_host_view_qt_delegate.h" +#include "render_widget_host_view_qt_delegate_item.h" + +#include <QtCore/qpointer.h> +#include <QtQuick/qquickwindow.h> + +// silence syncqt +QT_BEGIN_NAMESPACE +QT_END_NAMESPACE + +namespace QtWebEngineCore { + +class RenderWidgetHostViewQtDelegateQuickWindow : public QQuickWindow , public WidgetDelegate { + +public: + RenderWidgetHostViewQtDelegateQuickWindow(RenderWidgetHostViewQtDelegateItem *realDelegate, + QWindow *parent); + ~RenderWidgetHostViewQtDelegateQuickWindow(); + + void InitAsPopup(const QRect &screenRect) override; + void SetClearColor(const QColor &) override; + bool ActiveFocusOnPress() override; + void MoveWindow(const QPoint &) override; + void Bind(WebContentsAdapterClient *) override; + void Unbind() override; + void Destroy() override; + void Resize(int width, int height) override; + + void setVirtualParent(QQuickItem *virtualParent); + +private: + QPointer<RenderWidgetHostViewQtDelegateItem> m_realDelegate; + QQuickItem *m_virtualParent; + QRect m_rect; + bool m_rotated; +}; + +} // namespace QtWebEngineCore + +#endif // RENDER_WIDGET_HOST_VIEW_QT_DELEGATE_QUICKWINDOW_H diff --git a/src/webenginequick/ui/AlertDialog.qml b/src/webenginequick/ui/AlertDialog.qml new file mode 100644 index 000000000..e4c17b056 --- /dev/null +++ b/src/webenginequick/ui/AlertDialog.qml @@ -0,0 +1,64 @@ +// 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 + +import QtQuick +import QtQuick.Controls +import QtQuick.Layouts + +Dialog { + property alias text: message.text + property bool handled: false + signal accepted() + signal rejected() + title: qsTr("Alert Dialog") + modal: false + anchors.centerIn: parent + objectName: "alertDialog" + + //handle the case where users simply closes the dialog + onVisibleChanged: { + if (visible == false && handled == false) { + handled = true; + rejected(); + } else { + handled = false; + } + } + + function acceptDialog() { + accepted(); + handled = true; + close(); + } + + ColumnLayout { + id: rootLayout + anchors.fill: parent + anchors.margins: 4 + property int minimumWidth: rootLayout.implicitWidth + rootLayout.doubleMargins + property int minimumHeight: rootLayout.implicitHeight + rootLayout.doubleMargins + property int doubleMargins: anchors.margins * 2 + SystemPalette { id: palette; colorGroup: SystemPalette.Active } + RowLayout { + Layout.alignment: Qt.AlignRight + spacing: 8 + Image { + source: "qrc:/qt-project.org/imports/QtWebEngine/ControlsDelegates/information.png" + } + Label { + id: message + Layout.fillWidth: true + color: palette.windowText + textFormat: Text.PlainText + } + } + Item { + Layout.fillHeight: true + } + Button { + Layout.alignment: Qt.AlignHCenter + text: qsTr("OK") + onClicked: acceptDialog() + } + } +} diff --git a/src/webenginequick/ui/AuthenticationDialog.qml b/src/webenginequick/ui/AuthenticationDialog.qml new file mode 100644 index 000000000..d0611b84f --- /dev/null +++ b/src/webenginequick/ui/AuthenticationDialog.qml @@ -0,0 +1,101 @@ +// 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 + +import QtQuick +import QtQuick.Controls +import QtQuick.Layouts + +Dialog { + property alias text: message.text + property bool handled: false + signal accepted(string user, string password) + signal rejected() + title: qsTr("Authentication Required") + modal: false + anchors.centerIn: parent + objectName: "authenticationDialog" + + //handle the case where users simply closes the dialog + onVisibleChanged: { + if (visible == false && handled == false) { + handled = true; + rejected(); + } else { + handled = false; + } + } + + function acceptDialog() { + accepted(userField.text, passwordField.text); + handled = true; + close(); + } + + function rejectDialog() { + rejected(); + handled = true; + close(); + } + + ColumnLayout { + id: rootLayout + anchors.fill: parent + anchors.margins: 4 + property int minimumWidth: rootLayout.implicitWidth + rootLayout.doubleMargins + property int minimumHeight: rootLayout.implicitHeight + rootLayout.doubleMargins + + property int doubleMargins: anchors.margins * 2 + + SystemPalette { id: palette; colorGroup: SystemPalette.Active } + Label { + id: message + color: palette.windowText + textFormat: Text.PlainText + } + GridLayout { + columns: 2 + Label { + text: qsTr("Username:") + color: palette.windowText + } + TextField { + id: userField + focus: true + Layout.fillWidth: true + onAccepted: { + if (userField.text && passwordField.text) + acceptDialog(); + } + } + Label { + text: qsTr("Password:") + color: palette.windowText + } + TextField { + id: passwordField + Layout.fillWidth: true + echoMode: TextInput.Password + onAccepted: { + if (userField.text && passwordField.text) + acceptDialog(); + } + } + } + Item { + Layout.fillHeight: true + } + RowLayout { + Layout.alignment: Qt.AlignRight + spacing: 8 + Button { + id: cancelButton + text: qsTr("Cancel") + onClicked: rejectDialog() + } + Button { + text: qsTr("Log In") + onClicked: acceptDialog() + } + } + } +} diff --git a/src/webenginequick/ui/AutofillPopup.qml b/src/webenginequick/ui/AutofillPopup.qml new file mode 100644 index 000000000..0a14b6233 --- /dev/null +++ b/src/webenginequick/ui/AutofillPopup.qml @@ -0,0 +1,41 @@ +// 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 + +import QtQuick +import QtQuick.Controls + +Popup { + id: root + // Let Chromium close the popup. + closePolicy: Popup.NoAutoClose + + property variant controller: null + property int itemHeight: 0 + + signal selected(int index) + signal accepted() + + function setCurrentIndex(index) + { + listView.currentIndex = index; + } + + ListView { + id: listView + anchors.fill: parent + clip: true + + model: controller.model + currentIndex: -1 + + delegate: ItemDelegate { + width: listView.width + height: root.itemHeight + text: model.display + highlighted: ListView.isCurrentItem + + onHoveredChanged: if (hovered) selected(index); + onClicked: accepted(); + } + } +} diff --git a/src/webenginequick/ui/CMakeLists.txt b/src/webenginequick/ui/CMakeLists.txt new file mode 100644 index 000000000..ac960535e --- /dev/null +++ b/src/webenginequick/ui/CMakeLists.txt @@ -0,0 +1,50 @@ +# Copyright (C) 2022 The Qt Company Ltd. +# SPDX-License-Identifier: BSD-3-Clause + +if (Qt6Quick_VERSION VERSION_GREATER_EQUAL "6.4.0") +set(colorDialog "ColorDialog.qml") +else() +set(colorDialog "custom/ColorDialog.qml") +endif() + +set(qml_files + "AlertDialog.qml" + "AuthenticationDialog.qml" + "AutofillPopup.qml" + "ConfirmDialog.qml" + "DirectoryPicker.qml" + "FilePicker.qml" + "Menu.qml" + "MenuItem.qml" + "MenuSeparator.qml" + "PromptDialog.qml" + "ToolTip.qml" + "TouchHandle.qml" + "TouchSelectionMenu.qml" + ${colorDialog} +) + +set(resource_files + "information.png" + "question.png" +) + +qt_internal_add_qml_module(WebEngineQuickDelegatesQml + URI "QtWebEngine.ControlsDelegates" + VERSION "${PROJECT_VERSION}" + QML_FILES ${qml_files} + PAST_MAJOR_VERSIONS 1 + NO_SYNC_QT + PLUGIN_TARGET qtwebenginequickdelegatesplugin + DEPENDENCIES QtQuickControls2 + NO_GENERATE_CPP_EXPORTS +) + +qt_internal_add_resource(qtwebenginequickdelegatesplugin "qtwebenginequickdelegatesplugin" + PREFIX + "/qt-project.org/imports/QtWebEngine/ControlsDelegates" + FILES + ${resource_files} +) + + diff --git a/src/webenginequick/ui/ColorDialog.qml b/src/webenginequick/ui/ColorDialog.qml new file mode 100644 index 000000000..f4d5b817b --- /dev/null +++ b/src/webenginequick/ui/ColorDialog.qml @@ -0,0 +1,13 @@ +// 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 + +import QtQuick.Dialogs + +ColorDialog { + id: colorDialog + objectName: "colorDialog" + + signal selectedColor(var color) + + onAccepted : selectedColor(selectedColor) +} diff --git a/src/webenginequick/ui/ConfirmDialog.qml b/src/webenginequick/ui/ConfirmDialog.qml new file mode 100644 index 000000000..cfffe7c4d --- /dev/null +++ b/src/webenginequick/ui/ConfirmDialog.qml @@ -0,0 +1,77 @@ +// 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 + +import QtQuick +import QtQuick.Controls +import QtQuick.Layouts + +Dialog { + property alias text: message.text + property bool handled: false + signal accepted() + signal rejected() + title: qsTr("Confirm Dialog") + modal: false + anchors.centerIn: parent + objectName: "confirmDialog" + + //handle the case where users simply closes the dialog + onVisibleChanged: { + if (visible == false && handled == false) { + handled = true; + rejected(); + } else { + handled = false; + } + } + + function acceptDialog() { + accepted(); + handled = true; + close(); + } + + function rejectDialog() { + rejected(); + handled = true; + close(); + } + + ColumnLayout { + id: rootLayout + anchors.fill: parent + anchors.margins: 4 + property int minimumWidth: rootLayout.implicitWidth + rootLayout.doubleMargins + property int minimumHeight: rootLayout.implicitHeight + rootLayout.doubleMargins + property int doubleMargins: anchors.margins * 2 + SystemPalette { id: palette; colorGroup: SystemPalette.Active } + RowLayout { + Layout.alignment: Qt.AlignRight + spacing: 8 + Image { + source: "qrc:/qt-project.org/imports/QtWebEngine/ControlsDelegates/question.png" + } + Text { + id: message + Layout.fillWidth: true + color: palette.windowText + textFormat: Text.PlainText + } + } + Item { + Layout.fillHeight: true + } + RowLayout { + Layout.alignment: Qt.AlignRight + spacing: 8 + Button { + text: qsTr("OK") + onClicked: acceptDialog() + } + Button { + text: qsTr("Cancel") + onClicked: rejectDialog() + } + } + } +} diff --git a/src/webenginequick/ui/DirectoryPicker.qml b/src/webenginequick/ui/DirectoryPicker.qml new file mode 100644 index 000000000..a8a6d47c9 --- /dev/null +++ b/src/webenginequick/ui/DirectoryPicker.qml @@ -0,0 +1,15 @@ +// 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 + +import QtQuick.Dialogs + +FolderDialog { + id: folderDialog + objectName: "folderDialog" + + signal folderSelected(var folder) + + onAccepted: { + folderSelected([selectedFolder]) + } +} diff --git a/src/webenginequick/ui/FilePicker.qml b/src/webenginequick/ui/FilePicker.qml new file mode 100644 index 000000000..d82c3bf35 --- /dev/null +++ b/src/webenginequick/ui/FilePicker.qml @@ -0,0 +1,15 @@ +// 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 + +import QtQuick.Dialogs + +FileDialog { + id: fileDialog + objectName: "fileDialog" + + signal filesSelected(var fileList) + + onAccepted: { + filesSelected(selectedFiles) + } +} diff --git a/src/webenginequick/ui/Menu.qml b/src/webenginequick/ui/Menu.qml new file mode 100644 index 000000000..bfa037d1c --- /dev/null +++ b/src/webenginequick/ui/Menu.qml @@ -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 + +import QtQuick +import QtQuick.Controls as C + +C.Menu { + id: menu + signal done() + objectName: "menu" + + // Use private API for now + onAboutToHide: doneTimer.start() + + // WORKAROUND On Mac the Menu may be destroyed before the MenuItem + // is actually triggered (see qtbase commit 08cc9b9991ae9ab51) + Timer { + id: doneTimer + interval: 100 + onTriggered: menu.done() + } +} diff --git a/src/webenginequick/ui/MenuItem.qml b/src/webenginequick/ui/MenuItem.qml new file mode 100644 index 000000000..8fefcdc69 --- /dev/null +++ b/src/webenginequick/ui/MenuItem.qml @@ -0,0 +1,7 @@ +// 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 + +import QtQuick +import QtQuick.Controls as C + +C.MenuItem { } diff --git a/src/webenginequick/ui/MenuSeparator.qml b/src/webenginequick/ui/MenuSeparator.qml new file mode 100644 index 000000000..af37f57a9 --- /dev/null +++ b/src/webenginequick/ui/MenuSeparator.qml @@ -0,0 +1,6 @@ +// 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 + +import QtQuick + +Item { id: dummy } diff --git a/src/webenginequick/ui/PromptDialog.qml b/src/webenginequick/ui/PromptDialog.qml new file mode 100644 index 000000000..275deace8 --- /dev/null +++ b/src/webenginequick/ui/PromptDialog.qml @@ -0,0 +1,79 @@ +// 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 + +import QtQuick +import QtQuick.Controls +import QtQuick.Layouts + +Dialog { + property alias text: message.text + property alias prompt: field.text + property bool handled: false + signal input(string text) + signal accepted() + signal rejected() + title: qsTr("Prompt Dialog") + modal: false + anchors.centerIn: parent + objectName: "promptDialog" + + //handle the case where users simply closes the dialog + onVisibleChanged: { + if (visible == false && handled == false) { + handled = true; + rejected(); + } else { + handled = false; + } + } + + function acceptDialog() { + input(field.text); + accepted(); + handled = true; + close(); + } + + function rejectDialog() { + rejected(); + handled = true; + close(); + } + + ColumnLayout { + id: rootLayout + anchors.fill: parent + anchors.margins: 4 + property int minimumWidth: rootLayout.implicitWidth + rootLayout.doubleMargins + property int minimumHeight: rootLayout.implicitHeight + rootLayout.doubleMargins + property int doubleMargins: anchors.margins * 2 + SystemPalette { id: palette; colorGroup: SystemPalette.Active } + Text { + id: message + Layout.fillWidth: true + color: palette.windowText + textFormat: Text.PlainText + } + TextField { + id:field + focus: true + Layout.fillWidth: true + onAccepted: acceptDialog() + } + Item { + Layout.fillHeight: true + } + RowLayout { + Layout.alignment: Qt.AlignRight + spacing: 8 + Button { + text: qsTr("OK") + onClicked: acceptDialog() + } + Button { + text: qsTr("Cancel") + onClicked: rejectDialog() + } + } + } +} diff --git a/src/webenginequick/ui/ToolTip.qml b/src/webenginequick/ui/ToolTip.qml new file mode 100644 index 000000000..525258e2f --- /dev/null +++ b/src/webenginequick/ui/ToolTip.qml @@ -0,0 +1,10 @@ +// 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 + +import QtQuick.Controls as C + +C.ToolTip { + delay: 1000 + timeout: 1500 + objectName: "toolTip" +} diff --git a/src/webenginequick/ui/TouchHandle.qml b/src/webenginequick/ui/TouchHandle.qml new file mode 100644 index 000000000..a879ec71b --- /dev/null +++ b/src/webenginequick/ui/TouchHandle.qml @@ -0,0 +1,6 @@ +// 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 + +import QtQuick + +Image { } diff --git a/src/webenginequick/ui/TouchSelectionMenu.qml b/src/webenginequick/ui/TouchSelectionMenu.qml new file mode 100644 index 000000000..f42c256bb --- /dev/null +++ b/src/webenginequick/ui/TouchSelectionMenu.qml @@ -0,0 +1,139 @@ +// 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 + +import QtQuick +import QtQuick.Layouts + +Rectangle { + id: menu + + signal cutTriggered + signal copyTriggered + signal pasteTriggered + signal contextMenuTriggered + + property bool isCutEnabled: false + property bool isCopyEnabled: false + property bool isPasteEnabled: false + + property color borderColor: "darkGray" + property color bgColor: "white" + + radius: 4 + border.color: borderColor + color: borderColor + antialiasing: true + + RowLayout { + anchors.fill: parent + spacing: parent.border.width + anchors.margins: parent.border.width + + Rectangle { + Layout.fillHeight: true + Layout.fillWidth: true + radius: menu.radius + color: bgColor + visible: isCutEnabled + + Text { + id: cutText + anchors.centerIn: parent + text: "Cut" + } + + MouseArea { + anchors.fill: parent + onPressed: { + parent.color = borderColor; + cutText.color = "white"; + } + onReleased: { + parent.color = bgColor; + cutText.color = "black"; + cutTriggered(); + } + } + } + + Rectangle { + Layout.fillHeight: true + Layout.fillWidth: true + radius: menu.radius + color: bgColor + visible: isCopyEnabled + + Text { + id: copyText + anchors.centerIn: parent + text: "Copy" + } + + MouseArea { + anchors.fill: parent + onPressed: { + parent.color = borderColor; + copyText.color = "white"; + } + onReleased: { + parent.color = bgColor; + copyText.color = "black"; + copyTriggered(); + } + } + } + + Rectangle { + Layout.fillHeight: true + Layout.fillWidth: true + radius: menu.radius + color: bgColor + visible: isPasteEnabled + + Text { + id: pasteText + anchors.centerIn: parent + text: "Paste" + } + + MouseArea { + anchors.fill: parent + onPressed: { + parent.color = borderColor; + pasteText.color = "white"; + } + onReleased: { + parent.color = bgColor; + pasteText.color = "black"; + pasteTriggered(); + } + } + } + + Rectangle { + Layout.fillHeight: true + Layout.fillWidth: true + radius: menu.radius + color: bgColor + + Text { + id: contextMenuText + anchors.centerIn: parent + text: "..." + } + + MouseArea { + anchors.fill: parent + onPressed: { + parent.color = borderColor; + contextMenuText.color = "white"; + } + onReleased: { + parent.color = bgColor; + contextMenuText.color = "black"; + contextMenuTriggered(); + } + } + } + } +} diff --git a/src/webenginequick/ui/custom/ColorDialog.qml b/src/webenginequick/ui/custom/ColorDialog.qml new file mode 100644 index 000000000..895c90198 --- /dev/null +++ b/src/webenginequick/ui/custom/ColorDialog.qml @@ -0,0 +1,285 @@ +// 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 + +import QtQuick +import QtQuick.Controls +import QtQuick.Layouts + +Dialog { + id: colorDialog + title: qsTr("Color Picker Dialog") + modal: false + anchors.centerIn: parent + objectName: "colorDialog" + + property bool handled: false + property color color + + signal selectedColor(var color) + signal rejected() + + function accept() { + handled = true; + selectedColor(colorDialog.color) + close(); + } + + function reject() { + handled = true; + rejected(); + close(); + } + + // Handle the case where users simply closes or clicks out of the dialog. + onVisibleChanged: { + if (!visible && !handled) { + handled = true; + rejected(); + } else { + handled = false; + } + } + + function selectColorFromPalette(paletteColor) { + colorDialog.color = paletteColor; + } + + function zeroPadding(text, length = 2) { + var textLength = text.length; + + if (textLength >= length) { + return text; + } + + for (var i = 0; i < length - textLength; i++) { + text = "0" + text; + } + + return text; + } + + function calculateRGBA() { + + var rgbArray = [colorDialog.color.r, colorDialog.color.g, colorDialog.color.b] + if (colorDialog.color.a != 1) { + rgbArray.push(colorDialog.color.a); + } + + for (var i = 0; i < rgbArray.length; i++) { + rgbArray[i] = Number(Math.round(rgbArray[i] * 255)).toString(16); + rgbArray[i] = zeroPadding(rgbArray[i]); + } + + return "#" + rgbArray.join(""); + } + + + function isNaNOrUndefined(value) { + return value == null || value == undefined || Number.isNaN(value); + } + + function parseColorText(colorText) { + if (colorText[0] == '#') { + colorText = colorText.substring(1); + } + + if (!(colorText.length == 6 || colorText.length == 8)) { + return undefined; + } + + var rgbaValues = [parseInt("0x" + colorText.substring(0,2)), + parseInt("0x" + colorText.substring(2,4)), + parseInt("0x" + colorText.substring(4,6)), + parseInt("0x" + (colorText.length > 6 ? colorText.substring(6,8) : "FF"))] + + for (var i = 0; i < rgbaValues.length; i++) { + if (isNaNOrUndefined(rgbaValues[i])) { + return undefined; + } + rgbaValues[i] = rgbaValues[i] / 255; + } + + return Qt.rgba(rgbaValues[0], rgbaValues[1], rgbaValues[2], rgbaValues[3]); + } + + ListModel { + id: colorList + ListElement { rectangleColor: "red" } + ListElement { rectangleColor: "orangered" } + ListElement { rectangleColor: "orange" } + ListElement { rectangleColor: "gold" } + ListElement { rectangleColor: "yellow" } + ListElement { rectangleColor: "yellowgreen" } + ListElement { rectangleColor: "green" } + ListElement { rectangleColor: "lightskyblue" } + ListElement { rectangleColor: "blue" } + ListElement { rectangleColor: "blueviolet" } + ListElement { rectangleColor: "violet" } + ListElement { rectangleColor: "mediumvioletred" } + ListElement { rectangleColor: "black" } + ListElement { rectangleColor: "white" } + } + + contentItem: GridLayout { + id: grid + columns: 7 + rows: 5 + + Repeater { + model: colorList + delegate: Rectangle { + width: 50 + height: 50 + color: rectangleColor + border.color: "black" + border.width: 1 + + MouseArea { + anchors.fill: parent + onClicked: selectColorFromPalette(parent.color) + } + } + } + ColumnLayout { + id: colorTools + Layout.columnSpan: 4 + Layout.rowSpan: 2 + Layout.alignment: Qt.AlignHCenter | Qt.AlignVCenter + + Rectangle { + height: 100 + width: 200 + border.color: "black" + border.width: 1 + + Binding on color { + when: colorDialog.color + value: colorDialog.color + } + } + TextField { + id: colorTextField + width: 100 + selectByMouse: true + Layout.alignment: Qt.AlignHCenter + + Binding on text { + when: colorDialog.color + value: calculateRGBA() + delayed: true + } + + onTextEdited: { + var parsedColor = parseColorText(colorTextField.text); + if (parsedColor != undefined) { + colorDialog.color = parsedColor; + } + } + + MouseArea { + id: colorTextFieldMouseArea + anchors.fill: parent + acceptedButtons: Qt.RightButton + onClicked: colorTextFieldContextMenu.open() + } + + Menu { + id: colorTextFieldContextMenu + x: colorTextFieldMouseArea.mouseX + y: colorTextFieldMouseArea.mouseY + MenuItem { + text: qsTr("Copy color") + onTriggered: { + colorTextField.selectAll(); + colorTextField.copy(); + colorTextField.deselect(); + } + } + MenuSeparator {} + MenuItem { + text: qsTr("Paste") + onTriggered: { + colorTextField.selectAll(); + colorTextField.paste(); + } + enabled: colorTextField.canPaste + } + } + } + } + ListModel { + id: sliderBoxElements + ListElement { labelText: "Red value"; colorChannel: 0 } + ListElement { labelText: "Green value"; colorChannel: 1 } + ListElement { labelText: "Blue value"; colorChannel: 2 } + ListElement { labelText: "Alpha value"; colorChannel: 3 } + } + ColumnLayout { + id: sliderBox + Layout.columnSpan: 3 + Layout.rowSpan: 2 + Layout.fillWidth: true + Layout.fillHeight: true + + Repeater { + model: sliderBoxElements + delegate: ColumnLayout { + Label { + text: labelText + } + Slider { + id: colorSlider + property int channel: colorChannel + from: 0 + to: 255 + stepSize: 1 + value: { + if (colorSlider.channel == 0) + return colorDialog.color.r * 255; + else if (colorSlider.channel == 1) + return colorDialog.color.g * 255; + else if (colorSlider.channel == 2) + return colorDialog.color.b * 255; + else if (colorSlider.channel == 3) + return colorDialog.color.a * 255; + } + + Connections { + function onMoved() { + var redChannelValue = colorDialog.color.r; + var greenChannelValue = colorDialog.color.g; + var blueChannelValue = colorDialog.color.b; + var alphaChannelValue = colorDialog.color.a; + + if (colorSlider.channel == 0) + redChannelValue = colorSlider.value / 255; + else if (colorSlider.channel == 1) + greenChannelValue = colorSlider.value / 255; + else if (colorSlider.channel == 2) + blueChannelValue = colorSlider.value / 255; + else if (colorSlider.channel == 3) + alphaChannelValue = colorSlider.value / 255; + + colorDialog.color = Qt.rgba(redChannelValue, greenChannelValue, blueChannelValue, alphaChannelValue); + } + } + } + } + } + } + DialogButtonBox { + id: dialogButtonBox + Layout.columnSpan: 7 + Layout.alignment: Qt.AlignRight + + Button { + text: qsTr("Apply") + onClicked: accept() + } + Button { + text: qsTr("Cancel") + onClicked: reject() + } + } + } +} diff --git a/src/webenginequick/ui/information.png b/src/webenginequick/ui/information.png Binary files differnew file mode 100644 index 000000000..0a2eb87d1 --- /dev/null +++ b/src/webenginequick/ui/information.png diff --git a/src/webenginequick/ui/question.png b/src/webenginequick/ui/question.png Binary files differnew file mode 100644 index 000000000..2dd92fd79 --- /dev/null +++ b/src/webenginequick/ui/question.png diff --git a/src/webenginequick/ui_delegates_manager.cpp b/src/webenginequick/ui_delegates_manager.cpp new file mode 100644 index 000000000..a4a22fedd --- /dev/null +++ b/src/webenginequick/ui_delegates_manager.cpp @@ -0,0 +1,806 @@ +// 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 "ui_delegates_manager_p.h" + +#include "api/qquickwebengineaction_p.h" +#include "api/qquickwebengineview_p_p.h" + +#include <authentication_dialog_controller.h> +#include <autofill_popup_controller.h> +#include <color_chooser_controller.h> +#include <file_picker_controller.h> +#include <javascript_dialog_controller.h> +#include <touch_selection_menu_controller.h> +#include <web_contents_adapter_client.h> + +#include <QtCore/qdiriterator.h> +#include <QtCore/qfileinfo.h> +#include <QtCore/qlist.h> +#include <QtCore/qtimer.h> +#include <QtGui/qcursor.h> +#include <QtGui/qguiapplication.h> +#include <QtGui/qscreen.h> +#include <QtQml/qqmlcontext.h> +#include <QtQml/qqmlengine.h> +#include <QtQml/qqmlproperty.h> +#include <QtQuick/qquickwindow.h> + +#include <algorithm> + +// Uncomment for QML debugging +//#define UI_DELEGATES_DEBUG + +namespace QtWebEngineCore { + +#define NO_SEPARATOR +#define FILE_NAME_CASE_STATEMENT(TYPE, COMPONENT) \ + case UIDelegatesManager::TYPE:\ + return QStringLiteral(#TYPE".qml"); + +static QString fileNameForComponent(UIDelegatesManager::ComponentType type) +{ + switch (type) { + FOR_EACH_COMPONENT_TYPE(FILE_NAME_CASE_STATEMENT, NO_SEPARATOR) + default: + Q_UNREACHABLE(); + } + return QString(); +} + +static QPoint calculateToolTipPosition(QPoint &position, QSize &toolTip) { + QRect screen; + const QList<QScreen *> screens = QGuiApplication::screens(); + for (const QScreen *src : screens) + if (src->availableGeometry().contains(position)) + screen = src->availableGeometry(); + + position += QPoint(2, 16); + + if (position.x() + toolTip.width() > screen.x() + screen.width()) + position.rx() -= 4 + toolTip.width(); + if (position.y() + toolTip.height() > screen.y() + screen.height()) + position.ry() -= 24 + toolTip.height(); + if (position.y() < screen.y()) + position.setY(screen.y()); + if (position.x() + toolTip.width() > screen.x() + screen.width()) + position.setX(screen.x() + screen.width() - toolTip.width()); + if (position.x() < screen.x()) + position.setX(screen.x()); + if (position.y() + toolTip.height() > screen.y() + screen.height()) + position.setY(screen.y() + screen.height() - toolTip.height()); + + return position; +} + +const char *defaultPropertyName(QObject *obj) +{ + const QMetaObject *metaObject = obj->metaObject(); + + int idx = metaObject->indexOfClassInfo("DefaultProperty"); + if (-1 == idx) + return 0; + + QMetaClassInfo info = metaObject->classInfo(idx); + return info.value(); +} + +#define COMPONENT_MEMBER_INIT(TYPE, COMPONENT) \ + , COMPONENT##Component(0) + +// clang-format off +UIDelegatesManager::UIDelegatesManager(QQuickWebEngineView *view) + : m_view(view) + , m_toolTip(nullptr) + , m_touchSelectionMenu(nullptr) + , m_autofillPopup(nullptr) + FOR_EACH_COMPONENT_TYPE(COMPONENT_MEMBER_INIT, NO_SEPARATOR) +// clang-format on +{ +} + +UIDelegatesManager::~UIDelegatesManager() +{ +} + +#define COMPONENT_MEMBER_CASE_STATEMENT(TYPE, COMPONENT) \ + case TYPE: \ + component = &COMPONENT##Component; \ + break; + +bool UIDelegatesManager::ensureComponentLoaded(ComponentType type) +{ + QQmlEngine* engine = qmlEngine(m_view); + if (m_importDirs.isEmpty() && !initializeImportDirs(m_importDirs, engine)) + return false; + + QQmlComponent **component; + switch (type) { + FOR_EACH_COMPONENT_TYPE(COMPONENT_MEMBER_CASE_STATEMENT, NO_SEPARATOR) + default: + Q_UNREACHABLE(); + return false; + } + QString fileName(fileNameForComponent(type)); +#ifndef UI_DELEGATES_DEBUG + if (*component) + return true; +#else // Unconditionally reload the components each time. + fprintf(stderr, "%s: %s\n", Q_FUNC_INFO, qPrintable(fileName)); +#endif + if (!engine) + return false; + + for (const QString &importDir : std::as_const(m_importDirs)) { + const QString componentFilePath = importDir % QLatin1Char('/') % fileName; + + if (!QFileInfo(componentFilePath).exists()) + continue; + + // FIXME: handle async loading + *component = (new QQmlComponent(engine, + importDir.startsWith(QLatin1String(":/")) ? QUrl(QLatin1String("qrc") + componentFilePath) + : QUrl::fromLocalFile(componentFilePath), + QQmlComponent::PreferSynchronous, m_view)); + + if ((*component)->status() != QQmlComponent::Ready) { + const QList<QQmlError> errs = (*component)->errors(); + for (const QQmlError &err : errs) + qWarning("QtWebEngine: component error: %s\n", qPrintable(err.toString())); + delete *component; + *component = nullptr; + return false; + } + return true; + } + return false; +} + +#define CHECK_QML_SIGNAL_PROPERTY(prop, location) \ + if (!prop.isSignalProperty()) \ + qWarning("%s is missing %s signal property.\n", qPrintable(location.toString()), qPrintable(prop.name())); + +void UIDelegatesManager::addMenuSeparator(QObject *menu) +{ + if (!ensureComponentLoaded(MenuSeparator)) + return; + + QQmlContext *itemContext = qmlContext(m_view); + QObject *sep = menuSeparatorComponent->create(itemContext); + sep->setParent(menu); + + QQmlListReference entries(menu, defaultPropertyName(menu)); + if (entries.isValid() && entries.count() > 0) + entries.append(sep); +} + +#define ASSIGN_DIALOG_COMPONENT_DATA_CASE_STATEMENT(TYPE, COMPONENT) \ + case TYPE:\ + dialogComponent = COMPONENT##Component; \ + break; + + +void UIDelegatesManager::showDialog(QSharedPointer<JavaScriptDialogController> dialogController) +{ + Q_ASSERT(!dialogController.isNull()); + ComponentType dialogComponentType = Invalid; + QString title; + switch (dialogController->type()) { + case WebContentsAdapterClient::AlertDialog: + dialogComponentType = AlertDialog; + title = tr("Javascript Alert - %1").arg(m_view->url().toString()); + break; + case WebContentsAdapterClient::ConfirmDialog: + dialogComponentType = ConfirmDialog; + title = tr("Javascript Confirm - %1").arg(m_view->url().toString()); + break; + case WebContentsAdapterClient::PromptDialog: + dialogComponentType = PromptDialog; + title = tr("Javascript Prompt - %1").arg(m_view->url().toString()); + break; + case WebContentsAdapterClient::UnloadDialog: + dialogComponentType = ConfirmDialog; + title = tr("Are you sure you want to leave this page?"); + break; + case WebContentsAdapterClient::InternalAuthorizationDialog: + dialogComponentType = ConfirmDialog; + title = dialogController->title(); + break; + default: + Q_UNREACHABLE(); + } + + if (!ensureComponentLoaded(dialogComponentType)) { + // Let the controller know it couldn't be loaded + qWarning("Failed to load dialog, rejecting."); + dialogController->reject(); + return; + } + + QQmlComponent *dialogComponent = nullptr; + switch (dialogComponentType) { + FOR_EACH_COMPONENT_TYPE(ASSIGN_DIALOG_COMPONENT_DATA_CASE_STATEMENT, NO_SEPARATOR) + default: + Q_UNREACHABLE(); + } + + QQmlContext *context = qmlContext(m_view); + QObject *dialog = dialogComponent->beginCreate(context); + // set visual parent for non-Window-based dialogs + if (QQuickItem *item = qobject_cast<QQuickItem*>(dialog)) + item->setParentItem(m_view); + dialog->setParent(m_view); + QQmlProperty textProp(dialog, QStringLiteral("text")); + if (dialogController->type() == WebContentsAdapterClient::UnloadDialog) + textProp.write(tr("Changes that you made may not be saved.")); + else + textProp.write(dialogController->message()); + + QQmlProperty titleProp(dialog, QStringLiteral("title")); + titleProp.write(title); + + QQmlProperty acceptSignal(dialog, QStringLiteral("onAccepted")); + QQmlProperty rejectSignal(dialog, QStringLiteral("onRejected")); + CHECK_QML_SIGNAL_PROPERTY(acceptSignal, dialogComponent->url()); + CHECK_QML_SIGNAL_PROPERTY(rejectSignal, dialogComponent->url()); + + static int acceptIndex = dialogController->metaObject()->indexOfSlot("accept()"); + QObject::connect(dialog, acceptSignal.method(), dialogController.data(), dialogController->metaObject()->method(acceptIndex)); + static int rejectIndex = dialogController->metaObject()->indexOfSlot("reject()"); + QObject::connect(dialog, rejectSignal.method(), dialogController.data(), dialogController->metaObject()->method(rejectIndex)); + + if (dialogComponentType == PromptDialog) { + QQmlProperty promptProp(dialog, QStringLiteral("prompt")); + promptProp.write(dialogController->defaultPrompt()); + QQmlProperty inputSignal(dialog, QStringLiteral("onInput")); + CHECK_QML_SIGNAL_PROPERTY(inputSignal, dialogComponent->url()); + static int setTextIndex = dialogController->metaObject()->indexOfSlot("textProvided(QString)"); + QObject::connect(dialog, inputSignal.method(), dialogController.data(), dialogController->metaObject()->method(setTextIndex)); + } + + dialogComponent->completeCreate(); + + QObject::connect(dialogController.data(), &JavaScriptDialogController::dialogCloseRequested, dialog, &QObject::deleteLater); + + QMetaObject::invokeMethod(dialog, "open"); +} + +void UIDelegatesManager::showColorDialog(QSharedPointer<ColorChooserController> controller) +{ + if (!ensureComponentLoaded(ColorDialog)) { + // Let the controller know it couldn't be loaded + qWarning("Failed to load dialog, rejecting."); + controller->reject(); + return; + } + + QQmlContext *context = qmlContext(m_view); + QObject *colorDialog = colorDialogComponent->beginCreate(context); + if (QQuickItem *item = qobject_cast<QQuickItem*>(colorDialog)) + item->setParentItem(m_view); + colorDialog->setParent(m_view); + + if (controller->initialColor().isValid()) + colorDialog->setProperty("color", controller->initialColor()); + + QQmlProperty selectedColorSignal(colorDialog, QStringLiteral("onSelectedColor")); + CHECK_QML_SIGNAL_PROPERTY(selectedColorSignal, colorDialogComponent->url()); + QQmlProperty rejectedSignal(colorDialog, QStringLiteral("onRejected")); + CHECK_QML_SIGNAL_PROPERTY(rejectedSignal, colorDialogComponent->url()); + + static int acceptIndex = controller->metaObject()->indexOfSlot("accept(QVariant)"); + QObject::connect(colorDialog, selectedColorSignal.method(), controller.data(), controller->metaObject()->method(acceptIndex)); + static int rejectIndex = controller->metaObject()->indexOfSlot("reject()"); + QObject::connect(colorDialog, rejectedSignal.method(), controller.data(), controller->metaObject()->method(rejectIndex)); + + // delete later + static int deleteLaterIndex = colorDialog->metaObject()->indexOfSlot("deleteLater()"); + QObject::connect(colorDialog, selectedColorSignal.method(), colorDialog, colorDialog->metaObject()->method(deleteLaterIndex)); + QObject::connect(colorDialog, rejectedSignal.method(), colorDialog, colorDialog->metaObject()->method(deleteLaterIndex)); + + colorDialogComponent->completeCreate(); + QMetaObject::invokeMethod(colorDialog, "open"); +} + +void UIDelegatesManager::showDialog(QSharedPointer<AuthenticationDialogController> dialogController) +{ + Q_ASSERT(!dialogController.isNull()); + + if (!ensureComponentLoaded(AuthenticationDialog)) { + // Let the controller know it couldn't be loaded + qWarning("Failed to load authentication dialog, rejecting."); + dialogController->reject(); + return; + } + + QQmlContext *context = qmlContext(m_view); + QObject *authenticationDialog = authenticationDialogComponent->beginCreate(context); + // set visual parent for non-Window-based dialogs + if (QQuickItem *item = qobject_cast<QQuickItem*>(authenticationDialog)) + item->setParentItem(m_view); + authenticationDialog->setParent(m_view); + + QString introMessage; + if (dialogController->isProxy()) { + introMessage = tr("Connect to proxy \"%1\" using:"); + introMessage = introMessage.arg(dialogController->host().toHtmlEscaped()); + } else { + const QUrl url = dialogController->url(); + introMessage = tr("Enter username and password for \"%1\" at %2://%3"); + introMessage = introMessage.arg(dialogController->realm(), url.scheme(), url.host()); + } + QQmlProperty textProp(authenticationDialog, QStringLiteral("text")); + textProp.write(introMessage); + + QQmlProperty acceptSignal(authenticationDialog, QStringLiteral("onAccepted")); + QQmlProperty rejectSignal(authenticationDialog, QStringLiteral("onRejected")); + CHECK_QML_SIGNAL_PROPERTY(acceptSignal, authenticationDialogComponent->url()); + CHECK_QML_SIGNAL_PROPERTY(rejectSignal, authenticationDialogComponent->url()); + + static int acceptIndex = dialogController->metaObject()->indexOfSlot("accept(QString,QString)"); + static int deleteLaterIndex = authenticationDialog->metaObject()->indexOfSlot("deleteLater()"); + QObject::connect(authenticationDialog, acceptSignal.method(), dialogController.data(), dialogController->metaObject()->method(acceptIndex)); + QObject::connect(authenticationDialog, acceptSignal.method(), authenticationDialog, authenticationDialog->metaObject()->method(deleteLaterIndex)); + static int rejectIndex = dialogController->metaObject()->indexOfSlot("reject()"); + QObject::connect(authenticationDialog, rejectSignal.method(), dialogController.data(), dialogController->metaObject()->method(rejectIndex)); + QObject::connect(authenticationDialog, rejectSignal.method(), authenticationDialog, authenticationDialog->metaObject()->method(deleteLaterIndex)); + + authenticationDialogComponent->completeCreate(); + QMetaObject::invokeMethod(authenticationDialog, "open"); +} + +void UIDelegatesManager::showFilePicker(QSharedPointer<FilePickerController> controller) +{ + if (controller->mode() == FilePickerController::UploadFolder) { + showDirectoryPicker(controller); + return; + } + + if (!ensureComponentLoaded(FilePicker)) + return; + + QQmlContext *context = qmlContext(m_view); + QObject *filePicker = filePickerComponent->beginCreate(context); + if (QQuickItem *item = qobject_cast<QQuickItem*>(filePicker)) + item->setParentItem(m_view); + filePicker->setParent(m_view); + filePickerComponent->completeCreate(); + + static int fileModeIndex = filePicker->metaObject()->indexOfEnumerator("FileMode"); + QMetaEnum fileModeEnum = filePicker->metaObject()->enumerator(fileModeIndex); + + // Fine-tune some properties depending on the mode. + switch (controller->mode()) { + case FilePickerController::Open: + filePicker->setProperty("fileMode", fileModeEnum.keyToValue("OpenFile")); + break; + case FilePickerController::Save: + filePicker->setProperty("fileMode", fileModeEnum.keyToValue("SaveFile")); + break; + case FilePickerController::OpenMultiple: + filePicker->setProperty("fileMode", fileModeEnum.keyToValue("OpenFiles")); + break; + case FilePickerController::UploadFolder: + default: + Q_UNREACHABLE(); + } + + filePicker->setProperty("nameFilters", FilePickerController::nameFilters(controller->acceptedMimeTypes())); + + QQmlProperty filesPickedSignal(filePicker, QStringLiteral("onFilesSelected")); + CHECK_QML_SIGNAL_PROPERTY(filesPickedSignal, filePickerComponent->url()); + QQmlProperty rejectSignal(filePicker, QStringLiteral("onRejected")); + CHECK_QML_SIGNAL_PROPERTY(rejectSignal, filePickerComponent->url()); + static int acceptedIndex = controller->metaObject()->indexOfSlot("accepted(QVariant)"); + QObject::connect(filePicker, filesPickedSignal.method(), controller.data(), controller->metaObject()->method(acceptedIndex)); + static int rejectedIndex = controller->metaObject()->indexOfSlot("rejected()"); + QObject::connect(filePicker, rejectSignal.method(), controller.data(), controller->metaObject()->method(rejectedIndex)); + + // delete when done. + static int deleteLaterIndex = filePicker->metaObject()->indexOfSlot("deleteLater()"); + QObject::connect(filePicker, filesPickedSignal.method(), filePicker, filePicker->metaObject()->method(deleteLaterIndex)); + QObject::connect(filePicker, rejectSignal.method(), filePicker, filePicker->metaObject()->method(deleteLaterIndex)); + + QMetaObject::invokeMethod(filePicker, "open"); +} + +void UIDelegatesManager::showDirectoryPicker(QSharedPointer<FilePickerController> controller) +{ + if (!ensureComponentLoaded(DirectoryPicker)) + return; + + QQmlContext *context = qmlContext(m_view); + QObject *directoryPicker = directoryPickerComponent->beginCreate(context); + if (QQuickItem *item = qobject_cast<QQuickItem*>(directoryPicker)) + item->setParentItem(m_view); + directoryPicker->setParent(m_view); + directoryPickerComponent->completeCreate(); + + QQmlProperty directoryPickedSignal(directoryPicker, QStringLiteral("onFolderSelected")); + CHECK_QML_SIGNAL_PROPERTY(directoryPickedSignal, directoryPickerComponent->url()); + QQmlProperty rejectSignal(directoryPicker, QStringLiteral("onRejected")); + CHECK_QML_SIGNAL_PROPERTY(rejectSignal, directoryPickerComponent->url()); + static int acceptedIndex = controller->metaObject()->indexOfSlot("accepted(QVariant)"); + QObject::connect(directoryPicker, directoryPickedSignal.method(), controller.data(), controller->metaObject()->method(acceptedIndex)); + static int rejectedIndex = controller->metaObject()->indexOfSlot("rejected()"); + QObject::connect(directoryPicker, rejectSignal.method(), controller.data(), controller->metaObject()->method(rejectedIndex)); + + // delete when done. + static int deleteLaterIndex = directoryPicker->metaObject()->indexOfSlot("deleteLater()"); + QObject::connect(directoryPicker, directoryPickedSignal.method(), directoryPicker, directoryPicker->metaObject()->method(deleteLaterIndex)); + QObject::connect(directoryPicker, rejectSignal.method(), directoryPicker, directoryPicker->metaObject()->method(deleteLaterIndex)); + + QMetaObject::invokeMethod(directoryPicker, "open"); +} + +class TemporaryCursorMove +{ +public: + TemporaryCursorMove(const QQuickItem *item, const QPoint &pos) + { + if (pos.isNull() || !item->contains(pos)) + return; + const QPoint oldPos = QCursor::pos(); + const QPoint globalPos = item->mapToGlobal(QPointF(pos)).toPoint(); + if (oldPos == globalPos) + return; + m_oldCursorPos = oldPos; + QCursor::setPos(globalPos); + } + + ~TemporaryCursorMove() + { + if (!m_oldCursorPos.isNull()) + QCursor::setPos(m_oldCursorPos); + } + +private: + QPoint m_oldCursorPos; +}; + +void UIDelegatesManager::showToolTip(const QString &text) +{ + if (text.isEmpty()) { + m_toolTip.reset(); + return; + } + + if (!ensureComponentLoaded(ToolTip)) + return; + + if (!m_toolTip.isNull()) + return; + + QQmlContext *context = qmlContext(m_view); + m_toolTip.reset(toolTipComponent->beginCreate(context)); + if (QQuickItem *item = qobject_cast<QQuickItem *>(m_toolTip.data())) + item->setParentItem(m_view); + m_toolTip->setParent(m_view); + toolTipComponent->completeCreate(); + + QQmlProperty(m_toolTip.data(), QStringLiteral("text")).write(text); + + int height = QQmlProperty(m_toolTip.data(), QStringLiteral("height")).read().toInt(); + int width = QQmlProperty(m_toolTip.data(), QStringLiteral("width")).read().toInt(); + QSize toolTipSize(width, height); + QPoint position = m_view->cursor().pos(); + position = m_view->mapFromGlobal(calculateToolTipPosition(position, toolTipSize)).toPoint(); + + QQmlProperty(m_toolTip.data(), QStringLiteral("x")).write(position.x()); + QQmlProperty(m_toolTip.data(), QStringLiteral("y")).write(position.y()); + + QMetaObject::invokeMethod(m_toolTip.data(), "open"); +} + +QQuickItem *UIDelegatesManager::createTouchHandle() +{ + if (!ensureComponentLoaded(TouchHandle)) + return nullptr; + + QQmlContext *context = qmlContext(m_view); + QObject *touchHandle = touchHandleComponent->beginCreate(context); + QQuickItem *item = qobject_cast<QQuickItem *>(touchHandle); + Q_ASSERT(item); + item->setParentItem(m_view); + touchHandleComponent->completeCreate(); + + return item; +} + +void UIDelegatesManager::showTouchSelectionMenu(QtWebEngineCore::TouchSelectionMenuController *menuController, const QRect &bounds, const int spacing) +{ + if (!ensureComponentLoaded(TouchSelectionMenu)) + return; + + QQmlContext *context = qmlContext(m_view); + m_touchSelectionMenu.reset(touchSelectionMenuComponent->beginCreate(context)); + if (QQuickItem *item = qobject_cast<QQuickItem *>(m_touchSelectionMenu.data())) + item->setParentItem(m_view); + m_touchSelectionMenu->setParent(m_view); + + QQmlProperty(m_touchSelectionMenu.data(), QStringLiteral("width")).write(bounds.width()); + QQmlProperty(m_touchSelectionMenu.data(), QStringLiteral("height")).write(bounds.height()); + QQmlProperty(m_touchSelectionMenu.data(), QStringLiteral("x")).write(bounds.x()); + QQmlProperty(m_touchSelectionMenu.data(), QStringLiteral("y")).write(bounds.y()); + QQmlProperty(m_touchSelectionMenu.data(), QStringLiteral("border.width")).write(spacing); + + // Cut button + bool cutEnabled = menuController->isCommandEnabled(TouchSelectionMenuController::Cut); + QQmlProperty(m_touchSelectionMenu.data(), QStringLiteral("isCutEnabled")).write(cutEnabled); + if (cutEnabled) { + QQmlProperty cutSignal(m_touchSelectionMenu.data(), QStringLiteral("onCutTriggered")); + CHECK_QML_SIGNAL_PROPERTY(cutSignal, touchSelectionMenuComponent->url()); + int cutIndex = menuController->metaObject()->indexOfSlot("cut()"); + QObject::connect(m_touchSelectionMenu.data(), cutSignal.method(), menuController, menuController->metaObject()->method(cutIndex)); + } + + // Copy button + bool copyEnabled = menuController->isCommandEnabled(TouchSelectionMenuController::Copy); + QQmlProperty(m_touchSelectionMenu.data(), QStringLiteral("isCopyEnabled")).write(copyEnabled); + if (copyEnabled) { + QQmlProperty copySignal(m_touchSelectionMenu.data(), QStringLiteral("onCopyTriggered")); + CHECK_QML_SIGNAL_PROPERTY(copySignal, touchSelectionMenuComponent->url()); + int copyIndex = menuController->metaObject()->indexOfSlot("copy()"); + QObject::connect(m_touchSelectionMenu.data(), copySignal.method(), menuController, menuController->metaObject()->method(copyIndex)); + } + + // Paste button + bool pasteEnabled = menuController->isCommandEnabled(TouchSelectionMenuController::Paste); + QQmlProperty(m_touchSelectionMenu.data(), QStringLiteral("isPasteEnabled")).write(pasteEnabled); + if (pasteEnabled) { + QQmlProperty pasteSignal(m_touchSelectionMenu.data(), QStringLiteral("onPasteTriggered")); + CHECK_QML_SIGNAL_PROPERTY(pasteSignal, touchSelectionMenuComponent->url()); + int pasteIndex = menuController->metaObject()->indexOfSlot("paste()"); + QObject::connect(m_touchSelectionMenu.data(), pasteSignal.method(), menuController, menuController->metaObject()->method(pasteIndex)); + } + + // Context menu button + QQmlProperty contextMenuSignal(m_touchSelectionMenu.data(), QStringLiteral("onContextMenuTriggered")); + CHECK_QML_SIGNAL_PROPERTY(contextMenuSignal, touchSelectionMenuComponent->url()); + int contextMenuIndex = menuController->metaObject()->indexOfSlot("runContextMenu()"); + QObject::connect(m_touchSelectionMenu.data(), contextMenuSignal.method(), menuController, menuController->metaObject()->method(contextMenuIndex)); + + touchSelectionMenuComponent->completeCreate(); +} + +void UIDelegatesManager::hideTouchSelectionMenu() +{ + QTimer::singleShot(0, m_view, [this] { m_touchSelectionMenu.reset(); }); +} + +bool AutofillPopupEventFilter::eventFilter(QObject *object, QEvent *event) +{ + if (event->type() == QEvent::ShortcutOverride) { + QKeyEvent *keyEvent = static_cast<QKeyEvent *>(event); + if (keyEvent->key() == Qt::Key_Escape) { + m_manager->hideAutofillPopup(); + return true; + } + + // Ignore shortcuts while the popup is open. It may result unwanted + // edit commands sent to Chromium that blocks the key press. + event->ignore(); + return true; + } + + // AutofillPopupControllerImpl::HandleKeyPressEvent() + // chrome/browser/ui/autofill/autofill_popup_controller_impl.cc + + if (event->type() == QEvent::KeyPress) { + QKeyEvent *keyEvent = static_cast<QKeyEvent *>(event); + switch (keyEvent->key()) { + case Qt::Key_Up: + m_controller->selectPreviousSuggestion(); + return true; + case Qt::Key_Down: + m_controller->selectNextSuggestion(); + return true; + case Qt::Key_PageUp: + m_controller->selectFirstSuggestion(); + return true; + case Qt::Key_PageDown: + m_controller->selectLastSuggestion(); + return true; + case Qt::Key_Escape: + m_manager->hideAutofillPopup(); + return true; + case Qt::Key_Enter: + case Qt::Key_Return: + m_controller->acceptSuggestion(); + return true; + case Qt::Key_Delete: + // Remove suggestion is not supported for datalist. + // Forward delete to view to be able to remove selected text. + break; + case Qt::Key_Tab: + m_controller->acceptSuggestion(); + break; + default: + break; + } + } + + // Do not forward release events of the overridden key presses. + if (event->type() == QEvent::KeyRelease) { + QKeyEvent *keyEvent = static_cast<QKeyEvent *>(event); + switch (keyEvent->key()) { + case Qt::Key_Up: + case Qt::Key_Down: + case Qt::Key_PageUp: + case Qt::Key_PageDown: + case Qt::Key_Escape: + case Qt::Key_Enter: + case Qt::Key_Return: + return true; + default: + break; + } + } + + return QObject::eventFilter(object, event); +} + +void UIDelegatesManager::showAutofillPopup(QtWebEngineCore::AutofillPopupController *controller, + QPointF pos, int width, bool autoselectFirstSuggestion) +{ + static const int padding = 1; + static const int itemHeight = 20; + const int proposedHeight = itemHeight * (controller->model()->rowCount()) + padding * 2; + + bool popupWasNull = false; + if (m_autofillPopup.isNull()) { + popupWasNull = true; + if (!ensureComponentLoaded(AutofillPopup)) + return; + + QQmlContext *context = qmlContext(m_view); + m_autofillPopup.reset(autofillPopupComponent->beginCreate(context)); + if (QQuickItem *item = qobject_cast<QQuickItem *>(m_autofillPopup.data())) + item->setParentItem(m_view); + m_autofillPopup->setParent(m_view); + } + + m_autofillPopup->setProperty("controller", QVariant::fromValue(controller)); + m_autofillPopup->setProperty("x", pos.x()); + m_autofillPopup->setProperty("y", pos.y()); + m_autofillPopup->setProperty("width", width); + m_autofillPopup->setProperty("height", + std::min(proposedHeight, qRound(m_view->height() - pos.y()))); + m_autofillPopup->setProperty("padding", padding); + m_autofillPopup->setProperty("itemHeight", itemHeight); + + if (popupWasNull) { + QQmlProperty selectedSignal(m_autofillPopup.data(), QStringLiteral("onSelected")); + CHECK_QML_SIGNAL_PROPERTY(selectedSignal, autofillPopupComponent->url()); + static int selectSuggestionIndex = + controller->metaObject()->indexOfSlot("selectSuggestion(int)"); + QObject::connect(m_autofillPopup.data(), selectedSignal.method(), controller, + controller->metaObject()->method(selectSuggestionIndex)); + + QQmlProperty acceptedSignal(m_autofillPopup.data(), QStringLiteral("onAccepted")); + CHECK_QML_SIGNAL_PROPERTY(acceptedSignal, autofillPopupComponent->url()); + static int acceptSuggestionIndex = + controller->metaObject()->indexOfSlot("acceptSuggestion()"); + QObject::connect(m_autofillPopup.data(), acceptedSignal.method(), controller, + controller->metaObject()->method(acceptSuggestionIndex)); + + QObject::connect(controller, &QtWebEngineCore::AutofillPopupController::currentIndexChanged, + [this](const QModelIndex &index) { + QMetaObject::invokeMethod(m_autofillPopup.data(), "setCurrentIndex", + Qt::DirectConnection, + Q_ARG(QVariant, index.row())); + }); + + autofillPopupComponent->completeCreate(); + + m_view->window()->installEventFilter( + new AutofillPopupEventFilter(controller, this, m_autofillPopup.data())); + + QMetaObject::invokeMethod(m_autofillPopup.data(), "open"); + controller->notifyPopupShown(); + } + + if (autoselectFirstSuggestion) + controller->selectFirstSuggestion(); +} + +void UIDelegatesManager::hideAutofillPopup() +{ + if (!m_autofillPopup) + return; + + QTimer::singleShot(0, m_view, [this] { + if (m_autofillPopup) { + QtWebEngineCore::AutofillPopupController *controller = + m_autofillPopup->property("controller") + .value<QtWebEngineCore::AutofillPopupController *>(); + m_autofillPopup.reset(); + controller->notifyPopupHidden(); + } + }); +} + +bool UIDelegatesManager::initializeImportDirs(QStringList &dirs, QQmlEngine *engine) +{ + const QStringList paths = engine->importPathList(); + for (const QString &path : paths) { + QString controlsImportPath = path % QLatin1String("/QtWebEngine/ControlsDelegates/"); + + // resource paths have to be tested using the ":/" prefix + if (controlsImportPath.startsWith(QLatin1String("qrc:/"))) { + controlsImportPath.remove(0, 3); + } + + QFileInfo fi(controlsImportPath); + if (fi.exists()) { + dirs << fi.absolutePath(); + + // add subdirectories + QDirIterator it(controlsImportPath, QDir::AllDirs | QDir::NoDotAndDotDot, QDirIterator::Subdirectories); + while (it.hasNext()) + dirs << QFileInfo(it.next()).absoluteFilePath(); + } + } + return !dirs.isEmpty(); +} + +QObject *UIDelegatesManager::addMenu(QObject *parentMenu, const QString &title, const QPoint &pos) +{ + Q_ASSERT(parentMenu); + if (!ensureComponentLoaded(Menu)) + return nullptr; + QQmlContext *context = qmlContext(m_view); + QObject *menu = menuComponent->beginCreate(context); + + // set visual parent for non-Window-based menus + if (QQuickItem *item = qobject_cast<QQuickItem*>(menu)) + item->setParentItem(m_view); + + if (!title.isEmpty()) + menu->setProperty("title", title); + if (!pos.isNull()) { + menu->setProperty("x", pos.x()); + menu->setProperty("y", pos.y()); + } + + menu->setParent(parentMenu); + QQmlProperty doneSignal(menu, QStringLiteral("onDone")); + CHECK_QML_SIGNAL_PROPERTY(doneSignal, menuComponent->url()) + static int deleteLaterIndex = menu->metaObject()->indexOfSlot("deleteLater()"); + QObject::connect(menu, doneSignal.method(), menu, menu->metaObject()->method(deleteLaterIndex)); + menuComponent->completeCreate(); + return menu; +} + +void UIDelegatesManager::addMenuItem(QQuickWebEngineAction *action, QObject *menu, bool checkable, bool checked) +{ + Q_ASSERT(action); + if (!ensureComponentLoaded(MenuItem)) + return; + + QObject *it = menuItemComponent->beginCreate(qmlContext(m_view)); + + it->setProperty("text", action->text()); + it->setProperty("enabled", action->isEnabled()); + it->setProperty("checked", checked); + it->setProperty("checkable", checkable); + + QQmlProperty signal(it, QStringLiteral("onTriggered")); + CHECK_QML_SIGNAL_PROPERTY(signal, menuItemComponent->url()); + const QMetaObject *actionMeta = action->metaObject(); + QObject::connect(it, signal.method(), action, actionMeta->method(actionMeta->indexOfSlot("trigger()"))); + menuItemComponent->completeCreate(); + + it->setParent(menu); + + QQmlListReference entries(menu, defaultPropertyName(menu)); + if (entries.isValid()) + entries.append(it); +} + +void UIDelegatesManager::showMenu(QObject *menu) +{ + QMetaObject::invokeMethod(menu, "open"); +} + +} // namespace QtWebEngineCore diff --git a/src/webenginequick/ui_delegates_manager_p.h b/src/webenginequick/ui_delegates_manager_p.h new file mode 100644 index 000000000..3502757d7 --- /dev/null +++ b/src/webenginequick/ui_delegates_manager_p.h @@ -0,0 +1,141 @@ +// 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 UI_DELEGATES_MANAGER_H +#define UI_DELEGATES_MANAGER_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists for the convenience +// of other Qt classes. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include <QtCore/qcoreapplication.h> // Q_DECLARE_TR_FUNCTIONS +#include <QtCore/qobject.h> +#include <QtCore/qpoint.h> +#include <QtCore/qscopedpointer.h> +#include <QtCore/qsharedpointer.h> +#include <QtCore/qstring.h> +#include <QtCore/qstringlist.h> + +// clang-format off +#define FOR_EACH_COMPONENT_TYPE(F, SEPARATOR) \ + F(Menu, menu) SEPARATOR \ + F(MenuItem, menuItem) SEPARATOR \ + F(MenuSeparator, menuSeparator) SEPARATOR \ + F(AlertDialog, alertDialog) SEPARATOR \ + F(ColorDialog, colorDialog) SEPARATOR \ + F(ConfirmDialog, confirmDialog) SEPARATOR \ + F(PromptDialog, promptDialog) SEPARATOR \ + F(FilePicker, filePicker) SEPARATOR \ + F(DirectoryPicker, directoryPicker) SEPARATOR \ + F(AuthenticationDialog, authenticationDialog) SEPARATOR \ + F(ToolTip, toolTip) SEPARATOR \ + F(TouchHandle, touchHandle) SEPARATOR \ + F(TouchSelectionMenu, touchSelectionMenu) SEPARATOR \ + F(AutofillPopup, autofillPopup) SEPARATOR + +#define COMMA_SEPARATOR , +#define SEMICOLON_SEPARATOR ; +#define ENUM_DECLARATION(TYPE, COMPONENT) \ + TYPE +#define MEMBER_DECLARATION(TYPE, COMPONENT) \ + QQmlComponent *COMPONENT##Component +// clang-format on + +QT_BEGIN_NAMESPACE +class QEvent; +class QQmlComponent; +class QQmlContext; +class QQmlEngine; +class QQuickItem; +class QQuickWebEngineAction; +class QQuickWebEngineView; +QT_END_NAMESPACE + +namespace QtWebEngineCore { +class AuthenticationDialogController; +class AutofillPopupController; +class ColorChooserController; +class FilePickerController; +class JavaScriptDialogController; +class TouchSelectionMenuController; + +const char *defaultPropertyName(QObject *obj); + +class UIDelegatesManager +{ + Q_DECLARE_TR_FUNCTIONS(UIDelegatesManager) +public: + enum ComponentType { + Invalid = -1, + FOR_EACH_COMPONENT_TYPE(ENUM_DECLARATION, COMMA_SEPARATOR) + ComponentTypeCount + }; + + UIDelegatesManager(QQuickWebEngineView *); + virtual ~UIDelegatesManager(); + + virtual bool initializeImportDirs(QStringList &dirs, QQmlEngine *engine); + virtual void addMenuItem(QQuickWebEngineAction *action, QObject *menu, + bool checkable = false, bool checked = true); + void addMenuSeparator(QObject *menu); + virtual QObject *addMenu(QObject *parentMenu, const QString &title, + const QPoint &pos = QPoint()); + QQmlContext *creationContextForComponent(QQmlComponent *); + void showColorDialog(QSharedPointer<ColorChooserController>); + void showDialog(QSharedPointer<JavaScriptDialogController>); + void showDialog(QSharedPointer<AuthenticationDialogController>); + void showFilePicker(QSharedPointer<FilePickerController>); + void showDirectoryPicker(QSharedPointer<FilePickerController>); + virtual void showMenu(QObject *menu); + void showToolTip(const QString &text); + QQuickItem *createTouchHandle(); + void showTouchSelectionMenu(TouchSelectionMenuController *, const QRect &, const int spacing); + void hideTouchSelectionMenu(); + void showAutofillPopup(QtWebEngineCore::AutofillPopupController *controller, QPointF pos, + int width, bool autoselectFirstSuggestion); + void hideAutofillPopup(); + +private: + bool ensureComponentLoaded(ComponentType); + + QQuickWebEngineView *m_view; + QStringList m_importDirs; + QScopedPointer<QObject> m_toolTip; + QScopedPointer<QObject> m_touchSelectionMenu; + QScopedPointer<QObject> m_autofillPopup; + + FOR_EACH_COMPONENT_TYPE(MEMBER_DECLARATION, SEMICOLON_SEPARATOR) + + Q_DISABLE_COPY(UIDelegatesManager) + +}; + +class AutofillPopupEventFilter : public QObject +{ + Q_OBJECT + +public: + AutofillPopupEventFilter(QtWebEngineCore::AutofillPopupController *controller, + UIDelegatesManager *manager, QObject *parent) + : QObject(parent), m_controller(controller), m_manager(manager) + { + } + +protected: + bool eventFilter(QObject *object, QEvent *event) override; + +private: + QtWebEngineCore::AutofillPopupController *m_controller; + UIDelegatesManager *m_manager; +}; + +} // namespace QtWebEngineCore + +#endif // UI_DELEGATES_MANAGER_H |