From 49c0ce8403e5caeb864f66553f122c68a7c975fb Mon Sep 17 00:00:00 2001 From: Viktor Engelmann Date: Mon, 3 Jul 2017 15:51:51 +0200 Subject: Add Setting to allow passing unknown URL schemes to QDesktopServices A new enum UnknownUrlSchemePolicy was added to WebEngineSettings, QWebEngineSettings and QQuickWebEngineSettings. WebContentsDelegate now has a new attribute of that type, which can be read and written through the public APIs Q(Quick)WebEngineSettings::unknownUrlSchemeNavigationPolicy and Q(Quick)WebEngineSettings::setUnknownUrlSchemeNavigationPolicy. This way, one can control, whether URLs with unknown schemes are passed to QDesktopServices. WebContentsAdapterClient::navigationRequested is called on these requests, so this allows more fine-grained control over the schemes and origins, that are allowed. Task-number: QTBUG-58627 Change-Id: Ie81d9503456d63ea1ed5606483254acf437cd8f7 Reviewed-by: Allan Sandfeld Jensen --- .../resource_dispatcher_host_delegate_qt.cpp | 10 +++--- src/core/web_contents_delegate_qt.cpp | 41 +++++++++++++++++++--- src/core/web_contents_delegate_qt.h | 2 +- src/core/web_engine_settings.cpp | 18 ++++++++++ src/core/web_engine_settings.h | 12 +++++++ 5 files changed, 71 insertions(+), 12 deletions(-) (limited to 'src/core') diff --git a/src/core/renderer_host/resource_dispatcher_host_delegate_qt.cpp b/src/core/renderer_host/resource_dispatcher_host_delegate_qt.cpp index afc2ea8fa..279a03d42 100644 --- a/src/core/renderer_host/resource_dispatcher_host_delegate_qt.cpp +++ b/src/core/renderer_host/resource_dispatcher_host_delegate_qt.cpp @@ -138,7 +138,7 @@ void ResourceDispatcherHostLoginDelegateQt::destroy() static void LaunchURL(const GURL& url, int render_process_id, const content::ResourceRequestInfo::WebContentsGetter& web_contents_getter, - ui::PageTransition page_transition, bool is_main_frame) + ui::PageTransition page_transition, bool is_main_frame, bool has_user_gesture) { Q_UNUSED(render_process_id); Q_ASSERT(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); @@ -146,16 +146,13 @@ static void LaunchURL(const GURL& url, int render_process_id, if (!webContents) return; WebContentsDelegateQt *contentsDelegate = static_cast(webContents->GetDelegate()); - contentsDelegate->launchExternalURL(toQt(url), page_transition, is_main_frame); + contentsDelegate->launchExternalURL(toQt(url), page_transition, is_main_frame, has_user_gesture); } bool ResourceDispatcherHostDelegateQt::HandleExternalProtocol(const GURL& url, content::ResourceRequestInfo* info) { Q_ASSERT(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO)); - // We don't want to launch external applications unless it is based on a user action - if (!info->HasUserGesture()) - return false; content::BrowserThread::PostTask( content::BrowserThread::UI, @@ -164,7 +161,8 @@ bool ResourceDispatcherHostDelegateQt::HandleExternalProtocol(const GURL& url, c info->GetChildID(), info->GetWebContentsGetterForRequest(), info->GetPageTransition(), - info->IsMainFrame()) + info->IsMainFrame(), + info->HasUserGesture()) ); return true; } diff --git a/src/core/web_contents_delegate_qt.cpp b/src/core/web_contents_delegate_qt.cpp index ad0e7ad6d..31180a1c1 100644 --- a/src/core/web_contents_delegate_qt.cpp +++ b/src/core/web_contents_delegate_qt.cpp @@ -499,14 +499,45 @@ void WebContentsDelegateQt::requestGeolocationPermission(const QUrl &requestingO extern WebContentsAdapterClient::NavigationType pageTransitionToNavigationType(ui::PageTransition transition); -void WebContentsDelegateQt::launchExternalURL(const QUrl &url, ui::PageTransition page_transition, bool is_main_frame) +void WebContentsDelegateQt::launchExternalURL(const QUrl &url, ui::PageTransition page_transition, bool is_main_frame, bool has_user_gesture) { - int navigationRequestAction = WebContentsAdapterClient::AcceptRequest; - m_viewClient->navigationRequested(pageTransitionToNavigationType(page_transition), url, navigationRequestAction, is_main_frame); + WebEngineSettings *settings = m_viewClient->webEngineSettings(); + bool navigationAllowedByPolicy = false; + bool navigationRequestAccepted = true; + + switch (settings->unknownUrlSchemePolicy()) { + case WebEngineSettings::DisallowUnknownUrlSchemes: + break; + case WebEngineSettings::AllowUnknownUrlSchemesFromUserInteraction: + navigationAllowedByPolicy = has_user_gesture; + break; + case WebEngineSettings::AllowAllUnknownUrlSchemes: + navigationAllowedByPolicy = true; + break; + default: + Q_UNREACHABLE(); + } + + if (navigationAllowedByPolicy) { + int navigationRequestAction = WebContentsAdapterClient::AcceptRequest; + m_viewClient->navigationRequested(pageTransitionToNavigationType(page_transition), url, navigationRequestAction, is_main_frame); + navigationRequestAccepted = navigationRequestAction == WebContentsAdapterClient::AcceptRequest; #ifndef QT_NO_DESKTOPSERVICES - if (navigationRequestAction == WebContentsAdapterClient::AcceptRequest) - QDesktopServices::openUrl(url); + if (navigationRequestAccepted) + QDesktopServices::openUrl(url); #endif + } + + if (!navigationAllowedByPolicy || !navigationRequestAccepted) { + if (!navigationAllowedByPolicy) + didFailLoad(url, 420, QStringLiteral("Launching external protocol forbidden by WebEngineSettings::UnknownUrlSchemePolicy")); + else + didFailLoad(url, 420, QStringLiteral("Launching external protocol suppressed by WebContentsAdapterClient::navigationRequested")); + if (settings->testAttribute(WebEngineSettings::ErrorPageEnabled)) { + EmitLoadStarted(toQt(GURL(content::kUnreachableWebDataURL)), true); + m_viewClient->webContentsAdapter()->load(toQt(GURL(content::kUnreachableWebDataURL))); + } + } } void WebContentsDelegateQt::ShowValidationMessage(content::WebContents *web_contents, const gfx::Rect &anchor_in_root_view, const base::string16 &main_text, const base::string16 &sub_text) diff --git a/src/core/web_contents_delegate_qt.h b/src/core/web_contents_delegate_qt.h index 2e37c498a..dab693780 100644 --- a/src/core/web_contents_delegate_qt.h +++ b/src/core/web_contents_delegate_qt.h @@ -142,7 +142,7 @@ public: void overrideWebPreferences(content::WebContents *, content::WebPreferences*); void allowCertificateError(const QSharedPointer &) ; void requestGeolocationPermission(const QUrl &requestingOrigin); - void launchExternalURL(const QUrl &url, ui::PageTransition page_transition, bool is_main_frame); + void launchExternalURL(const QUrl &url, ui::PageTransition page_transition, bool is_main_frame, bool has_user_gesture); FaviconManager *faviconManager(); void setSavePageInfo(const SavePageInfo &spi) { m_savePageInfo = spi; } diff --git a/src/core/web_engine_settings.cpp b/src/core/web_engine_settings.cpp index 4c944892a..7b9c1225d 100644 --- a/src/core/web_engine_settings.cpp +++ b/src/core/web_engine_settings.cpp @@ -110,6 +110,7 @@ WebEngineSettings::WebEngineSettings(WebEngineSettings *_parentSettings) : m_adapter(0) , m_batchTimer(new BatchTimer(this)) , parentSettings(_parentSettings) + , m_unknownUrlSchemePolicy(WebEngineSettings::InheritedUnknownUrlSchemePolicy) { if (parentSettings) parentSettings->childSettings.insert(this); @@ -212,6 +213,22 @@ QString WebEngineSettings::defaultTextEncoding() const return m_defaultEncoding.isEmpty()? parentSettings->defaultTextEncoding() : m_defaultEncoding; } +void WebEngineSettings::setUnknownUrlSchemePolicy(WebEngineSettings::UnknownUrlSchemePolicy policy) +{ + m_unknownUrlSchemePolicy = policy; +} + +WebEngineSettings::UnknownUrlSchemePolicy WebEngineSettings::unknownUrlSchemePolicy() const +{ + // value InheritedUnknownUrlSchemePolicy means it is taken from parent, if possible. If there + // is no parent, then AllowUnknownUrlSchemesFromUserInteraction (the default behavior) is used. + if (m_unknownUrlSchemePolicy != InheritedUnknownUrlSchemePolicy) + return m_unknownUrlSchemePolicy; + if (parentSettings) + return parentSettings->unknownUrlSchemePolicy(); + return AllowUnknownUrlSchemesFromUserInteraction; +} + void WebEngineSettings::initDefaults() { if (s_defaultAttributes.isEmpty()) { @@ -284,6 +301,7 @@ void WebEngineSettings::initDefaults() } m_defaultEncoding = QStringLiteral("ISO-8859-1"); + m_unknownUrlSchemePolicy = InheritedUnknownUrlSchemePolicy; } void WebEngineSettings::scheduleApply() diff --git a/src/core/web_engine_settings.h b/src/core/web_engine_settings.h index 639d314f3..d4c5e02a8 100644 --- a/src/core/web_engine_settings.h +++ b/src/core/web_engine_settings.h @@ -107,6 +107,14 @@ public: DefaultFixedFontSize }; + // Must match the values from the public API in qwebenginesettings.h. + enum UnknownUrlSchemePolicy { + InheritedUnknownUrlSchemePolicy = 0, + DisallowUnknownUrlSchemes = 1, + AllowUnknownUrlSchemesFromUserInteraction, + AllowAllUnknownUrlSchemes + }; + explicit WebEngineSettings(WebEngineSettings *parentSettings = 0); ~WebEngineSettings(); @@ -129,6 +137,9 @@ public: void setDefaultTextEncoding(const QString &encoding); QString defaultTextEncoding() const; + void setUnknownUrlSchemePolicy(UnknownUrlSchemePolicy policy); + UnknownUrlSchemePolicy unknownUrlSchemePolicy() const; + void initDefaults(); void scheduleApply(); @@ -155,6 +166,7 @@ private: static QHash s_defaultAttributes; static QHash s_defaultFontFamilies; static QHash s_defaultFontSizes; + UnknownUrlSchemePolicy m_unknownUrlSchemePolicy; friend class BatchTimer; friend class WebContentsAdapter; -- cgit v1.2.3