You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何通过快捷键或命令打开Safari Web Extension弹窗?

如何通过快捷键打开Safari Web Extension的弹窗

针对Safari Web Extension(非App Extension),确实没有内置的快捷键打开弹窗的机制,但可以通过Web脚本+原生扩展Handler的组合实现,以下是完整的实现步骤:

1. 完善Content脚本(监听快捷键)

修改content.js,设置精准的快捷键组合(避免和网页/浏览器默认快捷键冲突):

document.addEventListener('keydown', function(event) {
    // 示例:监听 Ctrl+Shift+O 组合键
    if (event.ctrlKey && event.shiftKey && event.key === 'O') {
        event.preventDefault(); // 阻止默认行为,避免干扰
        browser.runtime.sendMessage({ action: "triggerPopover" }).then((response) => {
            console.log("弹窗打开响应: ", response);
        });
    }
});

2. 调整Background脚本(转发消息到原生)

更新background.js,将消息封装为对象,方便原生端解析:

browser.runtime.onMessage.addListener((request, sender, sendResponse) => {
    if (request.action === "triggerPopover") {
        browser.runtime.sendNativeMessage(
            "com.owner.MyExtension", // 需与原生扩展的Bundle Identifier一致
            { command: "openPopover" }
        ).then((response) => {
            sendResponse({ status: "success", msg: response.echo });
        }).catch((error) => {
            console.error("发送原生消息失败: ", error);
            sendResponse({ status: "error", msg: error.message });
        });
    }
    return true; // 保持端口开放,等待异步响应
});

3. 实现原生Handler(打开弹窗)

补全SafariWebExtensionHandler.swift,通过Safari原生API触发弹窗:

import SafariServices

class SafariWebExtensionHandler: NSObject, NSExtensionRequestHandling {
    func beginRequest(with context: NSExtensionContext) {
        // 解析来自Web扩展的消息
        guard let inputItem = context.inputItems.first as? NSExtensionItem,
              let messageDict = inputItem.userInfo?[SFExtensionMessageKey] as? [String: Any],
              let command = messageDict["command"] as? String,
              command == "openPopover" else {
            context.completeRequest(returningItems: nil, completionHandler: nil)
            return
        }
        
        // 获取当前活跃的Safari窗口、标签页,触发弹窗
        SFSafariApplication.getActiveWindow { window in
            window?.getActiveTab { tab in
                tab?.getToolbarItem { toolbarItem in
                    toolbarItem?.showPopover { error in
                        let responseItem = NSExtensionItem()
                        var responseDict = [String: Any]()
                        
                        if let error = error {
                            responseDict["echo"] = "打开弹窗失败: \(error.localizedDescription)"
                        } else {
                            responseDict["echo"] = "弹窗已打开"
                        }
                        
                        responseItem.userInfo = [SFExtensionMessageKey: responseDict]
                        context.completeRequest(returningItems: [responseItem], completionHandler: nil)
                    }
                }
            }
        }
    }
}

关键注意事项

  • Bundle Identifier一致性:background.js中sendNativeMessage的第一个参数必须和Xcode中原生扩展目标的Bundle Identifier完全一致(比如com.owner.MyExtension)。
  • 权限与启用:确保在Safari偏好设置→扩展中启用你的Web Extension,并赋予必要的网站访问权限。
  • Xcode配置:在原生扩展的Info.plist中,确认NSExtensionPrincipalClass的值指向SafariWebExtensionHandler(格式为$(PRODUCT_MODULE_NAME).SafariWebExtensionHandler)。

内容的提问来源于stack exchange,提问作者Alonso Huerta

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.19 00:20:07