From e01dc0556f72da94e8a310959f3ad0471d063bcb Mon Sep 17 00:00:00 2001
From: Szabolcs David <davidsz@inf.u-szeged.hu>
Date: Wed, 1 Jun 2016 08:54:03 -0700
Subject: [PATCH] Add profile-wide user scripts to the Quick API

Add API tests in order to try how it works in C++ and QML.

Task-number: QTBUG-51034
Change-Id: I1680297e2dafba39dbd4b161f0dbdb14fb6d4243
Reviewed-by: Allan Sandfeld Jensen <allan.jensen@qt.io>
---
 src/webengine/api/qquickwebengineprofile.cpp  | 61 +++++++++++++++++++
 src/webengine/api/qquickwebengineprofile.h    |  5 ++
 src/webengine/api/qquickwebengineprofile_p.h  |  7 +++
 src/webengine/api/qquickwebenginescript_p.h   |  1 +
 .../quick/qmltests/data/tst_userScripts.qml   | 19 ++++++
 .../tst_qquickwebengineview.cpp               | 25 ++++++++
 6 files changed, 118 insertions(+)

diff --git a/src/webengine/api/qquickwebengineprofile.cpp b/src/webengine/api/qquickwebengineprofile.cpp
index 871428f33..c88c7faf8 100644
--- a/src/webengine/api/qquickwebengineprofile.cpp
+++ b/src/webengine/api/qquickwebengineprofile.cpp
@@ -42,6 +42,7 @@
 #include "qquickwebenginedownloaditem_p.h"
 #include "qquickwebenginedownloaditem_p_p.h"
 #include "qquickwebengineprofile_p.h"
+#include "qquickwebenginescript_p_p.h"
 #include "qquickwebenginesettings_p.h"
 #include "qwebenginecookiestore.h"
 
@@ -49,6 +50,7 @@
 
 #include "browser_context_adapter.h"
 #include <qtwebenginecoreglobal.h>
+#include "renderer_host/user_resource_controller_host.h"
 #include "web_engine_settings.h"
 
 using QtWebEngineCore::BrowserContextAdapter;
@@ -229,6 +231,38 @@ void QQuickWebEngineProfilePrivate::downloadUpdated(const DownloadItemInfo &info
     }
 }
 
+void QQuickWebEngineProfilePrivate::userScripts_append(QQmlListProperty<QQuickWebEngineScript> *p, QQuickWebEngineScript *script)
+{
+    Q_ASSERT(p && p->data);
+    QQuickWebEngineProfilePrivate *d = static_cast<QQuickWebEngineProfilePrivate *>(p->data);
+    QtWebEngineCore::UserResourceControllerHost *resourceController = d->browserContext()->userResourceController();
+    d->m_userScripts.append(script);
+    script->d_func()->bind(resourceController);
+}
+
+int QQuickWebEngineProfilePrivate::userScripts_count(QQmlListProperty<QQuickWebEngineScript> *p)
+{
+    Q_ASSERT(p && p->data);
+    QQuickWebEngineProfilePrivate *d = static_cast<QQuickWebEngineProfilePrivate *>(p->data);
+    return d->m_userScripts.count();
+}
+
+QQuickWebEngineScript *QQuickWebEngineProfilePrivate::userScripts_at(QQmlListProperty<QQuickWebEngineScript> *p, int idx)
+{
+    Q_ASSERT(p && p->data);
+    QQuickWebEngineProfilePrivate *d = static_cast<QQuickWebEngineProfilePrivate *>(p->data);
+    return d->m_userScripts.at(idx);
+}
+
+void QQuickWebEngineProfilePrivate::userScripts_clear(QQmlListProperty<QQuickWebEngineScript> *p)
+{
+    Q_ASSERT(p && p->data);
+    QQuickWebEngineProfilePrivate *d = static_cast<QQuickWebEngineProfilePrivate *>(p->data);
+    QtWebEngineCore::UserResourceControllerHost *resourceController = d->browserContext()->userResourceController();
+    resourceController->clearAllScripts(NULL);
+    d->m_userScripts.clear();
+}
+
 /*!
     \qmltype WebEngineProfile
     \instantiates QQuickWebEngineProfile
@@ -851,4 +885,31 @@ QQuickWebEngineSettings *QQuickWebEngineProfile::settings() const
     return d->settings();
 }
 
+/*!
+    \qmlproperty list<WebEngineScript> WebEngineProfile::userScripts
+    \since 1.5
+
+    Returns the collection of WebEngineScripts that are injected into all pages that share
+    this profile.
+
+    \sa WebEngineScript
+*/
+
+/*!
+    \property QQuickWebEngineProfile::userScripts
+    \since 5.9
+
+    \brief the collection of scripts that are injected into all pages that share
+    this profile.
+*/
+QQmlListProperty<QQuickWebEngineScript> QQuickWebEngineProfile::userScripts()
+{
+    Q_D(QQuickWebEngineProfile);
+    return QQmlListProperty<QQuickWebEngineScript>(this, d,
+                                                   d->userScripts_append,
+                                                   d->userScripts_count,
+                                                   d->userScripts_at,
+                                                   d->userScripts_clear);
+}
+
 QT_END_NAMESPACE
