From a5e680c2ef404693870aedfb10f22ffc83cd38e7 Mon Sep 17 00:00:00 2001 From: Michal Klocek Date: Fri, 31 Aug 2018 10:29:07 +0200 Subject: Fix issues with qml bindings accessing non-existing adapter We have currently two levels of initialization for WebEngineView: the profile initialization and the adapter initialization. The adapter initialization is delayed to first navigation request to pick the right initial site instance and avoid creating dummy/blank WebContents, which in turn would start unnecessary render process. Profile initialization is delayed to make sure we avoid unnecessary default profile creations. Created profiles use filestorage. Unfortunately qml will call QQuickItem::componentComplete() only when the root element is completed and the bindings can be already in use by that time. Profile initialization has to take place before adapter initialization. Construct adapter together with WebEngineView, but create and initialize profile before adapter initialization. Go through WebEngineView and fix emitting signals based on adapter initialization. Most of the signals are emitted on initializationFinished(). Task-number: QTBUG-70248 Change-Id: I2acd8bff761c692a360733cbf537de53e1295695 Reviewed-by: Allan Sandfeld Jensen --- src/webengine/api/qquickwebengineprofile.h | 1 + src/webengine/api/qquickwebengineprofile_p.h | 2 +- src/webengine/api/qquickwebenginesettings_p.h | 2 +- src/webengine/api/qquickwebengineview.cpp | 155 ++++++++++++++------------ src/webengine/api/qquickwebengineview_p_p.h | 6 +- 5 files changed, 90 insertions(+), 76 deletions(-) (limited to 'src/webengine') diff --git a/src/webengine/api/qquickwebengineprofile.h b/src/webengine/api/qquickwebengineprofile.h index 4f1053924..9fc4f9eca 100644 --- a/src/webengine/api/qquickwebengineprofile.h +++ b/src/webengine/api/qquickwebengineprofile.h @@ -168,6 +168,7 @@ private: friend class QQuickWebEngineViewPrivate; friend class QQuickWebEngineDownloadItem; friend class QQuickWebEngineDownloadItemPrivate; + friend class QQuickWebEngineView; QScopedPointer d_ptr; }; diff --git a/src/webengine/api/qquickwebengineprofile_p.h b/src/webengine/api/qquickwebengineprofile_p.h index 9ed8b89de..d31ded0ec 100644 --- a/src/webengine/api/qquickwebengineprofile_p.h +++ b/src/webengine/api/qquickwebengineprofile_p.h @@ -90,7 +90,7 @@ public: static void userScripts_clear(QQmlListProperty *p); private: - friend class QQuickWebEngineViewPrivate; + friend class QQuickWebEngineView; QQuickWebEngineProfile *q_ptr; QScopedPointer m_settings; QPointer m_profileAdapter; diff --git a/src/webengine/api/qquickwebenginesettings_p.h b/src/webengine/api/qquickwebenginesettings_p.h index 179416b54..6e1aaca39 100644 --- a/src/webengine/api/qquickwebenginesettings_p.h +++ b/src/webengine/api/qquickwebenginesettings_p.h @@ -204,7 +204,7 @@ private: Q_DISABLE_COPY(QQuickWebEngineSettings) friend class QQuickWebEngineProfilePrivate; friend class QQuickWebEngineViewPrivate; - + friend class QQuickWebEngineView; void setParentSettings(QQuickWebEngineSettings *parentSettings); QScopedPointer d_ptr; diff --git a/src/webengine/api/qquickwebengineview.cpp b/src/webengine/api/qquickwebengineview.cpp index bdd3bfe26..6bf23ea7b 100644 --- a/src/webengine/api/qquickwebengineview.cpp +++ b/src/webengine/api/qquickwebengineview.cpp @@ -107,8 +107,11 @@ static QAccessibleInterface *webAccessibleFactory(const QString &, QObject *obje } #endif // QT_NO_ACCESSIBILITY +static QLatin1String defaultMimeType("text/html;charset=UTF-8"); + QQuickWebEngineViewPrivate::QQuickWebEngineViewPrivate() : m_profile(nullptr) + , adapter(QSharedPointer::create()) , m_history(new QQuickWebEngineHistory(this)) #if QT_CONFIG(webengine_testsupport) , m_testSupport(0) @@ -125,7 +128,7 @@ 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) { @@ -168,16 +171,13 @@ QQuickWebEngineViewPrivate::~QQuickWebEngineViewPrivate() 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); - adapter = QSharedPointer::create(); m_settings.reset(new QQuickWebEngineSettings(m_profile->settings())); -#if QT_CONFIG(webengine_webchannel) - if (m_webChannel) - adapter->setWebChannel(m_webChannel, m_webChannelWorld); -#endif + adapter->setClient(this); } } @@ -348,7 +348,6 @@ void QQuickWebEngineViewPrivate::urlChanged(const QUrl &url) { Q_Q(QQuickWebEngineView); Q_UNUSED(url); - explicitUrl = QUrl(); Q_EMIT q->urlChanged(); } @@ -473,7 +472,6 @@ void QQuickWebEngineViewPrivate::loadFinished(bool success, const QUrl &url, boo return; } if (success) { - explicitUrl = QUrl(); QTimer::singleShot(0, q, [q, url, errorDescription, errorCode]() { QQuickWebEngineLoadRequest loadRequest(url, QQuickWebEngineView::LoadSucceededStatus, errorDescription, errorCode); emit q->loadingChanged(&loadRequest); @@ -784,9 +782,12 @@ QQuickWebEngineView::~QQuickWebEngineView() 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(); } @@ -796,14 +797,21 @@ 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); #endif - if (!qFuzzyCompare(adapter->currentZoomFactor(), m_defaultZoomFactor)) - q->setZoomFactor(m_defaultZoomFactor); if (devToolsView && devToolsView->d_ptr->adapter) adapter->openDevToolsFrontend(devToolsView->d_ptr->adapter); @@ -874,20 +882,25 @@ void QQuickWebEngineViewPrivate::updateAction(QQuickWebEngineView::WebAction act 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->profileInitialized() && 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 @@ -899,11 +912,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() @@ -939,20 +953,17 @@ 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() { Q_D(QQuickWebEngineView); - // this can be called before onComplete for group properties d->initializeProfile(); return d->m_profile; } @@ -960,7 +971,24 @@ QQuickWebEngineProfile *QQuickWebEngineView::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() @@ -980,40 +1008,22 @@ QQmlListProperty QQuickWebEngineView::userScripts() d->userScripts_clear); } -void QQuickWebEngineViewPrivate::setProfile(QQuickWebEngineProfile *profile) +void QQuickWebEngineViewPrivate::updateAdapter() { - Q_Q(QQuickWebEngineView); - - if (profile == m_profile) - return; - - if (!m_profileInitialized) { - m_profile = profile; - return; - } - - if (m_profile) - m_profile->d_ptr->removeWebContentsAdapterClient(this); - - m_profile = profile; - m_profile->d_ptr->addWebContentsAdapterClient(this); - Q_EMIT q->profileChanged(); - m_settings->setParentSettings(profile->settings()); - - if (adapter->profile() != profileAdapter()->profile()) { - // 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::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::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(); } } @@ -1178,7 +1188,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(); } @@ -1194,8 +1204,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(); + } } /*! @@ -1963,7 +1975,6 @@ void QQuickWebEngineView::componentComplete() QQuickItem::componentComplete(); Q_D(QQuickWebEngineView); d->initializeProfile(); - d->adapter->setClient(d); #ifndef QT_NO_ACCESSIBILITY // Enable accessibility via a dynamic QQmlProperty, instead of using private API call // QQuickAccessibleAttached::qmlAttachedProperties(this). The qmlContext is required, otherwise diff --git a/src/webengine/api/qquickwebengineview_p_p.h b/src/webengine/api/qquickwebengineview_p_p.h index fda67a6bf..ee38ece6b 100644 --- a/src/webengine/api/qquickwebengineview_p_p.h +++ b/src/webengine/api/qquickwebengineview_p_p.h @@ -160,6 +160,7 @@ public: void updateAction(QQuickWebEngineView::WebAction) const; void adoptWebContents(QtWebEngineCore::WebContentsAdapter *webContents); void setProfile(QQuickWebEngineProfile *profile); + void updateAdapter(); void ensureContentsAdapter(); void setFullScreenMode(bool); @@ -178,7 +179,8 @@ public: #endif QQmlComponent *contextMenuExtraItems; QtWebEngineCore::WebEngineContextMenuData m_contextMenuData; - QUrl explicitUrl; + QUrl m_url; + QString m_html; QUrl iconUrl; QQuickWebEngineFaviconProvider *faviconProvider; int loadProgress; @@ -203,7 +205,7 @@ private: QList m_userScripts; qreal m_dpiScale; QColor m_backgroundColor; - qreal m_defaultZoomFactor; + qreal m_zoomFactor; bool m_ui2Enabled; bool m_profileInitialized; }; -- cgit v1.2.3