| 218 | // 所以service_worker与offscreen使用ServiceWorker的方式进行通信 |
| 219 | // 现在同时支持接收来自offscreen的请求(实现完整Message接口),使双向通道都走postMessage(结构化克隆,支持Blob) |
| 220 | export class ServiceWorkerMessageSend implements Message { |
| 221 | EE = new EventEmitter<string, any>(); |
| 222 | |
| 223 | private target: PostMessage | undefined = undefined; |
| 224 | |
| 225 | constructor() { |
| 226 | // 在构造函数中设置监听,确保能接收来自offscreen的请求 |
| 227 | self.addEventListener("message", (e: MessageEvent) => { |
| 228 | this.messageHandle(e.data, e.source as PostMessage); |
| 229 | }); |
| 230 | } |
| 231 | |
| 232 | async init() { |
| 233 | if (!this.target && self.clients) { |
| 234 | const list = await self.clients.matchAll({ includeUncontrolled: true, type: "window" }); |
| 235 | // 找到offscreen.html窗口 |
| 236 | this.target = list.find((client) => client.url == chrome.runtime.getURL("src/offscreen.html")) as PostMessage; |
| 237 | } |
| 238 | } |
| 239 | |
| 240 | messageHandle(data: WindowMessageBody, source?: PostMessage) { |
| 241 | // 处理消息 |
| 242 | if (data.type === "sendMessage" && source) { |
| 243 | // 接收到来自offscreen的请求消息 |
| 244 | // 第三个参数传空对象作为sender,避免Server中SenderRuntime访问undefined属性 |
| 245 | // 空对象经过getExtMessageSender()会得到tabId=-1等值,表示后台脚本 |
| 246 | this.EE.emit( |
| 247 | "message", |
| 248 | data.data, |
| 249 | (resp: any) => { |
| 250 | if (!data.messageId) { |
| 251 | return; |
| 252 | } |
| 253 | const body: WindowMessageBody = { |
| 254 | messageId: data.messageId, |
| 255 | type: "respMessage", |
| 256 | data: resp, |
| 257 | }; |
| 258 | source.postMessage(body); |
| 259 | }, |
| 260 | {} as RuntimeMessageSender |
| 261 | ); |
| 262 | } else if (data.type === "connect" && source) { |
| 263 | // 接收到来自offscreen的连接请求 |
| 264 | this.EE.emit("connect", data.data, new WindowMessageConnect(data.messageId, this.EE, source)); |
| 265 | } else if (data.type === "respMessage") { |
| 266 | // 接收到响应消息 |
| 267 | this.EE.emit(`response:${data.messageId}`, data); |
| 268 | } else if (data.type === "disconnect") { |
| 269 | this.EE.emit(`disconnect:${data.messageId}`); |
| 270 | } else if (data.type === "connectMessage") { |
| 271 | this.EE.emit(`connectMessage:${data.messageId}`, data.data); |
| 272 | } |
| 273 | } |
| 274 | |
| 275 | onMessage(callback: OnMessageCallback): void { |
| 276 | this.EE.addListener("message", callback); |
| 277 | } |
nothing calls this directly
no outgoing calls
no test coverage detected