如何实现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
相关产品推荐
相关产品推荐

