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

如何实现Safari Web Extension background页向原生App发消息并在原生端接收

原生端接收消息的实现方案

你需要在原生项目的SFSafariExtensionHandler子类中实现指定的代理方法,即可接收background.js通过port.postMessage发送的消息,Objective-C实现示例如下:

1. 头文件(MyExtensionHandler.h)

#import <SafariServices/SafariServices.h>

@interface MyExtensionHandler : SFSafariExtensionHandler
@end

2. 实现文件(MyExtensionHandler.m)

#import "MyExtensionHandler.h"
#import <os/log.h>

@implementation MyExtensionHandler

/// 接收Safari扩展发来的所有消息的入口方法
- (void)messageReceivedWithName:(NSString *)messageName
                       fromPage:(SFSafariPage *)page
                       userInfo:(NSDictionary<NSString *, id> *)userInfo {
    // 输出日志排查问题
    os_log(.default, "收到扩展消息:名称=%@, 参数=%@", messageName, userInfo);
    
    // 匹配消息类型,处理签名请求
    if ([messageName isEqualToString:@"requestSign"]) {
        // 取出待签名数据
        NSString *originData = userInfo[@"dataToSign"];
        // 调用你的USB密钥签名逻辑,生成签名值
        NSString *signature = [self getSignFromUSBKey:originData];
        
        // 把签名结果回传给background页面
        [page dispatchMessageToScriptWithName:@"signResponse" 
                                     userInfo:@{@"signature": signature} 
                            completionHandler:^(NSError * _Nullable error) {
            if (error) {
                os_log(.error, "回传签名结果失败:%@", error.localizedDescription);
            }
        }];
    }
}

/// 替换为你的实际USB密钥签名逻辑
- (NSString *)getSignFromUSBKey:(NSString *)data {
    // 这里写调用USB硬件生成签名的代码
    return @"实际生成的签名值";
}

@end

配套的background.js发送示例

为了方便传参,推荐发送JSON格式消息,而不是纯字符串:

// 发送签名请求
port.postMessage({
  message: "requestSign",
  dataToSign: "需要被USB密钥签名的原始数据"
});

// 接收原生返回的签名结果
port.onMessage.addListener(function(message) {
    if (message.message === "signResponse") {
        console.log("拿到签名值:", message.signature);
    }
});

注意事项

  • 确保你的Xcode项目中已经正确配置了Safari扩展的目标,且SFSafariExtensionHandler子类已经在扩展的Info.plist中被指定为 principal class
  • port.postMessage传入对象时,对象的message属性值会作为原生端收到的messageName,其余属性会被放入userInfo参数中
  • 纯字符串作为参数调用postMessage时,该字符串会直接作为原生端的messageName,userInfo为空

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.28 13:24:05