Skip to content

Commit

Permalink
fix: Handle error when offscreen document already exists
Browse files Browse the repository at this point in the history
A `try..catch` block has been added to catch errors about the Offscreen
document already existing. This circumstance is not a bug, it's
expected to happen sometimes due to race conditions between
`hasDocument` and the creation step. The code in question is just meant
to create the document if it doesn't exist, so it's OK if we get this
error.

The `hasDocument` call has been removed as well, since it's now
redundant. This function wasn't safe to call anyway; it's an
undocumented private function.

See here for more information:
* https://stackoverflow.com/a/7725839
* https://groups.google.com/a/chromium.org/g/chromium-extensions/c/D5Jg2ukyvUc4

Fixes #25118
  • Loading branch information
Gudahtt committed Jun 20, 2024
1 parent 7e6fb5d commit ac73ecc
Showing 1 changed file with 30 additions and 10 deletions.
40 changes: 30 additions & 10 deletions app/scripts/offscreen.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,29 +9,49 @@ import { OffscreenCommunicationTarget } from '../../shared/constants/offscreen-c
*/
export async function createOffscreen() {
const { chrome } = globalThis;
if (!chrome.offscreen || (await chrome.offscreen.hasDocument())) {
if (!chrome.offscreen) {
return;
}

let offscreenDocumentLoadedListener;
const loadPromise = new Promise((resolve) => {
const messageListener = (msg) => {
offscreenDocumentLoadedListener = (msg) => {
if (
msg.target === OffscreenCommunicationTarget.extensionMain &&
msg.isBooted
) {
chrome.runtime.onMessage.removeListener(messageListener);
chrome.runtime.onMessage.removeListener(
offscreenDocumentLoadedListener,
);
resolve();
}
};
chrome.runtime.onMessage.addListener(messageListener);
chrome.runtime.onMessage.addListener(offscreenDocumentLoadedListener);
});

await chrome.offscreen.createDocument({
url: './offscreen.html',
reasons: ['IFRAME_SCRIPTING'],
justification:
'Used for Hardware Wallet and Snaps scripts to communicate with the extension.',
});
try {
await chrome.offscreen.createDocument({
url: './offscreen.html',
reasons: ['IFRAME_SCRIPTING'],
justification:
'Used for Hardware Wallet and Snaps scripts to communicate with the extension.',
});
} catch (error) {
if (
error?.message?.startsWith(
'Only a single offscreen document may be created',
)
) {
console.debug('Offscreen document already exists; skipping creation');
if (offscreenDocumentLoadedListener) {
chrome.runtime.onMessage.removeListener(
offscreenDocumentLoadedListener,
);
}
return;
}
throw error;
}

// In case we are in a bad state where the offscreen document is not loading, timeout and let execution continue.
const timeoutPromise = new Promise((resolve) => {
Expand Down

0 comments on commit ac73ecc

Please sign in to comment.