From ef1f608f76f02f11b4bdcc8d52fa41cdf4cdf5c3 Mon Sep 17 00:00:00 2001 From: Allan Sandfeld Jensen Date: Fri, 29 Jan 2016 15:57:18 +0100 Subject: Preserve webchannel and userscripts when restoring history Most page-state is set in webcontentsadapter::initialize except user scripts and webchannel. This patch ensures those are initialized too when changing to a new adapter during history restore. Change-Id: I4dca23ddab50480b1a72252a038834ce1802ad77 Task-number: QTBUG-50751 Reviewed-by: Kai Koehne Reviewed-by: David Rosca --- src/webenginewidgets/api/qwebenginepage.cpp | 14 +++++++-- src/webenginewidgets/api/qwebenginepage_p.h | 1 + .../api/qwebenginescriptcollection.cpp | 12 ++++++++ .../api/qwebenginescriptcollection_p.h | 2 ++ .../widgets/qwebenginepage/tst_qwebenginepage.cpp | 36 ++++++++++++++++++++++ 5 files changed, 63 insertions(+), 2 deletions(-) diff --git a/src/webenginewidgets/api/qwebenginepage.cpp b/src/webenginewidgets/api/qwebenginepage.cpp index 511ddfb0f..b1bf33067 100644 --- a/src/webenginewidgets/api/qwebenginepage.cpp +++ b/src/webenginewidgets/api/qwebenginepage.cpp @@ -107,6 +107,7 @@ QWebEnginePagePrivate::QWebEnginePagePrivate(QWebEngineProfile *_profile) , m_isBeingAdopted(false) , m_backgroundColor(Qt::white) , fullscreenMode(false) + , webChannel(nullptr) { memset(actions, 0, sizeof(actions)); } @@ -407,8 +408,14 @@ void QWebEnginePagePrivate::recreateFromSerializedHistory(QDataStream &input) { QExplicitlySharedDataPointer newWebContents = WebContentsAdapter::createFromSerializedNavigationHistory(input, this); if (newWebContents) { + // Keep the old adapter referenced so the user-scripts are not + // unregistered immediately. + QExplicitlySharedDataPointer oldWebContents = adapter; adapter = newWebContents.data(); adapter->initialize(this); + if (webChannel) + adapter->setWebChannel(webChannel); + scriptCollection.d->rebindToContents(adapter.data()); } } @@ -519,7 +526,7 @@ QWebEngineSettings *QWebEnginePage::settings() const QWebChannel *QWebEnginePage::webChannel() const { Q_D(const QWebEnginePage); - return d->adapter->webChannel(); + return d->webChannel; } /*! @@ -536,7 +543,10 @@ QWebChannel *QWebEnginePage::webChannel() const void QWebEnginePage::setWebChannel(QWebChannel *channel) { Q_D(QWebEnginePage); - d->adapter->setWebChannel(channel); + if (d->webChannel != channel) { + d->webChannel = channel; + d->adapter->setWebChannel(channel); + } } /*! diff --git a/src/webenginewidgets/api/qwebenginepage_p.h b/src/webenginewidgets/api/qwebenginepage_p.h index 9cc4553d1..18110d923 100644 --- a/src/webenginewidgets/api/qwebenginepage_p.h +++ b/src/webenginewidgets/api/qwebenginepage_p.h @@ -151,6 +151,7 @@ public: bool m_isBeingAdopted; QColor m_backgroundColor; bool fullscreenMode; + QWebChannel *webChannel; mutable QtWebEngineCore::CallbackDirectory m_callbacks; mutable QAction *actions[QWebEnginePage::WebActionCount]; diff --git a/src/webenginewidgets/api/qwebenginescriptcollection.cpp b/src/webenginewidgets/api/qwebenginescriptcollection.cpp index 9967cde85..117c35b5a 100644 --- a/src/webenginewidgets/api/qwebenginescriptcollection.cpp +++ b/src/webenginewidgets/api/qwebenginescriptcollection.cpp @@ -220,3 +220,15 @@ void QWebEngineScriptCollectionPrivate::reserve(int capacity) { m_scriptController->reserve(m_contents, capacity); } + +void QWebEngineScriptCollectionPrivate::rebindToContents(QtWebEngineCore::WebContentsAdapter *page) +{ + Q_ASSERT(m_contents); + Q_ASSERT(page); + Q_ASSERT(m_contents != page); + + Q_FOREACH (const UserScript &script, m_scriptController->registeredScripts(m_contents)) { + m_scriptController->addUserScript(script, page); + } + m_contents = page; +} diff --git a/src/webenginewidgets/api/qwebenginescriptcollection_p.h b/src/webenginewidgets/api/qwebenginescriptcollection_p.h index cc6e88445..b5ae60a2c 100644 --- a/src/webenginewidgets/api/qwebenginescriptcollection_p.h +++ b/src/webenginewidgets/api/qwebenginescriptcollection_p.h @@ -69,6 +69,8 @@ public: QList toList(const QString &scriptName = QString()) const; QWebEngineScript find(const QString & name) const; + void rebindToContents(QtWebEngineCore::WebContentsAdapter *contents); + void insert(const QWebEngineScript &); bool remove(const QWebEngineScript &); void clear(); diff --git a/tests/auto/widgets/qwebenginepage/tst_qwebenginepage.cpp b/tests/auto/widgets/qwebenginepage/tst_qwebenginepage.cpp index 8fd71c701..690cf70e4 100644 --- a/tests/auto/widgets/qwebenginepage/tst_qwebenginepage.cpp +++ b/tests/auto/widgets/qwebenginepage/tst_qwebenginepage.cpp @@ -33,6 +33,7 @@ #include #include #include +#include #include #include #include @@ -42,6 +43,8 @@ #include #include #include +#include +#include #include #include #include @@ -237,6 +240,8 @@ private Q_SLOTS: void loadInSignalHandlers_data(); void loadInSignalHandlers(); + void restoreHistory(); + private: QWebEngineView* m_view; QWebEnginePage* m_page; @@ -5079,5 +5084,36 @@ void tst_QWebEnginePage::loadInSignalHandlers() QCOMPARE(m_page->url(), urlForSetter); } +void tst_QWebEnginePage::restoreHistory() +{ + QWebChannel *channel = new QWebChannel; + QWebEnginePage *page = new QWebEnginePage; + page->setWebChannel(channel); + + QWebEngineScript script; + script.setName(QStringLiteral("script")); + page->scripts().insert(script); + + QSignalSpy spy(page, SIGNAL(loadFinished(bool))); + page->load(QUrl(QStringLiteral("qrc:/resources/test1.html"))); + QTRY_COMPARE(spy.count(), 1); + + QCOMPARE(page->webChannel(), channel); + QVERIFY(page->scripts().contains(script)); + + QByteArray data; + QDataStream out(&data, QIODevice::ReadWrite); + out << *page->history(); + QDataStream in(&data, QIODevice::ReadOnly); + in >> *page->history(); + QTRY_COMPARE(spy.count(), 2); + + QCOMPARE(page->webChannel(), channel); + QVERIFY(page->scripts().contains(script)); + + delete page; + delete channel; +} + QTEST_MAIN(tst_QWebEnginePage) #include "tst_qwebenginepage.moc" -- cgit v1.2.3