From b0324c5e020b98cbc0caf8176bbdfc5cd80b545e Mon Sep 17 00:00:00 2001
From: Viktor Engelmann <Viktor.Engelmann@qt.io>
Date: Mon, 13 Mar 2017 14:30:02 +0100
Subject: [PATCH] Handle ViewHostMsg_Focus message from chromium
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Calling the method window.focus() in javascript causes chromium to send
a ViewHostMsg_Focus message, which is received by RenderViewHost,
which then calls RenderViewHost::OnFocus.
This calls WebContentsDelegate::ActivateContents, which does
nothing in the default implementation. We now override this method in
WebContentsDelegateQt::ActivateContents and call Focus() on
the WebContents object IF the new WebEngineSettings value
AllowWindowActivationFromJavaScript is true (by default, it is false).
This in turn calls QWebEnginePagePrivate::focusContainer.
The WebEnginePage now calls QWidget::activateWindow() in addition
to QWidget::setFocus, to make sure the window is also activated (which
it might not be, if multiple windows are open).
For the QML side, a new boolean Property
allowWindowActivationFromJavaScript was added.

Task-number: QTBUG-58800
Change-Id: Iabf5d4d15236c77838a3886de81e9dafcaf49f5d
Reviewed-by: Jüri Valdmann <juri.valdmann@qt.io>
Reviewed-by: Joerg Bornemann <joerg.bornemann@qt.io>
---
 src/core/web_contents_delegate_qt.cpp          |  7 +++++++
 src/core/web_contents_delegate_qt.h            |  1 +
 src/core/web_engine_settings.cpp               |  1 +
 src/core/web_engine_settings.h                 |  3 ++-
 src/webengine/api/qquickwebenginesettings.cpp  | 18 ++++++++++++++++++
 src/webengine/api/qquickwebenginesettings_p.h  |  4 ++++
 src/webengine/api/qquickwebengineview.cpp      |  3 +++
 src/webengine/plugin/plugin.cpp                |  1 +
 src/webengine/plugin/plugin.pro                |  2 +-
 src/webengine/plugin/plugins.qmltypes          |  9 ++++++---
 src/webenginewidgets/api/qwebenginepage.cpp    |  4 +++-
 .../api/qwebenginesettings.cpp                 |  2 ++
 src/webenginewidgets/api/qwebenginesettings.h  |  3 ++-
 .../doc/src/qwebenginesettings_lgpl.qdoc       |  3 +++
 14 files changed, 54 insertions(+), 7 deletions(-)

diff --git a/src/core/web_contents_delegate_qt.cpp b/src/core/web_contents_delegate_qt.cpp
index 6c5b63960..3e09df340 100644
--- a/src/core/web_contents_delegate_qt.cpp
+++ b/src/core/web_contents_delegate_qt.cpp
@@ -403,6 +403,13 @@ void WebContentsDelegateQt::DidFirstVisuallyNonEmptyPaint()
     }
 }
 
+void WebContentsDelegateQt::ActivateContents(content::WebContents* contents)
+{
+    WebEngineSettings *settings = m_viewClient->webEngineSettings();
+    if (settings->testAttribute(settings->Attribute::AllowWindowActivationFromJavaScript))
+        contents->Focus();
+}
+
 void WebContentsDelegateQt::RequestToLockMouse(content::WebContents *web_contents, bool user_gesture, bool last_unlocked_by_target)
 {
     Q_UNUSED(user_gesture);
diff --git a/src/core/web_contents_delegate_qt.h b/src/core/web_contents_delegate_qt.h
index 2e294a841..8b5f5fd80 100644
--- a/src/core/web_contents_delegate_qt.h
+++ b/src/core/web_contents_delegate_qt.h
@@ -136,6 +136,7 @@ public:
     void DidNavigateAnyFrame(content::RenderFrameHost *render_frame_host, const content::LoadCommittedDetails &details, const content::FrameNavigateParams &params) override;
     void WasShown() override;
     void DidFirstVisuallyNonEmptyPaint() override;
+    void ActivateContents(content::WebContents* contents) override;
 
     void overrideWebPreferences(content::WebContents *, content::WebPreferences*);
     void allowCertificateError(const QSharedPointer<CertificateErrorController> &) ;
diff --git a/src/core/web_engine_settings.cpp b/src/core/web_engine_settings.cpp
index 58f0a3e2c..ca051397b 100644
--- a/src/core/web_engine_settings.cpp
+++ b/src/core/web_engine_settings.cpp
@@ -243,6 +243,7 @@ void WebEngineSettings::initDefaults(bool offTheRecord)
         s_defaultAttributes.insert(PrintElementBackgrounds, true);
         s_defaultAttributes.insert(AllowRunningInsecureContent, allowRunningInsecureContent);
         s_defaultAttributes.insert(AllowGeolocationOnInsecureOrigins, false);
+        s_defaultAttributes.insert(AllowWindowActivationFromJavaScript, false);
     }
     if (offTheRecord)
         m_attributes.insert(LocalStorageEnabled, false);
