Refactor browser extension background init to prevent init warnings (#2004)

This commit is contained in:
Leendert de Borst
2026-05-14 09:35:59 +02:00
committed by Leendert de Borst
parent 431fbee9ae
commit 27eeb589c8

View File

@@ -32,8 +32,41 @@ browser.alarms.onAlarm.addListener(handleAutoLockAlarm);
export default defineBackground({
/**
* This is the main entry point for the background script.
*
* IMPORTANT: This function MUST remain synchronous (no async/await directly in
* the body). MV3 service workers can be terminated when idle and woken up by
* events; only listeners registered synchronously during script evaluation are
* guaranteed to be ready when the next event fires. Any asynchronous setup must
* run as a fire-and-forget IIFE so this function returns synchronously.
*/
async main() {
main() {
/*
* Register any synchronous event listeners first, before any await,
* so they're attached synchronously on service-worker wake-up.
*/
browser.commands.onCommand.addListener(async (command) => {
if (command !== "show-autofill-popup") {
return;
}
try {
const [tab] = await browser.tabs.query({ active: true, currentWindow: true });
if (!tab?.id) {
return;
}
const results = await browser.scripting.executeScript({
target: { tabId: tab.id },
func: getActiveElementIdentifier,
});
const elementIdentifier = results[0]?.result;
if (elementIdentifier) {
sendMessage('OPEN_AUTOFILL_POPUP', { elementIdentifier }, `content-script@${tab.id}`);
}
} catch (error) {
console.error('Error handling show-autofill-popup command:', error);
}
});
// Listen for messages using webext-bridge
onMessage('CHECK_AUTH_STATUS', () => handleCheckAuthStatus());
@@ -130,44 +163,32 @@ export default defineBackground({
onMessage('PASSKEY_POPUP_RESPONSE', ({ data }) => handlePasskeyPopupResponse(data));
onMessage('GET_REQUEST_DATA', ({ data }) => handleGetRequestData(data));
// Setup context menus
const isContextMenuEnabled = await LocalPreferencesService.getGlobalContextMenuEnabled();
if (isContextMenuEnabled) {
await setupContextMenus();
}
/*
* Initialize auto-lock alarm system.
* This ensures the alarm is restored if the service worker was terminated.
* Note: The alarm listener is registered at top-level scope (see above).
* Async setup (context menus, alarm restoration) runs in a fire-and-forget
* IIFE so main() returns synchronously. Listener registrations above are
* already synchronous and complete before this runs.
*/
await initializeAutoLockAlarm();
// Listen for custom commands
try {
browser.commands.onCommand.addListener(async (command) => {
if (command === "show-autofill-popup") {
// Get the currently active tab
const [tab] = await browser.tabs.query({ active: true, currentWindow: true });
if (!tab?.id) {
return;
}
// Execute script in the active tab
await browser.scripting.executeScript({
target: { tabId: tab.id },
func: getActiveElementIdentifier,
}).then((results) => {
const elementIdentifier = results[0]?.result;
if (elementIdentifier) {
sendMessage('OPEN_AUTOFILL_POPUP', { elementIdentifier }, `content-script@${tab.id}`);
}
}).catch(console.error);
(async () : Promise<void> => {
try {
const isContextMenuEnabled = await LocalPreferencesService.getGlobalContextMenuEnabled();
if (isContextMenuEnabled) {
await setupContextMenus();
}
});
} catch (error) {
console.error('Error setting up command listener:', error);
}
} catch (error) {
console.error('Error setting up context menus:', error);
}
try {
/*
* Initialize auto-lock alarm system.
* This ensures the alarm is restored if the service worker was terminated.
* Note: The alarm listener is registered at top-level scope (see above).
*/
await initializeAutoLockAlarm();
} catch (error) {
console.error('Error initializing auto-lock alarm:', error);
}
})();
}
});