mirror of
https://github.com/bitwarden/browser
synced 2026-02-04 10:43:47 +00:00
Improve Autofill IPC reliability (#14358)
* Delay IPC server start * Better ipc handling * Rename ready() to listenerReady() --------- Co-authored-by: Daniel García <dani-garcia@users.noreply.github.com>
This commit is contained in:
@@ -9,6 +9,8 @@ export default {
|
||||
runCommand: <C extends Command>(params: RunCommandParams<C>): Promise<RunCommandResult<C>> =>
|
||||
ipcRenderer.invoke("autofill.runCommand", params),
|
||||
|
||||
listenerReady: () => ipcRenderer.send("autofill.listenerReady"),
|
||||
|
||||
listenPasskeyRegistration: (
|
||||
fn: (
|
||||
clientId: number,
|
||||
|
||||
@@ -296,6 +296,8 @@ export class DesktopAutofillService implements OnDestroy {
|
||||
await this.adHocSync();
|
||||
}
|
||||
});
|
||||
|
||||
ipc.autofill.listenerReady();
|
||||
}
|
||||
|
||||
private convertRegistrationRequest(
|
||||
|
||||
@@ -7,6 +7,11 @@ import { WindowMain } from "../../../main/window.main";
|
||||
|
||||
import { CommandDefinition } from "./command";
|
||||
|
||||
type BufferedMessage = {
|
||||
channel: string;
|
||||
data: any;
|
||||
};
|
||||
|
||||
export type RunCommandParams<C extends CommandDefinition> = {
|
||||
namespace: C["namespace"];
|
||||
command: C["name"];
|
||||
@@ -17,12 +22,46 @@ export type RunCommandResult<C extends CommandDefinition> = C["output"];
|
||||
|
||||
export class NativeAutofillMain {
|
||||
private ipcServer: autofill.IpcServer | null;
|
||||
private messageBuffer: BufferedMessage[] = [];
|
||||
private listenerReady = false;
|
||||
|
||||
constructor(
|
||||
private logService: LogService,
|
||||
private windowMain: WindowMain,
|
||||
) {}
|
||||
|
||||
/**
|
||||
* Safely sends a message to the renderer, buffering it if the server isn't ready yet
|
||||
*/
|
||||
private safeSend(channel: string, data: any) {
|
||||
if (this.listenerReady && this.windowMain.win?.webContents) {
|
||||
this.windowMain.win.webContents.send(channel, data);
|
||||
} else {
|
||||
this.logService.info(
|
||||
`Buffering message to ${channel} until server is ready. Call .listenerReady() to flush.`,
|
||||
);
|
||||
this.messageBuffer.push({ channel, data });
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Flushes all buffered messages to the renderer
|
||||
*/
|
||||
private flushMessageBuffer() {
|
||||
if (!this.windowMain.win?.webContents) {
|
||||
this.logService.error("Cannot flush message buffer - window not available");
|
||||
return;
|
||||
}
|
||||
|
||||
this.logService.info(`Flushing ${this.messageBuffer.length} buffered messages`);
|
||||
|
||||
for (const { channel, data } of this.messageBuffer) {
|
||||
this.windowMain.win.webContents.send(channel, data);
|
||||
}
|
||||
|
||||
this.messageBuffer = [];
|
||||
}
|
||||
|
||||
async init() {
|
||||
ipcMain.handle(
|
||||
"autofill.runCommand",
|
||||
@@ -43,7 +82,7 @@ export class NativeAutofillMain {
|
||||
this.ipcServer.completeError(clientId, sequenceNumber, String(error));
|
||||
return;
|
||||
}
|
||||
this.windowMain.win.webContents.send("autofill.passkeyRegistration", {
|
||||
this.safeSend("autofill.passkeyRegistration", {
|
||||
clientId,
|
||||
sequenceNumber,
|
||||
request,
|
||||
@@ -56,7 +95,7 @@ export class NativeAutofillMain {
|
||||
this.ipcServer.completeError(clientId, sequenceNumber, String(error));
|
||||
return;
|
||||
}
|
||||
this.windowMain.win.webContents.send("autofill.passkeyAssertion", {
|
||||
this.safeSend("autofill.passkeyAssertion", {
|
||||
clientId,
|
||||
sequenceNumber,
|
||||
request,
|
||||
@@ -69,7 +108,7 @@ export class NativeAutofillMain {
|
||||
this.ipcServer.completeError(clientId, sequenceNumber, String(error));
|
||||
return;
|
||||
}
|
||||
this.windowMain.win.webContents.send("autofill.passkeyAssertionWithoutUserInterface", {
|
||||
this.safeSend("autofill.passkeyAssertionWithoutUserInterface", {
|
||||
clientId,
|
||||
sequenceNumber,
|
||||
request,
|
||||
@@ -82,8 +121,7 @@ export class NativeAutofillMain {
|
||||
this.ipcServer.completeError(clientId, sequenceNumber, String(error));
|
||||
return;
|
||||
}
|
||||
this.logService.info("Received native status", status);
|
||||
this.windowMain.win.webContents.send("autofill.nativeStatus", {
|
||||
this.safeSend("autofill.nativeStatus", {
|
||||
clientId,
|
||||
sequenceNumber,
|
||||
status,
|
||||
@@ -91,6 +129,14 @@ export class NativeAutofillMain {
|
||||
},
|
||||
);
|
||||
|
||||
ipcMain.on("autofill.listenerReady", async () => {
|
||||
this.listenerReady = true;
|
||||
this.logService.info(
|
||||
`Listener is ready, flushing ${this.messageBuffer.length} buffered messages`,
|
||||
);
|
||||
this.flushMessageBuffer();
|
||||
});
|
||||
|
||||
ipcMain.on("autofill.completePasskeyRegistration", (event, data) => {
|
||||
this.logService.warning("autofill.completePasskeyRegistration", data);
|
||||
const { clientId, sequenceNumber, response } = data;
|
||||
|
||||
Reference in New Issue
Block a user