diff --git a/src/webengine/api/qquickwebengineprofile.h b/src/webengine/api/qquickwebengineprofile.h
index d0d925930..0155c954a 100644
--- a/src/webengine/api/qquickwebengineprofile.h
+++ b/src/webengine/api/qquickwebengineprofile.h
@@ -46,6 +46,7 @@
 #include <QtCore/QObject>
 #include <QtCore/QScopedPointer>
 #include <QtCore/QString>
+#include <QtQml/QQmlListProperty>
 
 namespace QtWebEngineCore {
 class BrowserContextAdapter;
@@ -55,6 +56,7 @@ QT_BEGIN_NAMESPACE
 
 class QQuickWebEngineDownloadItem;
 class QQuickWebEngineProfilePrivate;
+class QQuickWebEngineScript;
 class QQuickWebEngineSettings;
 class QWebEngineCookieStore;
 class QWebEngineUrlRequestInterceptor;
@@ -73,6 +75,7 @@ class Q_WEBENGINE_EXPORT QQuickWebEngineProfile : public QObject {
     Q_PROPERTY(int httpCacheMaximumSize READ httpCacheMaximumSize WRITE setHttpCacheMaximumSize NOTIFY httpCacheMaximumSizeChanged FINAL)
     Q_PROPERTY(QStringList spellCheckLanguages READ spellCheckLanguages WRITE setSpellCheckLanguages NOTIFY spellCheckLanguagesChanged FINAL REVISION 3)
     Q_PROPERTY(bool spellCheckEnabled READ isSpellCheckEnabled WRITE setSpellCheckEnabled NOTIFY spellCheckEnabledChanged FINAL REVISION 3)
+    Q_PROPERTY(QQmlListProperty<QQuickWebEngineScript> userScripts READ userScripts FINAL REVISION 4)
 
 public:
     QQuickWebEngineProfile(QObject *parent = Q_NULLPTR);
@@ -136,6 +139,8 @@ public:
     void setSpellCheckEnabled(bool enabled);
     bool isSpellCheckEnabled() const;
 
+    QQmlListProperty<QQuickWebEngineScript> userScripts();
+
     static QQuickWebEngineProfile *defaultProfile();
 
 Q_SIGNALS:
diff --git a/src/webengine/api/qquickwebengineprofile_p.h b/src/webengine/api/qquickwebengineprofile_p.h
index 1ba1eb53f..1828f8085 100644
--- a/src/webengine/api/qquickwebengineprofile_p.h
+++ b/src/webengine/api/qquickwebengineprofile_p.h
@@ -80,12 +80,19 @@ public:
     void downloadRequested(DownloadItemInfo &info) Q_DECL_OVERRIDE;
     void downloadUpdated(const DownloadItemInfo &info) Q_DECL_OVERRIDE;
 
+    // QQmlListPropertyHelpers
+    static void userScripts_append(QQmlListProperty<QQuickWebEngineScript> *p, QQuickWebEngineScript *script);
+    static int userScripts_count(QQmlListProperty<QQuickWebEngineScript> *p);
+    static QQuickWebEngineScript *userScripts_at(QQmlListProperty<QQuickWebEngineScript> *p, int idx);
+    static void userScripts_clear(QQmlListProperty<QQuickWebEngineScript> *p);
+
 private:
     friend class QQuickWebEngineViewPrivate;
     QQuickWebEngineProfile *q_ptr;
     QScopedPointer<QQuickWebEngineSettings> m_settings;
     QSharedPointer<QtWebEngineCore::BrowserContextAdapter> m_browserContextRef;
     QMap<quint32, QPointer<QQuickWebEngineDownloadItem> > m_ongoingDownloads;
+    QList<QQuickWebEngineScript *> m_userScripts;
 };
 
 QT_END_NAMESPACE
diff --git a/src/webengine/api/qquickwebenginescript_p.h b/src/webengine/api/qquickwebenginescript_p.h
index 851ecd26b..c4368f1d5 100644
--- a/src/webengine/api/qquickwebenginescript_p.h
+++ b/src/webengine/api/qquickwebenginescript_p.h
@@ -116,6 +116,7 @@ protected:
     void timerEvent(QTimerEvent *e) override;
 
 private:
+    friend class QQuickWebEngineProfilePrivate;
     friend class QQuickWebEngineViewPrivate;
     Q_DECLARE_PRIVATE(QQuickWebEngineScript)
     QScopedPointer<QQuickWebEngineScriptPrivate> d_ptr;
diff --git a/tests/auto/quick/qmltests/data/tst_userScripts.qml b/tests/auto/quick/qmltests/data/tst_userScripts.qml
index 88fa6f6e3..e9a4eba99 100644
--- a/tests/auto/quick/qmltests/data/tst_userScripts.qml
+++ b/tests/auto/quick/qmltests/data/tst_userScripts.qml
@@ -60,6 +60,12 @@ Item {
         height: 300
     }
 
+    TestWebEngineView {
+        id: webEngineView2
+        width: 400
+        height: 300
+    }
+
     TestWebEngineView {
         id: webEngineViewWithConditionalUserScripts
         width: 400
@@ -82,6 +88,7 @@ Item {
         function init() {
             webEngineView.url = "";
             webEngineView.userScripts = [];
+            webEngineView.profile.userScripts = [];
         }
 
         function test_oneScript() {
@@ -173,5 +180,17 @@ Item {
             webEngineView.waitForLoadSucceeded();
             tryCompare(webEngineView, "title", "Test page with huge link area");
         }
+
+        function test_profileWideScript() {
+            webEngineView.profile.userScripts = [ changeDocumentTitleScript ];
+
+            webEngineView.url = Qt.resolvedUrl("test1.html");
+            webEngineView.waitForLoadSucceeded();
+            compare(webEngineView.title, "New title");
+
+            webEngineView2.url = Qt.resolvedUrl("test1.html");
+            webEngineView2.waitForLoadSucceeded();
+            compare(webEngineView2.title, "New title");
+        }
     }
 }
diff --git a/tests/auto/quick/qquickwebengineview/tst_qquickwebengineview.cpp b/tests/auto/quick/qquickwebengineview/tst_qquickwebengineview.cpp
index 7f808a4e2..dcc2c4f5e 100644
--- a/tests/auto/quick/qquickwebengineview/tst_qquickwebengineview.cpp
+++ b/tests/auto/quick/qquickwebengineview/tst_qquickwebengineview.cpp
@@ -34,6 +34,7 @@
 #include <QtGui/qpa/qwindowsysteminterface.h>
 #include <QtQml/QQmlEngine>
 #include <QtTest/QtTest>
+#include <QtWebEngine/QQuickWebEngineProfile>
 #include <private/qquickwebengineview_p.h>
 
 #include <functional>
@@ -77,6 +78,7 @@ private Q_SLOTS:
     void inputEventForwardingDisabledWhenActiveFocusOnPressDisabled();
 
     void changeLocale();
+    void userScripts();
 
 private:
     inline QQuickWebEngineView *newWebEngineView();
@@ -715,5 +717,28 @@ void tst_QQuickWebEngineView::changeLocale()
     delete viewEN;
 }
 
+void tst_QQuickWebEngineView::userScripts()
+{
+    QScopedPointer<QQuickWebEngineView> webEngineView1(newWebEngineView());
+    webEngineView1->setParentItem(m_window->contentItem());
+    QScopedPointer<QQuickWebEngineView> webEngineView2(newWebEngineView());
+    webEngineView2->setParentItem(m_window->contentItem());
+
+    QQmlListReference list(webEngineView1->profile(), "userScripts");
+    QQuickWebEngineScript script;
+    script.setSourceCode("document.title = 'New title';");
+    list.append(&script);
+
+    webEngineView1->setUrl(urlFromTestPath("html/basic_page.html"));
+    QVERIFY(waitForLoadSucceeded(webEngineView1.data()));
+    QTRY_COMPARE(webEngineView1->title(), QStringLiteral("New title"));
+
+    webEngineView2->setUrl(urlFromTestPath("html/basic_page.html"));
+    QVERIFY(waitForLoadSucceeded(webEngineView2.data()));
+    QTRY_COMPARE(webEngineView2->title(), QStringLiteral("New title"));
+
+    list.clear();
+}
+
 QTEST_MAIN(tst_QQuickWebEngineView)
 #include "tst_qquickwebengineview.moc"
-- 
GitLab