Target messages to only the interested ports (#7301)
This commit is contained in:
parent
062a3ce2d2
commit
bbdf704763
|
@ -25,20 +25,23 @@ export class BackgroundMemoryStorageService extends MemoryStorageService {
|
||||||
});
|
});
|
||||||
port.onMessage.addListener(listenerCallback);
|
port.onMessage.addListener(listenerCallback);
|
||||||
// Initialize the new memory storage service with existing data
|
// Initialize the new memory storage service with existing data
|
||||||
this.sendMessage({
|
this.sendMessageTo(port, {
|
||||||
action: "initialization",
|
action: "initialization",
|
||||||
data: Array.from(this.store.keys()),
|
data: Array.from(this.store.keys()),
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
this.updates$.subscribe((update) => {
|
this.updates$.subscribe((update) => {
|
||||||
this.sendMessage({
|
this.broadcastMessage({
|
||||||
action: "subject_update",
|
action: "subject_update",
|
||||||
data: update,
|
data: update,
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private async onMessageFromForeground(message: MemoryStoragePortMessage) {
|
private async onMessageFromForeground(
|
||||||
|
message: MemoryStoragePortMessage,
|
||||||
|
port: chrome.runtime.Port,
|
||||||
|
) {
|
||||||
if (message.originator === "background") {
|
if (message.originator === "background") {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -60,19 +63,26 @@ export class BackgroundMemoryStorageService extends MemoryStorageService {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.sendMessage({
|
this.sendMessageTo(port, {
|
||||||
id: message.id,
|
id: message.id,
|
||||||
key: message.key,
|
key: message.key,
|
||||||
data: JSON.stringify(result),
|
data: JSON.stringify(result),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private async sendMessage(data: Omit<MemoryStoragePortMessage, "originator">) {
|
private broadcastMessage(data: Omit<MemoryStoragePortMessage, "originator">) {
|
||||||
this._ports.forEach((port) => {
|
this._ports.forEach((port) => {
|
||||||
|
this.sendMessageTo(port, data);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private sendMessageTo(
|
||||||
|
port: chrome.runtime.Port,
|
||||||
|
data: Omit<MemoryStoragePortMessage, "originator">,
|
||||||
|
) {
|
||||||
port.postMessage({
|
port.postMessage({
|
||||||
...data,
|
...data,
|
||||||
originator: "background",
|
originator: "background",
|
||||||
});
|
});
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,15 +7,14 @@ import { trackEmissions } from "@bitwarden/common/../spec/utils";
|
||||||
|
|
||||||
import { BackgroundMemoryStorageService } from "./background-memory-storage.service";
|
import { BackgroundMemoryStorageService } from "./background-memory-storage.service";
|
||||||
import { ForegroundMemoryStorageService } from "./foreground-memory-storage.service";
|
import { ForegroundMemoryStorageService } from "./foreground-memory-storage.service";
|
||||||
import { mockPort } from "./mock-port.spec-util";
|
import { mockPorts } from "./mock-ports.spec-util";
|
||||||
import { portName } from "./port-name";
|
|
||||||
|
|
||||||
describe("foreground background memory storage interaction", () => {
|
describe("foreground background memory storage interaction", () => {
|
||||||
let foreground: ForegroundMemoryStorageService;
|
let foreground: ForegroundMemoryStorageService;
|
||||||
let background: BackgroundMemoryStorageService;
|
let background: BackgroundMemoryStorageService;
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
mockPort(portName(chrome.storage.session));
|
mockPorts();
|
||||||
|
|
||||||
background = new BackgroundMemoryStorageService();
|
background = new BackgroundMemoryStorageService();
|
||||||
foreground = new ForegroundMemoryStorageService();
|
foreground = new ForegroundMemoryStorageService();
|
||||||
|
@ -63,4 +62,16 @@ describe("foreground background memory storage interaction", () => {
|
||||||
|
|
||||||
expect(emissions).toEqual([{ key, updateType }]);
|
expect(emissions).toEqual([{ key, updateType }]);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test("background should message only the requesting foreground", async () => {
|
||||||
|
const secondForeground = new ForegroundMemoryStorageService();
|
||||||
|
const secondPort = secondForeground["_port"];
|
||||||
|
const secondPost = secondPort.postMessage as jest.Mock;
|
||||||
|
secondPost.mockClear();
|
||||||
|
|
||||||
|
const key = "key";
|
||||||
|
await foreground.get(key);
|
||||||
|
|
||||||
|
expect(secondPost).not.toHaveBeenCalled();
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,25 +0,0 @@
|
||||||
import { mockDeep } from "jest-mock-extended";
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Mocks a chrome.runtime.Port set up to send messages through `postMessage` to `onMessage.addListener` callbacks.
|
|
||||||
* @returns a mock chrome.runtime.Port
|
|
||||||
*/
|
|
||||||
export function mockPort(name: string) {
|
|
||||||
const port = mockDeep<chrome.runtime.Port>();
|
|
||||||
// notify listeners of a new port
|
|
||||||
(chrome.runtime.connect as jest.Mock).mockImplementation((portInfo) => {
|
|
||||||
port.name = portInfo.name;
|
|
||||||
(chrome.runtime.onConnect.addListener as jest.Mock).mock.calls.forEach(([callbackFn]) => {
|
|
||||||
callbackFn(port);
|
|
||||||
});
|
|
||||||
return port;
|
|
||||||
});
|
|
||||||
|
|
||||||
// set message broadcast
|
|
||||||
(port.postMessage as jest.Mock).mockImplementation((message) => {
|
|
||||||
(port.onMessage.addListener as jest.Mock).mock.calls.forEach(([callbackFn]) => {
|
|
||||||
callbackFn(message);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
return port;
|
|
||||||
}
|
|
|
@ -0,0 +1,29 @@
|
||||||
|
import { mockDeep } from "jest-mock-extended";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Mocks a chrome.runtime.Port set up to send messages through `postMessage` to `onMessage.addListener` callbacks.
|
||||||
|
* @param name - The name of the port.
|
||||||
|
* @param immediateOnConnectExecution - Whether to immediately execute the onConnect callbacks against the new port.
|
||||||
|
* Defaults to false. If true, the creator of the port will not have had a chance to set up listeners yet.
|
||||||
|
* @returns a mock chrome.runtime.Port
|
||||||
|
*/
|
||||||
|
export function mockPorts() {
|
||||||
|
// notify listeners of a new port
|
||||||
|
(chrome.runtime.connect as jest.Mock).mockImplementation((portInfo) => {
|
||||||
|
const port = mockDeep<chrome.runtime.Port>();
|
||||||
|
port.name = portInfo.name;
|
||||||
|
|
||||||
|
// set message broadcast
|
||||||
|
(port.postMessage as jest.Mock).mockImplementation((message) => {
|
||||||
|
(port.onMessage.addListener as jest.Mock).mock.calls.forEach(([callbackFn]) => {
|
||||||
|
callbackFn(message, port);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
(chrome.runtime.onConnect.addListener as jest.Mock).mock.calls.forEach(([callbackFn]) => {
|
||||||
|
callbackFn(port);
|
||||||
|
});
|
||||||
|
|
||||||
|
return port;
|
||||||
|
});
|
||||||
|
}
|
Loading…
Reference in New Issue