From bfdf3ce774adceedbecd6e6e8c6e482114d20343 Mon Sep 17 00:00:00 2001 From: Harry Twyford Date: Tue, 2 Nov 2021 18:08:08 +0000 Subject: [PATCH] Bug 1525788 - Support sending Handoff. r=mstange,Gijs Differential Revision: https://phabricator.services.mozilla.com/D129406 --- browser/base/content/browser.js | 36 +++++++++++++++ widget/cocoa/moz.build | 1 + widget/cocoa/nsCocoaWindow.mm | 1 + widget/cocoa/nsMacSharingService.mm | 1 + widget/cocoa/nsMacUserActivityUpdater.h | 23 +++++++++ widget/cocoa/nsMacUserActivityUpdater.mm | 59 ++++++++++++++++++++++++ widget/cocoa/nsWidgetFactory.mm | 6 +++ widget/moz.build | 1 + widget/nsIMacUserActivityUpdater.idl | 24 ++++++++++ widget/nsWidgetsCID.h | 8 ++++ 10 files changed, 160 insertions(+) create mode 100644 widget/cocoa/nsMacUserActivityUpdater.h create mode 100644 widget/cocoa/nsMacUserActivityUpdater.mm create mode 100644 widget/nsIMacUserActivityUpdater.idl diff --git a/browser/base/content/browser.js b/browser/base/content/browser.js index fa6355844337..a0a2827f1d38 100644 --- a/browser/base/content/browser.js +++ b/browser/base/content/browser.js @@ -445,6 +445,16 @@ XPCOMUtils.defineLazyGetter(this, "PopupNotifications", () => { } }); +XPCOMUtils.defineLazyGetter(this, "MacUserActivityUpdater", () => { + if (AppConstants.platform != "macosx") { + return null; + } + + return Cc["@mozilla.org/widget/macuseractivityupdater;1"].getService( + Ci.nsIMacUserActivityUpdater + ); +}); + XPCOMUtils.defineLazyGetter(this, "Win7Features", () => { if (AppConstants.platform != "win") { return null; @@ -5468,6 +5478,8 @@ var XULBrowserWindow = { this._updateElementsForContentType(); + this._updateMacUserActivity(window, aLocationURI, aWebProgress); + // Unconditionally disable the Text Encoding button during load to // keep the UI calm when navigating from one modern page to another and // the toolbar button is visible. @@ -5561,6 +5573,30 @@ var XULBrowserWindow = { } }, + /** + * Updates macOS platform code with the current URI and page title. + * From there, we update the current NSUserActivity, enabling Handoff to other + * Apple devices. + * @param {Window} window + * The window in which the navigation occurred. + * @param {nsIURI} uri + * The URI pointing to the current page. + * @param {nsIWebProgress} webProgress + * The nsIWebProgress instance that fired a onLocationChange notification. + */ + _updateMacUserActivity(win, uri, webProgress) { + if (!webProgress.isTopLevel || AppConstants.platform != "macosx") { + return; + } + + let baseWin = win.docShell.treeOwner.QueryInterface(Ci.nsIBaseWindow); + MacUserActivityUpdater.updateLocation( + uri.spec, + win.gBrowser.contentTitle, + baseWin + ); + }, + asyncUpdateUI() { BrowserSearch.updateOpenSearchBadge(); }, diff --git a/widget/cocoa/moz.build b/widget/cocoa/moz.build index f4cf072b530f..fcb202e6f77a 100644 --- a/widget/cocoa/moz.build +++ b/widget/cocoa/moz.build @@ -56,6 +56,7 @@ UNIFIED_SOURCES += [ "nsMacDockSupport.mm", "nsMacFinderProgress.mm", "nsMacSharingService.mm", + "nsMacUserActivityUpdater.mm", "nsMacWebAppUtils.mm", "nsMenuBarX.mm", "nsMenuGroupOwnerX.mm", diff --git a/widget/cocoa/nsCocoaWindow.mm b/widget/cocoa/nsCocoaWindow.mm index 4ed4b7e88e54..e08c196e17a2 100644 --- a/widget/cocoa/nsCocoaWindow.mm +++ b/widget/cocoa/nsCocoaWindow.mm @@ -10,6 +10,7 @@ #include "NativeKeyBindings.h" #include "ScreenHelperCocoa.h" #include "TextInputHandler.h" +#include "nsCocoaUtils.h" #include "nsObjCExceptions.h" #include "nsCOMPtr.h" #include "nsWidgetsCID.h" diff --git a/widget/cocoa/nsMacSharingService.mm b/widget/cocoa/nsMacSharingService.mm index f9c64fd1db7a..aa24a2473f9a 100644 --- a/widget/cocoa/nsMacSharingService.mm +++ b/widget/cocoa/nsMacSharingService.mm @@ -178,6 +178,7 @@ nsMacSharingService::ShareUrl(const nsAString& aServiceName, const nsAString& aP if ([pageUrl.scheme hasPrefix:@"http"]) { [shareActivity setWebpageURL:pageUrl]; } + [shareActivity setEligibleForHandoff:NO]; [shareActivity setTitle:pageTitle]; [shareActivity becomeCurrent]; diff --git a/widget/cocoa/nsMacUserActivityUpdater.h b/widget/cocoa/nsMacUserActivityUpdater.h new file mode 100644 index 000000000000..6870a6634375 --- /dev/null +++ b/widget/cocoa/nsMacUserActivityUpdater.h @@ -0,0 +1,23 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#ifndef nsMacUserActivityUpdater_h_ +#define nsMacUserActivityUpdater_h_ + +#include "nsIMacUserActivityUpdater.h" +#include "nsCocoaWindow.h" + +class nsMacUserActivityUpdater : public nsIMacUserActivityUpdater { + public: + nsMacUserActivityUpdater() {} + + NS_DECL_ISUPPORTS + NS_DECL_NSIMACUSERACTIVITYUPDATER + + protected: + virtual ~nsMacUserActivityUpdater() {} + BaseWindow* GetCocoaWindow(nsIBaseWindow* aWindow); +}; + +#endif // nsMacUserActivityUpdater_h_ diff --git a/widget/cocoa/nsMacUserActivityUpdater.mm b/widget/cocoa/nsMacUserActivityUpdater.mm new file mode 100644 index 000000000000..989001f1a3a6 --- /dev/null +++ b/widget/cocoa/nsMacUserActivityUpdater.mm @@ -0,0 +1,59 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#import + +#include "nsMacUserActivityUpdater.h" + +#include "nsCocoaUtils.h" +#include "nsIBaseWindow.h" + +NSString* const kBrowsingActivityType = @"com.mozilla.firefox.handoff.webpage"; + +NS_IMPL_ISUPPORTS(nsMacUserActivityUpdater, nsIMacUserActivityUpdater) + +NS_IMETHODIMP +nsMacUserActivityUpdater::UpdateLocation(const nsAString& aPageUrl, const nsAString& aPageTitle, + nsIBaseWindow* aWindow) { + NS_OBJC_BEGIN_TRY_BLOCK_RETURN; + BaseWindow* cocoaWin = nsMacUserActivityUpdater::GetCocoaWindow(aWindow); + if (!cocoaWin) { + return NS_ERROR_FAILURE; + } + + NSURL* pageUrl = nsCocoaUtils::ToNSURL(aPageUrl); + if (![pageUrl.scheme isEqualToString:@"https"] && ![pageUrl.scheme isEqualToString:@"http"]) { + [cocoaWin.userActivity invalidate]; + return NS_OK; + } + + NSString* pageTitle = nsCocoaUtils::ToNSString(aPageTitle); + if (!pageTitle) { + pageTitle = pageUrl.absoluteString; + } + + NSUserActivity* userActivity = + [[NSUserActivity alloc] initWithActivityType:kBrowsingActivityType]; + userActivity.webpageURL = pageUrl; + userActivity.title = pageTitle; + cocoaWin.userActivity = userActivity; + [userActivity release]; + + return NS_OK; + + NS_OBJC_END_TRY_BLOCK_RETURN(NS_ERROR_FAILURE); +} + +BaseWindow* nsMacUserActivityUpdater::GetCocoaWindow(nsIBaseWindow* aWindow) { + nsCOMPtr widget = nullptr; + aWindow->GetMainWidget(getter_AddRefs(widget)); + if (!widget) { + return nil; + } + BaseWindow* cocoaWin = (BaseWindow*)widget->GetNativeData(NS_NATIVE_WINDOW); + if (!cocoaWin) { + return nil; + } + return cocoaWin; +} diff --git a/widget/cocoa/nsWidgetFactory.mm b/widget/cocoa/nsWidgetFactory.mm index 9e0cd7c75193..6e76c4ec87dd 100644 --- a/widget/cocoa/nsWidgetFactory.mm +++ b/widget/cocoa/nsWidgetFactory.mm @@ -80,6 +80,9 @@ NS_GENERIC_FACTORY_CONSTRUCTOR(nsMacFinderProgress) #include "nsMacSharingService.h" NS_GENERIC_FACTORY_CONSTRUCTOR(nsMacSharingService) +#include "nsMacUserActivityUpdater.h" +NS_GENERIC_FACTORY_CONSTRUCTOR(nsMacUserActivityUpdater) + #include "nsMacWebAppUtils.h" NS_GENERIC_FACTORY_CONSTRUCTOR(nsMacWebAppUtils) @@ -111,6 +114,7 @@ NS_DEFINE_NAMED_CID(NS_SYSTEMALERTSSERVICE_CID); NS_DEFINE_NAMED_CID(NS_MACDOCKSUPPORT_CID); NS_DEFINE_NAMED_CID(NS_MACFINDERPROGRESS_CID); NS_DEFINE_NAMED_CID(NS_MACSHARINGSERVICE_CID); +NS_DEFINE_NAMED_CID(NS_MACUSERACTIVITYUPDATER_CID); NS_DEFINE_NAMED_CID(NS_MACWEBAPPUTILS_CID); NS_DEFINE_NAMED_CID(NS_STANDALONENATIVEMENU_CID); NS_DEFINE_NAMED_CID(NS_SYSTEMSTATUSBAR_CID); @@ -141,6 +145,7 @@ static const mozilla::Module::CIDEntry kWidgetCIDs[] = { {&kNS_MACDOCKSUPPORT_CID, false, NULL, nsMacDockSupportConstructor}, {&kNS_MACFINDERPROGRESS_CID, false, NULL, nsMacFinderProgressConstructor}, {&kNS_MACSHARINGSERVICE_CID, false, NULL, nsMacSharingServiceConstructor}, + {&kNS_MACUSERACTIVITYUPDATER_CID, false, NULL, nsMacUserActivityUpdaterConstructor}, {&kNS_MACWEBAPPUTILS_CID, false, NULL, nsMacWebAppUtilsConstructor}, {&kNS_STANDALONENATIVEMENU_CID, false, NULL, nsStandaloneNativeMenuConstructor}, {&kNS_SYSTEMSTATUSBAR_CID, false, NULL, nsSystemStatusBarCocoaConstructor}, @@ -169,6 +174,7 @@ static const mozilla::Module::ContractIDEntry kWidgetContracts[] = { {"@mozilla.org/widget/macdocksupport;1", &kNS_MACDOCKSUPPORT_CID}, {"@mozilla.org/widget/macfinderprogress;1", &kNS_MACFINDERPROGRESS_CID}, {"@mozilla.org/widget/macsharingservice;1", &kNS_MACSHARINGSERVICE_CID}, + {"@mozilla.org/widget/macuseractivityupdater;1", &kNS_MACUSERACTIVITYUPDATER_CID}, {"@mozilla.org/widget/mac-web-app-utils;1", &kNS_MACWEBAPPUTILS_CID}, {"@mozilla.org/widget/standalonenativemenu;1", &kNS_STANDALONENATIVEMENU_CID}, {"@mozilla.org/widget/systemstatusbar;1", &kNS_SYSTEMSTATUSBAR_CID}, diff --git a/widget/moz.build b/widget/moz.build index 4724d667d8ac..bd95a2377e0e 100644 --- a/widget/moz.build +++ b/widget/moz.build @@ -41,6 +41,7 @@ if toolkit == "cocoa": "nsIMacDockSupport.idl", "nsIMacFinderProgress.idl", "nsIMacSharingService.idl", + "nsIMacUserActivityUpdater.idl", "nsIMacWebAppUtils.idl", "nsIStandaloneNativeMenu.idl", "nsITaskbarProgress.idl", diff --git a/widget/nsIMacUserActivityUpdater.idl b/widget/nsIMacUserActivityUpdater.idl new file mode 100644 index 000000000000..c5de948a4320 --- /dev/null +++ b/widget/nsIMacUserActivityUpdater.idl @@ -0,0 +1,24 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include "nsISupports.idl" + +interface nsIBaseWindow; + +/** + * Updates macOS widget code with the current URI and page title. Widget code + * can use this information to update NSUserActivity, enabling Handoff + * functionality. + */ + +[scriptable, uuid(29046c8f-cba6-4ffa-9141-1685e96c4ea0)] +interface nsIMacUserActivityUpdater : nsISupports +{ + /** + * Update active URL and page title for the given window. + */ + void updateLocation(in AString pageUrl, + in AString pageTitle, + in nsIBaseWindow window); +}; diff --git a/widget/nsWidgetsCID.h b/widget/nsWidgetsCID.h index 8a295823b0eb..5a632e26124f 100644 --- a/widget/nsWidgetsCID.h +++ b/widget/nsWidgetsCID.h @@ -106,6 +106,14 @@ } \ } +// {29046c8f-cba6-4ffa-9141-1685e96c4ea0} +#define NS_MACUSERACTIVITYUPDATER_CID \ + { \ + 0x29046c8f, 0xcba6, 0x4ffa, { \ + 0x91, 0x41, 0x16, 0x85, 0xe9, 0x6c, 0x4e, 0xa0 \ + } \ + } + // {b6e1a890-b2b8-4883-a65f-9476f6185313} #define NS_SYSTEMSTATUSBAR_CID \ { \