diff --git a/src/core/web_engine_settings.h b/src/core/web_engine_settings.h
index 4b0ce7b39..7cfb9434f 100644
--- a/src/core/web_engine_settings.h
+++ b/src/core/web_engine_settings.h
@@ -83,7 +83,8 @@ public:
         FocusOnNavigationEnabled,
         PrintElementBackgrounds,
         AllowRunningInsecureContent,
-        AllowGeolocationOnInsecureOrigins
+        AllowGeolocationOnInsecureOrigins,
+        AllowWindowActivationFromJavaScript
     };
 
     // Must match the values from the public API in qwebenginesettings.h.
diff --git a/src/webengine/api/qquickwebenginesettings.cpp b/src/webengine/api/qquickwebenginesettings.cpp
index ff2541376..cdbb25e4c 100644
--- a/src/webengine/api/qquickwebenginesettings.cpp
+++ b/src/webengine/api/qquickwebenginesettings.cpp
@@ -362,6 +362,16 @@ bool QQuickWebEngineSettings::allowGeolocationOnInsecureOrigins() const
     return d_ptr->testAttribute(WebEngineSettings::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(WebEngineSettings::AllowWindowActivationFromJavaScript);
+}
+
 /*!
     \qmlproperty string WebEngineSettings::defaultTextEncoding
     \since QtWebEngine 1.2
@@ -564,6 +574,14 @@ void QQuickWebEngineSettings::setAllowGeolocationOnInsecureOrigins(bool on)
         Q_EMIT allowGeolocationOnInsecureOriginsChanged();
 }
 
+void QQuickWebEngineSettings::setAllowWindowActivationFromJavaScript(bool on)
+{
+    bool wasOn = d_ptr->testAttribute(WebEngineSettings::AllowWindowActivationFromJavaScript);
+    d_ptr->setAttribute(WebEngineSettings::AllowWindowActivationFromJavaScript, on);
+    if (wasOn != on)
+        Q_EMIT allowWindowActivationFromJavaScriptChanged();
+}
+
 void QQuickWebEngineSettings::setParentSettings(QQuickWebEngineSettings *parentSettings)
 {
     d_ptr->setParentSettings(parentSettings->d_ptr.data());
diff --git a/src/webengine/api/qquickwebenginesettings_p.h b/src/webengine/api/qquickwebenginesettings_p.h
index 10217c678..1b9988bce 100644
--- a/src/webengine/api/qquickwebenginesettings_p.h
+++ b/src/webengine/api/qquickwebenginesettings_p.h
@@ -86,6 +86,7 @@ class Q_WEBENGINE_PRIVATE_EXPORT QQuickWebEngineSettings : public QObject {
     Q_PROPERTY(bool printElementBackgrounds READ printElementBackgrounds WRITE setPrintElementBackgrounds NOTIFY printElementBackgroundsChanged REVISION 3 FINAL)
     Q_PROPERTY(bool allowRunningInsecureContent READ allowRunningInsecureContent WRITE setAllowRunningInsecureContent NOTIFY allowRunningInsecureContentChanged REVISION 3 FINAL)
     Q_PROPERTY(bool allowGeolocationOnInsecureOrigins READ allowGeolocationOnInsecureOrigins WRITE setAllowGeolocationOnInsecureOrigins NOTIFY allowGeolocationOnInsecureOriginsChanged REVISION 4 FINAL)
+    Q_PROPERTY(bool allowWindowActivationFromJavaScript READ allowWindowActivationFromJavaScript WRITE setAllowWindowActivationFromJavaScript NOTIFY allowWindowActivationFromJavaScriptChanged REVISION 5 FINAL)
 
 public:
     ~QQuickWebEngineSettings();
@@ -113,6 +114,7 @@ public:
     bool printElementBackgrounds() const;
     bool allowRunningInsecureContent() const;
     bool allowGeolocationOnInsecureOrigins() const;
+    bool allowWindowActivationFromJavaScript() const;
 
     void setAutoLoadImages(bool on);
     void setJavascriptEnabled(bool on);
@@ -137,6 +139,7 @@ public:
     void setPrintElementBackgrounds(bool on);
     void setAllowRunningInsecureContent(bool on);
     void setAllowGeolocationOnInsecureOrigins(bool on);
+    void setAllowWindowActivationFromJavaScript(bool on);
 
 signals:
     void autoLoadImagesChanged();
@@ -162,6 +165,7 @@ signals:
     Q_REVISION(3) void printElementBackgroundsChanged();
     Q_REVISION(3) void allowRunningInsecureContentChanged();
     Q_REVISION(4) void allowGeolocationOnInsecureOriginsChanged();
+    Q_REVISION(5) void allowWindowActivationFromJavaScriptChanged();
 
 private:
     explicit QQuickWebEngineSettings(QQuickWebEngineSettings *parentSettings = 0);
diff --git a/src/webengine/api/qquickwebengineview.cpp b/src/webengine/api/qquickwebengineview.cpp
index 45f65e49b..dac844fdb 100644
--- a/src/webengine/api/qquickwebengineview.cpp
+++ b/src/webengine/api/qquickwebengineview.cpp
@@ -564,6 +564,9 @@ void QQuickWebEngineViewPrivate::loadFinished(bool success, const QUrl &url, boo
 void QQuickWebEngineViewPrivate::focusContainer()
 {
     Q_Q(QQuickWebEngineView);
+    QQuickWindow *window = q->window();
+    if (window)
+        window->requestActivate();
     q->forceActiveFocus();
 }
 
diff --git a/src/webengine/plugin/plugin.cpp b/src/webengine/plugin/plugin.cpp
index 3c8991ff7..668d55458 100644
--- a/src/webengine/plugin/plugin.cpp
+++ b/src/webengine/plugin/plugin.cpp
@@ -109,6 +109,7 @@ public:
         qmlRegisterUncreatableType<QQuickWebEngineSettings, 2>(uri, 1, 3, "WebEngineSettings", tr("Cannot create a separate instance of WebEngineSettings"));
         qmlRegisterUncreatableType<QQuickWebEngineSettings, 3>(uri, 1, 4, "WebEngineSettings", tr("Cannot create a separate instance of WebEngineSettings"));
         qmlRegisterUncreatableType<QQuickWebEngineSettings, 4>(uri, 1, 5, "WebEngineSettings", tr("Cannot create a separate instance of WebEngineSettings"));
+        qmlRegisterUncreatableType<QQuickWebEngineSettings, 5>(uri, 1, 6, "WebEngineSettings", tr("Cannot create a separate instance of WebEngineSettings"));
         qmlRegisterSingletonType<QQuickWebEngineSingleton>(uri, 1, 1, "WebEngine", webEngineSingletonProvider);
         qmlRegisterUncreatableType<QQuickWebEngineHistory>(uri, 1, 1, "NavigationHistory",
             tr("Cannot create a separate instance of NavigationHistory"));
diff --git a/src/webengine/plugin/plugin.pro b/src/webengine/plugin/plugin.pro
index 68404b4f8..1f9ef00c5 100644
--- a/src/webengine/plugin/plugin.pro
+++ b/src/webengine/plugin/plugin.pro
@@ -1,7 +1,7 @@
 CXX_MODULE = qml
 TARGET = qtwebengineplugin
 TARGETPATH = QtWebEngine
-IMPORT_VERSION = 1.5
+IMPORT_VERSION = 1.6
 
 QT += webengine qml quick
 QT_PRIVATE += webengine-private
diff --git a/src/webengine/plugin/plugins.qmltypes b/src/webengine/plugin/plugins.qmltypes
index 81ff25a63..0cfa2d25b 100644
--- a/src/webengine/plugin/plugins.qmltypes
+++ b/src/webengine/plugin/plugins.qmltypes
@@ -4,7 +4,7 @@ import QtQuick.tooling 1.2
 // It is used for QML tooling purposes only.
 //
 // This file was auto-generated by:
-// 'qmlplugindump -defaultplatform -dependencies dependencies.json -nonrelocatable QtWebEngine 1.5'
+// 'qmlplugindump -defaultplatform -dependencies dependencies.json -nonrelocatable QtWebEngine 1.6'
 
 Module {
     dependencies: ["QtQuick 2.6"]
@@ -509,10 +509,11 @@ Module {
             "QtWebEngine/WebEngineSettings 1.2",
             "QtWebEngine/WebEngineSettings 1.3",
             "QtWebEngine/WebEngineSettings 1.4",
-            "QtWebEngine/WebEngineSettings 1.5"
+            "QtWebEngine/WebEngineSettings 1.5",
+            "QtWebEngine/WebEngineSettings 1.6"
         ]
         isCreatable: false
-        exportMetaObjectRevisions: [0, 1, 2, 3, 4]
+        exportMetaObjectRevisions: [0, 1, 2, 3, 4, 5]
         Property { name: "autoLoadImages"; type: "bool" }
         Property { name: "javascriptEnabled"; type: "bool" }
         Property { name: "javascriptCanOpenWindows"; type: "bool" }
@@ -536,6 +537,7 @@ Module {
         Property { name: "printElementBackgrounds"; revision: 3; type: "bool" }
         Property { name: "allowRunningInsecureContent"; revision: 3; type: "bool" }
         Property { name: "allowGeolocationOnInsecureOrigins"; revision: 4; type: "bool" }
+        Property { name: "allowWindowActivationFromJavaScript"; revision: 5; type: "bool" }
         Signal { name: "fullScreenSupportEnabledChanged"; revision: 1 }
         Signal { name: "screenCaptureEnabledChanged"; revision: 2 }
         Signal { name: "webGLEnabledChanged"; revision: 2 }
@@ -546,6 +548,7 @@ Module {
         Signal { name: "printElementBackgroundsChanged"; revision: 3 }
         Signal { name: "allowRunningInsecureContentChanged"; revision: 3 }
         Signal { name: "allowGeolocationOnInsecureOriginsChanged"; revision: 4 }
+        Signal { name: "allowWindowActivationFromJavaScriptChanged"; revision: 5 }
     }
     Component {
         name: "QQuickWebEngineSingleton"
diff --git a/src/webenginewidgets/api/qwebenginepage.cpp b/src/webenginewidgets/api/qwebenginepage.cpp
index 45b6af763..40180d9b8 100644
--- a/src/webenginewidgets/api/qwebenginepage.cpp
+++ b/src/webenginewidgets/api/qwebenginepage.cpp
@@ -379,8 +379,10 @@ void QWebEnginePagePrivate::didPrintPageToPdf(const QString &filePath, bool succ
 
 void QWebEnginePagePrivate::focusContainer()
 {
-    if (view)
+    if (view) {
+        view->activateWindow();
         view->setFocus();
+    }
 }
 
 void QWebEnginePagePrivate::unhandledKeyEvent(QKeyEvent *event)
diff --git a/src/webenginewidgets/api/qwebenginesettings.cpp b/src/webenginewidgets/api/qwebenginesettings.cpp
index 08d24376a..4c8c4be33 100644
--- a/src/webenginewidgets/api/qwebenginesettings.cpp
+++ b/src/webenginewidgets/api/qwebenginesettings.cpp
@@ -97,6 +97,8 @@ static WebEngineSettings::Attribute toWebEngineAttribute(QWebEngineSettings::Web
         return WebEngineSettings::AllowRunningInsecureContent;
     case QWebEngineSettings::AllowGeolocationOnInsecureOrigins:
         return WebEngineSettings::AllowGeolocationOnInsecureOrigins;
+    case QWebEngineSettings::AllowWindowActivationFromJavaScript:
+        return WebEngineSettings::AllowWindowActivationFromJavaScript;
 
     default:
         return WebEngineSettings::UnsupportedInCoreSettings;
diff --git a/src/webenginewidgets/api/qwebenginesettings.h b/src/webenginewidgets/api/qwebenginesettings.h
index 73995a457..4b997f0ac 100644
--- a/src/webenginewidgets/api/qwebenginesettings.h
+++ b/src/webenginewidgets/api/qwebenginesettings.h
@@ -89,7 +89,8 @@ public:
         FocusOnNavigationEnabled,
         PrintElementBackgrounds,
         AllowRunningInsecureContent,
-        AllowGeolocationOnInsecureOrigins
+        AllowGeolocationOnInsecureOrigins,
+        AllowWindowActivationFromJavaScript
     };
 
     enum FontSize {
diff --git a/src/webenginewidgets/doc/src/qwebenginesettings_lgpl.qdoc b/src/webenginewidgets/doc/src/qwebenginesettings_lgpl.qdoc
index efbeb1991..bc841849e 100644
--- a/src/webenginewidgets/doc/src/qwebenginesettings_lgpl.qdoc
+++ b/src/webenginewidgets/doc/src/qwebenginesettings_lgpl.qdoc
@@ -166,6 +166,9 @@
             Geolocation features. This provides an override to allow non secure
             origins to access Geolocation again.
             Disabled by default. (Added in Qt 5.9)
+    \value  AllowWindowActivationFromJavaScript
+            Allows the window.focus() method in JavaScript. Disallowed by default.
+            (Added in Qt 5.10)
 
 */
 
-- 
GitLab