From 6dcd08546d50fbb0ac389b4ef2abcde883e62fe1 Mon Sep 17 00:00:00 2001 From: Leendert de Borst Date: Sun, 12 Jul 2026 16:58:37 +0200 Subject: [PATCH] Show keyboard shortcuts button in Safari browser extension (#2257) --- .../SafariWebExtensionHandler.swift | 28 +++++++++++++++++++ .../popup/pages/settings/Settings.tsx | 8 ++++++ apps/browser-extension/wxt.config.ts | 5 ++++ 3 files changed, 41 insertions(+) diff --git a/apps/browser-extension/safari-xcode/AliasVault Extension/SafariWebExtensionHandler.swift b/apps/browser-extension/safari-xcode/AliasVault Extension/SafariWebExtensionHandler.swift index ab89c7ff8..72655d202 100644 --- a/apps/browser-extension/safari-xcode/AliasVault Extension/SafariWebExtensionHandler.swift +++ b/apps/browser-extension/safari-xcode/AliasVault Extension/SafariWebExtensionHandler.swift @@ -22,6 +22,12 @@ class SafariWebExtensionHandler: NSObject, NSExtensionRequestHandling { os_log(.default, "Received message from browser.runtime.sendNativeMessage: %@ (profile: %@)", String(describing: message), profile?.uuidString ?? "none") + if let messageDict = message as? [String: Any], + messageDict["action"] as? String == "openShortcutSettings" { + openShortcutSettings(context: context) + return + } + let response = NSExtensionItem() if #available(iOS 15.0, macOS 11.0, *) { response.userInfo = [ SFExtensionMessageKey: [ "echo": message ] ] @@ -32,4 +38,26 @@ class SafariWebExtensionHandler: NSObject, NSExtensionRequestHandling { context.completeRequest(returningItems: [ response ], completionHandler: nil) } + /// Open Safari Settings → Extensions for this extension, which lists its keyboard shortcuts. + private func openShortcutSettings(context: NSExtensionContext) { + var success = false + #if os(macOS) + let identifier = Bundle.main.bundleIdentifier ?? "net.aliasvault.safari.extension" + SFSafariApplication.showPreferencesForExtension(withIdentifier: identifier) { error in + if let error = error { + os_log(.error, "Failed to open Safari extension preferences: %@", error.localizedDescription) + } + } + success = true + #endif + + let response = NSExtensionItem() + if #available(iOS 15.0, macOS 11.0, *) { + response.userInfo = [ SFExtensionMessageKey: [ "success": success ] ] + } else { + response.userInfo = [ "message": [ "success": success ] ] + } + context.completeRequest(returningItems: [ response ], completionHandler: nil) + } + } diff --git a/apps/browser-extension/src/entrypoints/popup/pages/settings/Settings.tsx b/apps/browser-extension/src/entrypoints/popup/pages/settings/Settings.tsx index 0631d8824..159f18d49 100644 --- a/apps/browser-extension/src/entrypoints/popup/pages/settings/Settings.tsx +++ b/apps/browser-extension/src/entrypoints/popup/pages/settings/Settings.tsx @@ -116,6 +116,14 @@ const Settings: React.FC = () => { } } + if (import.meta.env.SAFARI) { + // The native SafariWebExtensionHandler opens Safari Settings → Extensions for this extension. + return async (): Promise => { + await browser.runtime.sendNativeMessage('application.id', { action: 'openShortcutSettings' }); + window.close(); + }; + } + return null; })(); diff --git a/apps/browser-extension/wxt.config.ts b/apps/browser-extension/wxt.config.ts index 2024b1f1b..759fa8e70 100644 --- a/apps/browser-extension/wxt.config.ts +++ b/apps/browser-extension/wxt.config.ts @@ -47,6 +47,11 @@ export default defineConfig({ permissions.push("offscreen"); } + // Safari: allow messaging the native app (e.g. to open Safari's extension shortcut settings) + if (browser === 'safari') { + permissions.push("nativeMessaging"); + } + return { name: "AliasVault", description: "AliasVault Browser AutoFill Extension. Keeping your personal information private.",