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 ¶ms) 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