Fix browser keyboard review follow-ups

This commit is contained in:
Mohamed Boudra
2026-07-14 14:11:32 +00:00
parent 650b4236ff
commit 52994373f7
4 changed files with 40 additions and 13 deletions

View File

@@ -6,7 +6,6 @@ describe("trusted browser input", () => {
test.each([
["a", "a", ["keyDown", "char", "keyUp"]],
["Z", "Z", ["keyDown", "char", "keyUp"]],
["Space", "Space", ["keyDown", "keyUp"]],
["ArrowDown", "Down", ["keyDown", "keyUp"]],
])(
"sends %s as Electron key code %s with unhandled redispatch disabled",
@@ -26,4 +25,18 @@ describe("trusted browser input", () => {
);
},
);
test("inserts a named Space keypress", () => {
const events: IsolatedKeyboardInputEvent[] = [];
dispatchTrustedKey((event) => {
events.push(event);
}, "Space");
expect(events).toEqual([
{ type: "keyDown", keyCode: "Space", skipIfUnhandled: true },
{ type: "char", keyCode: " ", skipIfUnhandled: true },
{ type: "keyUp", keyCode: "Space", skipIfUnhandled: true },
]);
});
});

View File

@@ -163,15 +163,21 @@ export async function dispatchTrustedText(send: CdpCommandSender, text: string):
export function dispatchTrustedKey(send: KeyboardInputSender, key: string): void {
const keyCode = ELECTRON_KEY_CODE_ALIASES[key] ?? key;
let character: string | null = null;
if (key === "Space") {
character = " ";
} else if (key.length === 1) {
character = key;
}
send({
type: "keyDown",
keyCode,
skipIfUnhandled: true,
});
if (key.length === 1) {
if (character !== null) {
send({
type: "char",
keyCode,
keyCode: character,
skipIfUnhandled: true,
});
}

View File

@@ -13,6 +13,7 @@ class FakeBrowserContents {
public readonly sent: SentMessage[] = [];
private destroyed = false;
private readonly destroyedListeners: Array<() => void> = [];
private domReadyListener: (() => void) | null = null;
private finishLoadListener: (() => void) | null = null;
private inputListener:
| ((event: { preventDefault(): void }, input: Electron.Input) => void)
@@ -41,18 +42,23 @@ class FakeBrowserContents {
}
public on(event: "did-finish-load", listener: () => void): void;
public on(event: "dom-ready", listener: () => void): void;
public on(
event: "before-input-event",
listener: (event: { preventDefault(): void }, input: Electron.Input) => void,
): void;
public on(
event: "did-finish-load" | "before-input-event",
event: "did-finish-load" | "dom-ready" | "before-input-event",
listener: (() => void) | ((event: { preventDefault(): void }, input: Electron.Input) => void),
): void {
if (event === "did-finish-load") {
this.finishLoadListener = listener as () => void;
return;
}
if (event === "dom-ready") {
this.domReadyListener = listener as () => void;
return;
}
this.inputListener = listener as (
event: { preventDefault(): void },
input: Electron.Input,
@@ -90,6 +96,10 @@ class FakeBrowserContents {
this.finishLoadListener?.();
}
public domReady(): void {
this.domReadyListener?.();
}
public input(input: Electron.Input): boolean {
let wasPrevented = false;
this.inputListener?.(
@@ -178,7 +188,7 @@ describe("BrowserKeyboard", () => {
]);
});
test("resends the latest shortcut policy after every main-frame load", () => {
test("republishes the latest shortcut policy when the next guest document is ready", () => {
const { attach, keyboard } = createBrowserKeyboard();
const guest = new FakeBrowserContents(61);
const host = new FakeBrowserContents(62);
@@ -199,8 +209,7 @@ describe("BrowserKeyboard", () => {
attach({ browserId: "browser-a", contents: guest, hostContents: host });
keyboard.publish(host.id, latestPolicy);
guest.finishLoad();
guest.finishLoad();
guest.domReady();
expect(guest.sent).toEqual([
{
@@ -215,11 +224,10 @@ describe("BrowserKeyboard", () => {
channel: "paseo:browser-keyboard-policy",
payload: { ...latestPolicy, browserId: "browser-a" },
},
{
channel: "paseo:browser-keyboard-policy",
payload: { ...latestPolicy, browserId: "browser-a" },
},
]);
guest.finishLoad();
expect(guest.sent).toHaveLength(3);
});
test("owns reserved shortcuts and leaves plain guest input contained", () => {

View File

@@ -27,7 +27,7 @@ interface BrowserKeyboardInputEvent {
interface BrowserKeyboardGuestContents extends BrowserKeyboardContentsIdentity {
isDestroyed(): boolean;
isLoadingMainFrame(): boolean;
on(event: "did-finish-load", listener: () => void): void;
on(event: "dom-ready", listener: () => void): void;
on(
event: "before-input-event",
listener: (event: BrowserKeyboardInputEvent, input: Electron.Input) => void,
@@ -82,7 +82,7 @@ export class BrowserKeyboard {
this.attachedGuestsByWebContentsId.delete(webContentsId);
}
});
input.contents.on("did-finish-load", () => {
input.contents.on("dom-ready", () => {
const currentRegistration = this.registrationForGuest(webContentsId, guest);
if (!currentRegistration) {
return;