From e8e881ba35fe7009961cbeb4b89efedc5371d5b5 Mon Sep 17 00:00:00 2001 From: Juha Vuolle Date: Tue, 30 Apr 2024 09:41:56 +0300 Subject: [PATCH] macOS: Add support for universal links / https uri scheme handling MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit With this support applications can claim to be handler for specific https URLs. This requires that an appropriate AASA (apple-app-site-association) JSON file is hosted and accessible. One notable usage example is the use of OAuth redirect_uris, which are often required to use "https" URI scheme. [ChangeLog][macOS] Added support for https/universal links handling Task-number: QTBUG-124340 Change-Id: I91c725fcf209b295dc1b2687a52cd0a547aff1c8 Reviewed-by: Tor Arne Vestbø --- .../cocoa/qcocoaapplicationdelegate.mm | 22 +++++++++++++++++++ src/plugins/platforms/cocoa/qcocoaservices.h | 6 +++++ src/plugins/platforms/cocoa/qcocoaservices.mm | 17 ++++++++++++++ 3 files changed, 45 insertions(+) diff --git a/src/plugins/platforms/cocoa/qcocoaapplicationdelegate.mm b/src/plugins/platforms/cocoa/qcocoaapplicationdelegate.mm index d7f8a1665e..10be0fe658 100644 --- a/src/plugins/platforms/cocoa/qcocoaapplicationdelegate.mm +++ b/src/plugins/platforms/cocoa/qcocoaapplicationdelegate.mm @@ -334,6 +334,28 @@ QT_USE_NAMESPACE [self doesNotRecognizeSelector:invocationSelector]; } +- (BOOL)application:(NSApplication *)application continueUserActivity:(NSUserActivity *)userActivity + restorationHandler:(void(^)(NSArray> *restorableObjects))restorationHandler +{ + // Check if eg. user has installed an app delegate capable of handling this + if ([reflectionDelegate respondsToSelector:_cmd] + && [reflectionDelegate application:application continueUserActivity:userActivity + restorationHandler:restorationHandler] == YES) { + return YES; + } + + if (!QGuiApplication::instance()) + return NO; + + if ([userActivity.activityType isEqualToString:NSUserActivityTypeBrowsingWeb]) { + QCocoaIntegration *cocoaIntegration = QCocoaIntegration::instance(); + Q_ASSERT(cocoaIntegration); + return cocoaIntegration->services()->handleUrl(QUrl::fromNSURL(userActivity.webpageURL)); + } + + return NO; +} + - (void)getUrl:(NSAppleEventDescriptor *)event withReplyEvent:(NSAppleEventDescriptor *)replyEvent { Q_UNUSED(replyEvent); diff --git a/src/plugins/platforms/cocoa/qcocoaservices.h b/src/plugins/platforms/cocoa/qcocoaservices.h index a0aec6f16b..b6299570e8 100644 --- a/src/plugins/platforms/cocoa/qcocoaservices.h +++ b/src/plugins/platforms/cocoa/qcocoaservices.h @@ -4,6 +4,8 @@ #ifndef QCOCOADESKTOPSERVICES_H #define QCOCOADESKTOPSERVICES_H +#include + #include QT_BEGIN_NAMESPACE @@ -15,8 +17,12 @@ public: bool openUrl(const QUrl &url) override; bool openDocument(const QUrl &url) override; + bool handleUrl(const QUrl &url); QPlatformServiceColorPicker *colorPicker(QWindow *parent) override; + +private: + QUrl m_handlingUrl; }; QT_END_NAMESPACE diff --git a/src/plugins/platforms/cocoa/qcocoaservices.mm b/src/plugins/platforms/cocoa/qcocoaservices.mm index 4566cbb8f7..87212c265c 100644 --- a/src/plugins/platforms/cocoa/qcocoaservices.mm +++ b/src/plugins/platforms/cocoa/qcocoaservices.mm @@ -8,12 +8,19 @@ #include #include +#include + +#include #include QT_BEGIN_NAMESPACE bool QCocoaServices::openUrl(const QUrl &url) { + // avoid recursing back into self + if (url == m_handlingUrl) + return false; + return [[NSWorkspace sharedWorkspace] openURL:url.toNSURL()]; } @@ -22,6 +29,16 @@ bool QCocoaServices::openDocument(const QUrl &url) return openUrl(url); } +/* Callback from macOS that the application should handle a URL */ +bool QCocoaServices::handleUrl(const QUrl &url) +{ + QScopedValueRollback rollback(m_handlingUrl, url); + // FIXME: Add platform services callback from QDesktopServices::setUrlHandler + // so that we can warn the user if calling setUrlHandler without also setting + // up the matching keys in the Info.plist file (CFBundleURLTypes and friends). + return QDesktopServices::openUrl(url); +} + class QCocoaColorPicker : public QPlatformServiceColorPicker { public: