diff --git a/packages/extension-koni/src/helper/ActionHandler.ts b/packages/extension-koni/src/helper/ActionHandler.ts index dd0f54bfc5..a5e73d177f 100644 --- a/packages/extension-koni/src/helper/ActionHandler.ts +++ b/packages/extension-koni/src/helper/ActionHandler.ts @@ -4,6 +4,8 @@ import { MessageTypes, RequestSignatures, TransportRequestMessage } from '@subwallet/extension-base/background/types'; import { PORT_CONTENT, PORT_EXTENSION } from '@subwallet/extension-base/defaults'; import { SWHandler } from '@subwallet/extension-base/koni/background/handlers'; +import { sendMessage } from '@subwallet/extension-base/page'; +import { isFirefox } from '@subwallet/extension-base/utils'; import { createPromiseHandler } from '@subwallet/extension-base/utils/promise'; import { startHeartbeat, stopHeartbeat } from '@subwallet/extension-koni/helper/HeartBeat'; @@ -92,7 +94,9 @@ export class ActionHandler { if (!this.isActive) { this.isActive = true; - startHeartbeat(); + startHeartbeat(async () => { + await (isFirefox ? sendMessage('pub(ping)', null) : chrome.storage.local.set({ 'last-heartbeat': new Date().getTime() })); + }); this.mainHandler && await this.mainHandler.state.wakeup(); this.waitActiveHandler.resolve(true); } diff --git a/packages/extension-koni/src/helper/HeartBeat.ts b/packages/extension-koni/src/helper/HeartBeat.ts index e45211e037..3559f11edf 100644 --- a/packages/extension-koni/src/helper/HeartBeat.ts +++ b/packages/extension-koni/src/helper/HeartBeat.ts @@ -3,6 +3,8 @@ // These code from https://developer.chrome.com/docs/extensions/develop/migrate/to-service-workers#keep-sw-alive +import { isFirefox } from '@subwallet/extension-base/utils'; + /** * Tracks when a service worker was last alive and extends the service worker * lifetime by writing the current time to extension storage every 20 seconds. @@ -13,8 +15,20 @@ let heartbeatInterval: NodeJS.Timer | undefined; -async function runHeartbeat () { - await chrome.storage.local.set({ 'last-heartbeat': new Date().getTime() }); +async function runHeartbeat (cb: () => Promise) { + if (isFirefox) { + await chrome.alarms.create('keep-loaded-alarm', { + periodInMinutes: 0.3 + }); + + chrome.alarms.onAlarm.addListener((alarm) => { + if (alarm.name === 'keep-loaded-alarm') { + cb().catch(() => console.error('Failed to load alarms')); + } + }); + } else { + await cb(); + } } /** @@ -22,22 +36,32 @@ async function runHeartbeat () { * this sparingly when you are doing work which requires persistence, and call * stopHeartbeat once that work is complete. */ -export function startHeartbeat () { +export function startHeartbeat (cb: () => Promise) { // Run the heartbeat once at service worker startup. if (heartbeatInterval) { clearInterval(heartbeatInterval); } - runHeartbeat().then(() => { - // Then again every 20 seconds. - heartbeatInterval = setInterval(() => { - runHeartbeat().catch(console.error); - }, 20 * 1000); + runHeartbeat(cb).then(() => { + if (!isFirefox) { + heartbeatInterval = setInterval(() => { + runHeartbeat(cb).catch(console.error); + }, 20 * 1000); + } }).catch(console.error); } export function stopHeartbeat () { - clearInterval(heartbeatInterval); + if (isFirefox) { + chrome.alarms.clear('keep-loaded-alarm', function (wasCleared) { + if (wasCleared) { + console.log('Alarm was cleared'); + } + }); + } else { + clearInterval(heartbeatInterval); + } + heartbeatInterval = undefined; } diff --git a/scripts/koni-ci-mv3-firefox.mjs b/scripts/koni-ci-mv3-firefox.mjs index b9a9eb1096..a36a1557e5 100755 --- a/scripts/koni-ci-mv3-firefox.mjs +++ b/scripts/koni-ci-mv3-firefox.mjs @@ -25,7 +25,7 @@ async function updateManifest() { delete manifest.web_accessible_resources[0].use_dynamic_url; } manifest.permissions.push("activeTab"); - manifest = {...manifest, host_permissions : [""], optional_permissions : ["activeTab"]}; + manifest = {...manifest, host_permissions : [""], optional_permissions : ["activeTab", "alarms"]}; if(manifest.content_scripts && manifest.content_scripts.length > 0) { manifest.content_scripts[0].js.push("injectGlobal.js");