diff options
Diffstat (limited to 'src/webengine/api/qquickwebengineview.cpp')
-rw-r--r-- | src/webengine/api/qquickwebengineview.cpp | 634 |
1 files changed, 487 insertions, 147 deletions
diff --git a/src/webengine/api/qquickwebengineview.cpp b/src/webengine/api/qquickwebengineview.cpp index 86fea67e8..39901e693 100644 --- a/src/webengine/api/qquickwebengineview.cpp +++ b/src/webengine/api/qquickwebengineview.cpp @@ -39,12 +39,15 @@ #include "qquickwebengineview_p.h" #include "qquickwebengineview_p_p.h" - +#include "qtwebenginecoreglobal_p.h" #include "authentication_dialog_controller.h" -#include "browser_context_adapter.h" +#include "profile_adapter.h" #include "certificate_error_controller.h" #include "file_picker_controller.h" #include "javascript_dialog_controller.h" + +#include "qquickwebengineaction_p.h" +#include "qquickwebengineaction_p_p.h" #include "qquickwebenginehistory_p.h" #include "qquickwebenginecertificateerror_p.h" #include "qquickwebenginecontextmenurequest_p.h" @@ -59,7 +62,7 @@ #include "qwebenginequotarequest.h" #include "qwebengineregisterprotocolhandlerrequest.h" -#ifdef ENABLE_QML_TESTSUPPORT_API +#if QT_CONFIG(webengine_testsupport) #include "qquickwebenginetestsupport_p.h" #endif @@ -82,13 +85,15 @@ #include <QQmlContext> #include <QQmlEngine> #include <QQmlProperty> +#if QT_CONFIG(webengine_webchannel) #include <QQmlWebChannel> +#endif #include <QQuickWebEngineProfile> #include <QScreen> #include <QUrl> #include <QTimer> -#include <private/qguiapplication_p.h> -#include <qpa/qplatformintegration.h> +#include <QtGui/private/qguiapplication_p.h> +#include <QtGui/qpa/qplatformintegration.h> QT_BEGIN_NAMESPACE using namespace QtWebEngineCore; @@ -102,12 +107,13 @@ static QAccessibleInterface *webAccessibleFactory(const QString &, QObject *obje } #endif // QT_NO_ACCESSIBILITY +static QLatin1String defaultMimeType("text/html;charset=UTF-8"); + QQuickWebEngineViewPrivate::QQuickWebEngineViewPrivate() - : adapter(QSharedPointer<WebContentsAdapter>::create()) + : m_profile(nullptr) + , adapter(QSharedPointer<WebContentsAdapter>::create()) , m_history(new QQuickWebEngineHistory(this)) - , m_profile(QQuickWebEngineProfile::defaultProfile()) - , m_settings(new QQuickWebEngineSettings(m_profile->settings())) -#ifdef ENABLE_QML_TESTSUPPORT_API +#if QT_CONFIG(webengine_testsupport) , m_testSupport(0) #endif , contextMenuExtraItems(0) @@ -122,9 +128,12 @@ QQuickWebEngineViewPrivate::QQuickWebEngineViewPrivate() , m_isBeingAdopted(false) , m_dpiScale(1.0) , m_backgroundColor(Qt::white) - , m_defaultZoomFactor(1.0) + , m_zoomFactor(1.0) , m_ui2Enabled(false) + , m_profileInitialized(false) { + memset(actions, 0, sizeof(actions)); + QString platform = qApp->platformName().toLower(); if (platform == QLatin1Literal("eglfs")) m_ui2Enabled = true; @@ -152,6 +161,37 @@ QQuickWebEngineViewPrivate::QQuickWebEngineViewPrivate() QQuickWebEngineViewPrivate::~QQuickWebEngineViewPrivate() { + Q_ASSERT(m_profileInitialized); + m_profile->d_ptr->removeWebContentsAdapterClient(this); + adapter->stopFinding(); + if (faviconProvider) + faviconProvider->detach(q_ptr); +} + +void QQuickWebEngineViewPrivate::initializeProfile() +{ + if (!m_profileInitialized) { + Q_ASSERT(!adapter->isInitialized()); + m_profileInitialized = true; + if (!m_profile) + m_profile = QQuickWebEngineProfile::defaultProfile(); + 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::destroy() +{ + // the profile for this web contens is about to be + // garbage collected, delete WebContent first and + // let the QQuickWebEngineView be collected later by gc. + delete q_ptr->d_ptr.take(); } UIDelegatesManager *QQuickWebEngineViewPrivate::ui() @@ -256,6 +296,11 @@ void QQuickWebEngineViewPrivate::allowCertificateError(const QSharedPointer<Cert m_certificateErrorControllers.append(errorController); } +void QQuickWebEngineViewPrivate::selectClientCert(const QSharedPointer<ClientCertSelectController> &) +{ + // Doing nothing will free the select-controller and perform default continue. +} + void QQuickWebEngineViewPrivate::runGeolocationPermissionRequest(const QUrl &url) { Q_Q(QQuickWebEngineView); @@ -303,7 +348,6 @@ void QQuickWebEngineViewPrivate::urlChanged(const QUrl &url) { Q_Q(QQuickWebEngineView); Q_UNUSED(url); - explicitUrl = QUrl(); Q_EMIT q->urlChanged(); } @@ -371,7 +415,7 @@ void QQuickWebEngineViewPrivate::loadStarted(const QUrl &provisionalUrl, bool is { Q_Q(QQuickWebEngineView); if (isErrorPage) { -#ifdef ENABLE_QML_TESTSUPPORT_API +#if QT_CONFIG(webengine_testsupport) if (m_testSupport) m_testSupport->errorPage()->loadStarted(provisionalUrl); #endif @@ -396,7 +440,7 @@ void QQuickWebEngineViewPrivate::loadCommitted() void QQuickWebEngineViewPrivate::loadVisuallyCommitted() { -#ifdef ENABLE_QML_TESTSUPPORT_API +#if QT_CONFIG(webengine_testsupport) if (m_testSupport) Q_EMIT m_testSupport->loadVisuallyCommitted(); #endif @@ -411,7 +455,7 @@ void QQuickWebEngineViewPrivate::loadFinished(bool success, const QUrl &url, boo Q_Q(QQuickWebEngineView); if (isErrorPage) { -#ifdef ENABLE_QML_TESTSUPPORT_API +#if QT_CONFIG(webengine_testsupport) if (m_testSupport) m_testSupport->errorPage()->loadFinished(success, url); #endif @@ -428,9 +472,8 @@ void QQuickWebEngineViewPrivate::loadFinished(bool success, const QUrl &url, boo return; } if (success) { - explicitUrl = QUrl(); - QTimer::singleShot(0, q, [q, url]() { - QQuickWebEngineLoadRequest loadRequest(url, QQuickWebEngineView::LoadSucceededStatus); + QTimer::singleShot(0, q, [q, url, errorDescription, errorCode]() { + QQuickWebEngineLoadRequest loadRequest(url, QQuickWebEngineView::LoadSucceededStatus, errorDescription, errorCode); emit q->loadingChanged(&loadRequest); }); return; @@ -504,7 +547,7 @@ void QQuickWebEngineViewPrivate::close() void QQuickWebEngineViewPrivate::windowCloseRejected() { -#ifdef ENABLE_QML_TESTSUPPORT_API +#if QT_CONFIG(webengine_testsupport) if (m_testSupport) Q_EMIT m_testSupport->windowCloseRejected(); #endif @@ -608,9 +651,9 @@ QObject *QQuickWebEngineViewPrivate::accessibilityParentObject() return q; } -QSharedPointer<BrowserContextAdapter> QQuickWebEngineViewPrivate::browserContextAdapter() +ProfileAdapter *QQuickWebEngineViewPrivate::profileAdapter() { - return m_profile->d_ptr->browserContext(); + return m_profile->d_ptr->profileAdapter(); } WebContentsAdapter *QQuickWebEngineViewPrivate::webContentsAdapter() @@ -618,6 +661,20 @@ WebContentsAdapter *QQuickWebEngineViewPrivate::webContentsAdapter() return adapter.data(); } +void QQuickWebEngineViewPrivate::printRequested() +{ + Q_Q(QQuickWebEngineView); + QTimer::singleShot(0, q, [q]() { + Q_EMIT q->printRequested(); + }); +} + +void QQuickWebEngineViewPrivate::widgetChanged(RenderWidgetHostViewQtDelegate *newWidgetBase) +{ + Q_Q(QQuickWebEngineView); + bindViewAndWidget(q, static_cast<RenderWidgetHostViewQtDelegateQuick *>(newWidgetBase)); +} + WebEngineSettings *QQuickWebEngineViewPrivate::webEngineSettings() const { return m_settings->d_ptr.data(); @@ -699,7 +756,7 @@ void QQuickWebEngineViewPrivate::adoptWebContents(WebContentsAdapter *webContent return; } - if (webContents->browserContextAdapter() && browserContextAdapter() != webContents->browserContextAdapter()) { + if (webContents->profileAdapter() && profileAdapter() != webContents->profileAdapter()) { qWarning("Can not adopt content from a different WebEngineProfile."); return; } @@ -721,25 +778,22 @@ QQuickWebEngineView::QQuickWebEngineView(QQuickItem *parent) { Q_D(QQuickWebEngineView); d->q_ptr = this; - d->adapter->setClient(d); - this->setActiveFocusOnTab(true); this->setFlags(QQuickItem::ItemIsFocusScope | QQuickItem::ItemAcceptsDrops); } QQuickWebEngineView::~QQuickWebEngineView() { - Q_D(QQuickWebEngineView); - d->adapter->stopFinding(); - if (d->faviconProvider) - d->faviconProvider->detach(this); } void QQuickWebEngineViewPrivate::ensureContentsAdapter() { + initializeProfile(); if (!adapter->isInitialized()) { - if (explicitUrl.isValid()) - adapter->load(explicitUrl); + if (!m_html.isEmpty()) + adapter->setContent(m_html.toUtf8(), defaultMimeType, m_url); + else if (m_url.isValid()) + adapter->load(m_url); else adapter->loadDefault(); } @@ -749,18 +803,30 @@ void QQuickWebEngineViewPrivate::initializationFinished() { Q_Q(QQuickWebEngineView); - if (m_backgroundColor != Qt::white) - adapter->backgroundColorChanged(); + Q_ASSERT(m_profileInitialized); + if (m_backgroundColor != Qt::white) { + adapter->setBackgroundColor(m_backgroundColor); + emit q->backgroundColorChanged(); + } + + if (!qFuzzyCompare(adapter->currentZoomFactor(), m_zoomFactor)) { + adapter->setZoomFactor(m_zoomFactor); + emit q->zoomFactorChanged(m_zoomFactor); + } + +#if QT_CONFIG(webengine_webchannel) if (m_webChannel) adapter->setWebChannel(m_webChannel, m_webChannelWorld); - if (!qFuzzyCompare(adapter->currentZoomFactor(), m_defaultZoomFactor)) - q->setZoomFactor(m_defaultZoomFactor); +#endif if (devToolsView && devToolsView->d_ptr->adapter) adapter->openDevToolsFrontend(devToolsView->d_ptr->adapter); - Q_FOREACH (QQuickWebEngineScript *script, m_userScripts) - script->d_func()->bind(browserContextAdapter()->userResourceController(), adapter.data()); + for (QQuickWebEngineScript *script : qAsConst(m_userScripts)) + script->d_func()->bind(profileAdapter()->userResourceController(), adapter.data()); + + if (q->window() && q->isVisible()) + adapter->wasShown(); if (!m_isBeingAdopted) return; @@ -786,23 +852,116 @@ void QQuickWebEngineViewPrivate::setFullScreenMode(bool fullscreen) } } +void QQuickWebEngineViewPrivate::bindViewAndWidget(QQuickWebEngineView *view, + RenderWidgetHostViewQtDelegateQuick *widget) +{ + auto oldWidget = view ? view->d_func()->widget : nullptr; + auto oldView = widget ? widget->m_view : nullptr; + + // Change pointers first. + + if (widget && oldView != view) { + if (oldView) + oldView->d_func()->widget = nullptr; + widget->m_view = view; + } + + if (view && oldWidget != widget) { + if (oldWidget) + oldWidget->m_view = nullptr; + view->d_func()->widget = widget; + } + + // Then notify. + + if (widget && oldView != view && oldView) + oldView->d_func()->widgetChanged(widget, nullptr); + + if (view && oldWidget != widget) + view->d_func()->widgetChanged(oldWidget, widget); +} + +void QQuickWebEngineViewPrivate::widgetChanged(RenderWidgetHostViewQtDelegateQuick *oldWidget, + RenderWidgetHostViewQtDelegateQuick *newWidget) +{ + Q_Q(QQuickWebEngineView); + + if (oldWidget) + oldWidget->setParentItem(nullptr); + + if (newWidget) { + newWidget->setParentItem(q); + newWidget->setSize(q->boundingRect().size()); + // Focus on creation if the view accepts it + if (q->activeFocusOnPress()) + newWidget->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; + 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); +} + QUrl QQuickWebEngineView::url() const { Q_D(const QQuickWebEngineView); - return d->explicitUrl.isValid() ? d->explicitUrl : d->adapter->activeUrl(); + if (d->adapter->isInitialized()) + return d->adapter->activeUrl(); + else + return d->m_url; } void QQuickWebEngineView::setUrl(const QUrl& url) { + Q_D(QQuickWebEngineView); if (url.isEmpty()) return; - Q_D(QQuickWebEngineView); - d->explicitUrl = url; - if (d->adapter->isInitialized()) + if (d->adapter->isInitialized()) { d->adapter->load(url); - if (!qmlEngine(this) || isComponentComplete()) - d->ensureContentsAdapter(); + return; + } + + d->m_url = url; + d->m_html.clear(); } QUrl QQuickWebEngineView::icon() const @@ -814,11 +973,12 @@ QUrl QQuickWebEngineView::icon() const void QQuickWebEngineView::loadHtml(const QString &html, const QUrl &baseUrl) { Q_D(QQuickWebEngineView); - d->explicitUrl = QUrl(); - if (!qmlEngine(this) || isComponentComplete()) - d->ensureContentsAdapter(); - if (d->adapter->isInitialized()) - d->adapter->setContent(html.toUtf8(), QStringLiteral("text/html;charset=UTF-8"), baseUrl); + d->m_url = baseUrl; + d->m_html = html; + if (d->adapter->isInitialized()) { + d->adapter->setContent(html.toUtf8(), defaultMimeType, baseUrl); + return; + } } void QQuickWebEngineView::goBack() @@ -854,31 +1014,48 @@ void QQuickWebEngineView::stop() void QQuickWebEngineView::setZoomFactor(qreal arg) { Q_D(QQuickWebEngineView); - d->m_defaultZoomFactor = arg; - - qreal oldFactor = d->adapter->currentZoomFactor(); - d->adapter->setZoomFactor(arg); - if (qFuzzyCompare(oldFactor, d->adapter->currentZoomFactor())) - return; - - emit zoomFactorChanged(arg); + if (d->adapter->isInitialized() && !qFuzzyCompare(d->m_zoomFactor, d->adapter->currentZoomFactor())) { + d->adapter->setZoomFactor(arg); + emit zoomFactorChanged(arg); + } else { + d->m_zoomFactor = arg; + } } -QQuickWebEngineProfile *QQuickWebEngineView::profile() const +QQuickWebEngineProfile *QQuickWebEngineView::profile() { - Q_D(const QQuickWebEngineView); + Q_D(QQuickWebEngineView); + d->initializeProfile(); return d->m_profile; } void QQuickWebEngineView::setProfile(QQuickWebEngineProfile *profile) { Q_D(QQuickWebEngineView); - d->setProfile(profile); + + 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() const +QQuickWebEngineSettings *QQuickWebEngineView::settings() { - Q_D(const QQuickWebEngineView); + Q_D(QQuickWebEngineView); + d->initializeProfile(); return d->m_settings.data(); } @@ -892,34 +1069,26 @@ QQmlListProperty<QQuickWebEngineScript> QQuickWebEngineView::userScripts() d->userScripts_clear); } -void QQuickWebEngineViewPrivate::setProfile(QQuickWebEngineProfile *profile) +void QQuickWebEngineViewPrivate::updateAdapter() { - Q_Q(QQuickWebEngineView); - - if (profile == m_profile) - return; - m_profile = profile; - Q_EMIT q->profileChanged(); - m_settings->setParentSettings(profile->settings()); - - if (adapter->browserContext() != browserContextAdapter()->browserContext()) { - // When the profile changes we need to create a new WebContentAdapter and reload the active URL. - bool wasInitialized = adapter->isInitialized(); - QUrl activeUrl = adapter->activeUrl(); - adapter = QSharedPointer<WebContentsAdapter>::create(); - adapter->setClient(this); - if (wasInitialized) { - if (explicitUrl.isValid()) - adapter->load(explicitUrl); - else if (activeUrl.isValid()) - adapter->load(activeUrl); - else - adapter->loadDefault(); - } + // When the profile changes we need to create a new WebContentAdapter and reload the active URL. + bool wasInitialized = adapter->isInitialized(); + QUrl activeUrl = adapter->activeUrl(); + 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 if (activeUrl.isValid()) + adapter->load(activeUrl); + else + adapter->loadDefault(); } } -#ifdef ENABLE_QML_TESTSUPPORT_API +#if QT_CONFIG(webengine_testsupport) QQuickWebEngineTestSupport *QQuickWebEngineView::testSupport() const { Q_D(const QQuickWebEngineView); @@ -1080,7 +1249,7 @@ qreal QQuickWebEngineView::zoomFactor() const { Q_D(const QQuickWebEngineView); if (!d->adapter->isInitialized()) - return d->m_defaultZoomFactor; + return d->m_zoomFactor; return d->adapter->currentZoomFactor(); } @@ -1096,8 +1265,10 @@ void QQuickWebEngineView::setBackgroundColor(const QColor &color) if (color == d->m_backgroundColor) return; d->m_backgroundColor = color; - d->adapter->backgroundColorChanged(); - emit backgroundColorChanged(); + if (d->adapter->isInitialized()) { + d->adapter->setBackgroundColor(color); + emit backgroundColorChanged(); + } } /*! @@ -1130,7 +1301,7 @@ bool QQuickWebEngineView::recentlyAudible() const void QQuickWebEngineView::printToPdf(const QString& filePath, PrintedPageSizeId pageSizeId, PrintedPageOrientation orientation) { -#if defined(ENABLE_PDF) +#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); @@ -1146,7 +1317,7 @@ void QQuickWebEngineView::printToPdf(const QString& filePath, PrintedPageSizeId void QQuickWebEngineView::printToPdf(const QJSValue &callback, PrintedPageSizeId pageSizeId, PrintedPageOrientation orientation) { -#if defined(ENABLE_PDF) +#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); @@ -1209,23 +1380,31 @@ QQuickWebEngineHistory *QQuickWebEngineView::navigationHistory() const QQmlWebChannel *QQuickWebEngineView::webChannel() { +#if QT_CONFIG(webengine_webchannel) Q_D(QQuickWebEngineView); if (!d->m_webChannel) { d->m_webChannel = new QQmlWebChannel(this); - d->adapter->setWebChannel(d->m_webChannel, d->m_webChannelWorld); } - 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; - d->adapter->setWebChannel(webChannel, d->m_webChannelWorld); + 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 @@ -1236,12 +1415,18 @@ uint QQuickWebEngineView::webChannelWorld() const void QQuickWebEngineView::setWebChannelWorld(uint webChannelWorld) { +#if QT_CONFIG(webengine_webchannel) Q_D(QQuickWebEngineView); if (d->m_webChannelWorld == webChannelWorld) return; d->m_webChannelWorld = webChannelWorld; - d->adapter->setWebChannel(d->m_webChannel, d->m_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 @@ -1271,6 +1456,7 @@ QQuickWebEngineView *QQuickWebEngineView::devToolsView() const return d->devToolsView; } + void QQuickWebEngineView::setDevToolsView(QQuickWebEngineView *devToolsView) { Q_D(QQuickWebEngineView); @@ -1283,7 +1469,7 @@ void QQuickWebEngineView::setDevToolsView(QQuickWebEngineView *devToolsView) d->devToolsView = devToolsView; if (devToolsView) devToolsView->setInspectedView(this); - if (d->adapter->isInitialized()) { + if (d->profileInitialized() && d->adapter->isInitialized()) { if (devToolsView) d->adapter->openDevToolsFrontend(devToolsView->d_ptr->adapter); else @@ -1360,16 +1546,16 @@ void QQuickWebEngineView::fullScreenCancelled() void QQuickWebEngineView::geometryChanged(const QRectF &newGeometry, const QRectF &oldGeometry) { QQuickItem::geometryChanged(newGeometry, oldGeometry); - Q_FOREACH(QQuickItem *child, childItems()) { - if (qobject_cast<RenderWidgetHostViewQtDelegateQuick *>(child)) - child->setSize(newGeometry.size()); - } + Q_D(QQuickWebEngineView); + if (d->widget) + d->widget->setSize(newGeometry.size()); } void QQuickWebEngineView::itemChange(ItemChange change, const ItemChangeData &value) { Q_D(QQuickWebEngineView); - if (d->adapter->isInitialized() && (change == ItemSceneChange || change == ItemVisibleHasChanged)) { + if (d && d->profileInitialized() && d->adapter->isInitialized() + && (change == ItemSceneChange || change == ItemVisibleHasChanged)) { if (window() && isVisible()) d->adapter->wasShown(); else @@ -1630,6 +1816,170 @@ void QQuickWebEngineView::triggerWebAction(WebAction action) } } +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]; + } + + QString text; + QString iconName; + + switch (action) { + case Back: + text = RenderViewContextMenuQt::getMenuItemName(RenderViewContextMenuQt::ContextMenuItem::Back); + iconName = QStringLiteral("go-previous"); + break; + case Forward: + text = RenderViewContextMenuQt::getMenuItemName(RenderViewContextMenuQt::ContextMenuItem::Forward); + iconName = QStringLiteral("go-next"); + break; + case Stop: + text = tr("Stop"); + break; + case Reload: + text = RenderViewContextMenuQt::getMenuItemName(RenderViewContextMenuQt::ContextMenuItem::Reload); + iconName = QStringLiteral("view-refresh"); + break; + case ReloadAndBypassCache: + text = tr("Reload and Bypass Cache"); + break; + case Cut: + text = RenderViewContextMenuQt::getMenuItemName(RenderViewContextMenuQt::ContextMenuItem::Cut); + iconName = QStringLiteral("Cut"); + break; + case Copy: + text = RenderViewContextMenuQt::getMenuItemName(RenderViewContextMenuQt::ContextMenuItem::Copy); + break; + case Paste: + text = RenderViewContextMenuQt::getMenuItemName(RenderViewContextMenuQt::ContextMenuItem::Paste); + break; + case Undo: + text = RenderViewContextMenuQt::getMenuItemName(RenderViewContextMenuQt::ContextMenuItem::Undo); + break; + case Redo: + text = RenderViewContextMenuQt::getMenuItemName(RenderViewContextMenuQt::ContextMenuItem::Redo); + break; + case SelectAll: + text = RenderViewContextMenuQt::getMenuItemName(RenderViewContextMenuQt::ContextMenuItem::SelectAll); + break; + case PasteAndMatchStyle: + text = RenderViewContextMenuQt::getMenuItemName(RenderViewContextMenuQt::ContextMenuItem::PasteAndMatchStyle); + break; + case OpenLinkInThisWindow: + text = tr("Open link in this window"); + break; + case OpenLinkInNewWindow: + text = RenderViewContextMenuQt::getMenuItemName(RenderViewContextMenuQt::ContextMenuItem::OpenLinkInNewWindow); + break; + case OpenLinkInNewTab: + text = RenderViewContextMenuQt::getMenuItemName(RenderViewContextMenuQt::ContextMenuItem::OpenLinkInNewTab); + break; + case CopyLinkToClipboard: + text = RenderViewContextMenuQt::getMenuItemName(RenderViewContextMenuQt::ContextMenuItem::CopyLinkToClipboard); + break; + case DownloadLinkToDisk: + text = RenderViewContextMenuQt::getMenuItemName(RenderViewContextMenuQt::ContextMenuItem::DownloadLinkToDisk); + break; + case CopyImageToClipboard: + text = RenderViewContextMenuQt::getMenuItemName(RenderViewContextMenuQt::ContextMenuItem::CopyImageToClipboard); + break; + case CopyImageUrlToClipboard: + text = RenderViewContextMenuQt::getMenuItemName(RenderViewContextMenuQt::ContextMenuItem::CopyImageUrlToClipboard); + break; + case DownloadImageToDisk: + text = RenderViewContextMenuQt::getMenuItemName(RenderViewContextMenuQt::ContextMenuItem::DownloadImageToDisk); + break; + case CopyMediaUrlToClipboard: + text = RenderViewContextMenuQt::getMenuItemName(RenderViewContextMenuQt::ContextMenuItem::CopyMediaUrlToClipboard); + break; + case ToggleMediaControls: + text = RenderViewContextMenuQt::getMenuItemName(RenderViewContextMenuQt::ContextMenuItem::ToggleMediaControls); + break; + case ToggleMediaLoop: + text = RenderViewContextMenuQt::getMenuItemName(RenderViewContextMenuQt::ContextMenuItem::ToggleMediaLoop); + break; + case ToggleMediaPlayPause: + text = tr("Toggle Play/Pause"); + break; + case ToggleMediaMute: + text = tr("Toggle Mute"); + break; + case DownloadMediaToDisk: + text = RenderViewContextMenuQt::getMenuItemName(RenderViewContextMenuQt::ContextMenuItem::DownloadMediaToDisk); + break; + case InspectElement: + text = RenderViewContextMenuQt::getMenuItemName(RenderViewContextMenuQt::ContextMenuItem::InspectElement); + break; + case ExitFullScreen: + text = RenderViewContextMenuQt::getMenuItemName(RenderViewContextMenuQt::ContextMenuItem::ExitFullScreen); + break; + case RequestClose: + text = tr("Close Page"); + break; + case Unselect: + text = tr("Unselect"); + break; + case SavePage: + text = RenderViewContextMenuQt::getMenuItemName(RenderViewContextMenuQt::ContextMenuItem::SavePage); + break; + case ViewSource: + text = RenderViewContextMenuQt::getMenuItemName(RenderViewContextMenuQt::ContextMenuItem::ViewSource); + iconName = QStringLiteral("view-source"); + break; + case ToggleBold: + text = tr("&Bold"); + break; + case ToggleItalic: + text = tr("&Italic"); + break; + case ToggleUnderline: + text = tr("&Underline"); + break; + case ToggleStrikethrough: + text = tr("&Strikethrough"); + break; + case AlignLeft: + text = tr("Align &Left"); + break; + case AlignCenter: + text = tr("Align &Center"); + break; + case AlignRight: + text = tr("Align &Right"); + break; + case AlignJustified: + text = tr("Align &Justified"); + break; + case Indent: + text = tr("&Indent"); + break; + case Outdent: + text = tr("&Outdent"); + break; + case InsertOrderedList: + text = tr("Insert &Ordered List"); + break; + case InsertUnorderedList: + text = tr("Insert &Unordered List"); + 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); @@ -1650,7 +2000,7 @@ void QQuickWebEngineViewPrivate::userScripts_append(QQmlListProperty<QQuickWebEn // If the adapter hasn't been initialized, we'll bind the scripts in initializationFinished() if (!d->adapter->isInitialized()) return; - UserResourceControllerHost *resourceController = d->browserContextAdapter()->userResourceController(); + UserResourceControllerHost *resourceController = d->profileAdapter()->userResourceController(); script->d_func()->bind(resourceController, d->adapter.data()); } @@ -1675,14 +2025,15 @@ void QQuickWebEngineViewPrivate::userScripts_clear(QQmlListProperty<QQuickWebEng d->m_userScripts.clear(); if (!d->adapter->isInitialized()) return; - UserResourceControllerHost *resourceController = d->browserContextAdapter()->userResourceController(); + UserResourceControllerHost *resourceController = d->profileAdapter()->userResourceController(); resourceController->clearAllScripts(d->adapter.data()); } void QQuickWebEngineView::componentComplete() { QQuickItem::componentComplete(); - + Q_D(QQuickWebEngineView); + d->initializeProfile(); #ifndef QT_NO_ACCESSIBILITY // Enable accessibility via a dynamic QQmlProperty, instead of using private API call // QQuickAccessibleAttached::qmlAttachedProperties(this). The qmlContext is required, otherwise @@ -1758,112 +2109,101 @@ bool QQuickContextMenuBuilder::isFullScreenMode() void QQuickContextMenuBuilder::addMenuItem(ContextMenuItem menuItem) { - MenuItemHandler *item = new MenuItemHandler(m_menu); - QString menuItemIcon; - QPointer<QQuickWebEngineView> thisRef(m_view); + QQuickWebEngineAction *action = nullptr; switch (menuItem) { case ContextMenuItem::Back: - QObject::connect(item, &MenuItemHandler::triggered, thisRef, &QQuickWebEngineView::goBack); - menuItemIcon = QStringLiteral("go-previous"); + action = m_view->action(QQuickWebEngineView::Back); break; case ContextMenuItem::Forward: - QObject::connect(item, &MenuItemHandler::triggered, thisRef, &QQuickWebEngineView::goForward); - menuItemIcon = QStringLiteral("go-next"); + action = m_view->action(QQuickWebEngineView::Forward); break; case ContextMenuItem::Reload: - QObject::connect(item, &MenuItemHandler::triggered, thisRef, &QQuickWebEngineView::reload); - menuItemIcon = QStringLiteral("view-refresh"); + action = m_view->action(QQuickWebEngineView::Reload); break; case ContextMenuItem::Cut: - QObject::connect(item, &MenuItemHandler::triggered, [thisRef] { thisRef->triggerWebAction(QQuickWebEngineView::Cut); }); - menuItemIcon = QStringLiteral("Cut"); + action = m_view->action(QQuickWebEngineView::Cut); break; case ContextMenuItem::Copy: - QObject::connect(item, &MenuItemHandler::triggered, [thisRef] { thisRef->triggerWebAction(QQuickWebEngineView::Copy); }); - menuItemIcon = QStringLiteral("Copy"); + action = m_view->action(QQuickWebEngineView::Copy); break; - case ContextMenuItem::Paste: - QObject::connect(item, &MenuItemHandler::triggered, [thisRef] { thisRef->triggerWebAction(QQuickWebEngineView::Paste); }); - menuItemIcon = QStringLiteral("Paste"); + action = m_view->action(QQuickWebEngineView::Paste); break; case ContextMenuItem::Undo: - QObject::connect(item, &MenuItemHandler::triggered, [thisRef] { thisRef->triggerWebAction(QQuickWebEngineView::Undo); }); - menuItemIcon = QStringLiteral("Undo"); + action = m_view->action(QQuickWebEngineView::Undo); break; case ContextMenuItem::Redo: - QObject::connect(item, &MenuItemHandler::triggered, [thisRef] { thisRef->triggerWebAction(QQuickWebEngineView::Redo); }); - menuItemIcon = QStringLiteral("Redo"); + action = m_view->action(QQuickWebEngineView::Redo); break; case ContextMenuItem::SelectAll: - QObject::connect(item, &MenuItemHandler::triggered, [thisRef] { thisRef->triggerWebAction(QQuickWebEngineView::SelectAll); }); - menuItemIcon = QStringLiteral("Select All"); + action = m_view->action(QQuickWebEngineView::SelectAll); break; case ContextMenuItem::PasteAndMatchStyle: - QObject::connect(item, &MenuItemHandler::triggered, [thisRef] { thisRef->triggerWebAction(QQuickWebEngineView::PasteAndMatchStyle); }); - menuItemIcon = QStringLiteral("Paste And Match Style"); + action = m_view->action(QQuickWebEngineView::PasteAndMatchStyle); break; case ContextMenuItem::OpenLinkInNewWindow: - QObject::connect(item, &MenuItemHandler::triggered, [thisRef] { thisRef->triggerWebAction(QQuickWebEngineView::OpenLinkInNewWindow); }); + action = m_view->action(QQuickWebEngineView::OpenLinkInNewWindow); break; case ContextMenuItem::OpenLinkInNewTab: - QObject::connect(item, &MenuItemHandler::triggered, [thisRef] { thisRef->triggerWebAction(QQuickWebEngineView::OpenLinkInNewTab); }); + action = m_view->action(QQuickWebEngineView::OpenLinkInNewTab); break; case ContextMenuItem::CopyLinkToClipboard: - QObject::connect(item, &MenuItemHandler::triggered, [thisRef] { thisRef->triggerWebAction(QQuickWebEngineView::CopyLinkToClipboard); }); + action = m_view->action(QQuickWebEngineView::CopyLinkToClipboard); break; case ContextMenuItem::DownloadLinkToDisk: - QObject::connect(item, &MenuItemHandler::triggered, [thisRef] { thisRef->triggerWebAction(QQuickWebEngineView::DownloadLinkToDisk); }); + action = m_view->action(QQuickWebEngineView::DownloadLinkToDisk); break; case ContextMenuItem::CopyImageToClipboard: - QObject::connect(item, &MenuItemHandler::triggered, [thisRef] { thisRef->triggerWebAction(QQuickWebEngineView::CopyImageToClipboard); }); + action = m_view->action(QQuickWebEngineView::CopyImageToClipboard); break; case ContextMenuItem::CopyImageUrlToClipboard: - QObject::connect(item, &MenuItemHandler::triggered, [thisRef] { thisRef->triggerWebAction(QQuickWebEngineView::CopyImageUrlToClipboard); }); + action = m_view->action(QQuickWebEngineView::CopyImageUrlToClipboard); break; case ContextMenuItem::DownloadImageToDisk: - QObject::connect(item, &MenuItemHandler::triggered, [thisRef] { thisRef->triggerWebAction(QQuickWebEngineView::DownloadImageToDisk); }); + action = m_view->action(QQuickWebEngineView::DownloadImageToDisk); break; case ContextMenuItem::CopyMediaUrlToClipboard: - QObject::connect(item, &MenuItemHandler::triggered, [thisRef] { thisRef->triggerWebAction(QQuickWebEngineView::CopyMediaUrlToClipboard); }); + action = m_view->action(QQuickWebEngineView::CopyMediaUrlToClipboard); break; case ContextMenuItem::ToggleMediaControls: - QObject::connect(item, &MenuItemHandler::triggered, [thisRef] { thisRef->triggerWebAction(QQuickWebEngineView::ToggleMediaControls); }); + action = m_view->action(QQuickWebEngineView::ToggleMediaControls); break; case ContextMenuItem::ToggleMediaLoop: - QObject::connect(item, &MenuItemHandler::triggered, [thisRef] { thisRef->triggerWebAction(QQuickWebEngineView::ToggleMediaLoop); }); + action = m_view->action(QQuickWebEngineView::ToggleMediaLoop); break; case ContextMenuItem::DownloadMediaToDisk: - QObject::connect(item, &MenuItemHandler::triggered, [thisRef] { thisRef->triggerWebAction(QQuickWebEngineView::DownloadMediaToDisk); }); + action = m_view->action(QQuickWebEngineView::DownloadMediaToDisk); break; case ContextMenuItem::InspectElement: - QObject::connect(item, &MenuItemHandler::triggered, [thisRef] { thisRef->triggerWebAction(QQuickWebEngineView::InspectElement); }); + action = m_view->action(QQuickWebEngineView::InspectElement); break; case ContextMenuItem::ExitFullScreen: - QObject::connect(item, &MenuItemHandler::triggered, [thisRef] { thisRef->triggerWebAction(QQuickWebEngineView::ExitFullScreen); }); + action = m_view->action(QQuickWebEngineView::ExitFullScreen); break; case ContextMenuItem::SavePage: - QObject::connect(item, &MenuItemHandler::triggered, [thisRef] { thisRef->triggerWebAction(QQuickWebEngineView::SavePage); }); + action = m_view->action(QQuickWebEngineView::SavePage); break; case ContextMenuItem::ViewSource: - QObject::connect(item, &MenuItemHandler::triggered, [thisRef] { thisRef->triggerWebAction(QQuickWebEngineView::ViewSource); }); - menuItemIcon = QStringLiteral("view-source"); + action = m_view->action(QQuickWebEngineView::ViewSource); break; case ContextMenuItem::SpellingSuggestions: + { + QPointer<QQuickWebEngineView> thisRef(m_view); for (int i=0; i < m_contextData.spellCheckerSuggestions().count() && i < 4; i++) { - item = new MenuItemHandler(m_menu); + action = new QQuickWebEngineAction(m_menu); QString replacement = m_contextData.spellCheckerSuggestions().at(i); - QObject::connect(item, &MenuItemHandler::triggered, [thisRef, replacement] { thisRef->replaceMisspelledWord(replacement); }); - m_view->d_ptr->ui()->addMenuItem(item, replacement); + QObject::connect(action, &QQuickWebEngineAction::triggered, [thisRef, replacement] { thisRef->replaceMisspelledWord(replacement); }); + m_view->d_ptr->ui()->addMenuItem(action, m_menu); } return; + } case ContextMenuItem::Separator: - thisRef->d_ptr->ui()->addMenuSeparator(m_menu); + m_view->d_ptr->ui()->addMenuSeparator(m_menu); return; } - QString menuItemName = RenderViewContextMenuQt::getMenuItemName(menuItem); - thisRef->d_ptr->ui()->addMenuItem(item, menuItemName, menuItemIcon, isMenuItemEnabled(menuItem)); + action->d_ptr->setEnabled(isMenuItemEnabled(menuItem)); + m_view->d_ptr->ui()->addMenuItem(action, m_menu); } bool QQuickContextMenuBuilder::isMenuItemEnabled(ContextMenuItem menuItem) |