Under MV3 the background is not persistent. Firefox suspends an idle event page after 30 seconds, and Chrome stops an idle service worker. An open port does not count as activity. A user importing an account spent longer than that typing a name and password. The background suspended and discarded the popup's subscriptions. Adding the account then woke it, and the account was saved. The popup never re-subscribed, so it kept showing the empty list until a reload. Upstream reconnected lazily on the next message and forgot what it had subscribed to. Every caller also raced to open its own port. Pages and the content script now share one client, which: - opens a single connection however many requests arrive together; - re-sends subscriptions, with their original ids, as soon as the connection drops; - rejects requests left unanswered by a restart instead of leaving them hanging; - keeps the background awake with a 20s wake-up while anything is outstanding, so a sign request under review, or a popup left open, is not lost to the idle timeout. The content script replays only pub(accounts.subscribe). RPC subscriptions are keyed by an id the background hands out, and a replay can't reproduce that. Verified in Firefox: - With the idle timeout at 5s, importing an ML-DSA-87 account across three background suspensions shows it in the list without a reload. The previous build reproduces the bug under the same conditions. - At the default 30s timeout, an open page saw no disconnects in 75s. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012uDUodEcRbBwNRi3UCmw8f
@polkadot/extension-base
Functions, classes and other utilities used in @polkadot/extension. These include:
- background script handlers,
- message passing,
- scripts injected inside pages.
They are primarily meant to be used in @polkadot/extension, and can be broken without any notice to cater for @polkadot/extension's needs.
They are exported here if you wish to use part of them in the development of your
own extension. Don't forget to add process.env.EXTENSION_PREFIX to separate
ports and stores from the current extension's ones.