Skip to content

Commit

Permalink
cherry-pick: Recreate offscreen document if it already exists (#27653)
Browse files Browse the repository at this point in the history
<!--
Please submit this PR as a draft initially.
Do not mark it as "Ready for review" until the template has been
completely filled out, and PR status checks have passed at least once.
-->

## **Description**

When the service worker is stopped it doesn't seem to guarantee that the
offscreen document is closed as well. Our current initialization logic
assumes this and thus once the service worker is spun back up, all
communication with the offscreen document fails due to initialization
failure.

This PR cherry-picks
03cd7d5
to the 12.5 RC, fixing this problem.

[![Open in GitHub

Codespaces](https://github.com/codespaces/badge.svg)](https://codespaces.new/MetaMask/metamask-extension/pull/27596?quickstart=1)
  • Loading branch information
FrederikBolding authored Oct 7, 2024
1 parent 0c1e287 commit 41e7889
Showing 1 changed file with 33 additions and 12 deletions.
45 changes: 33 additions & 12 deletions app/scripts/offscreen.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,27 @@ import {
} from '../../shared/constants/offscreen-communication';
import { getSocketBackgroundToMocha } from '../../test/e2e/background-socket/socket-background-to-mocha';

/**
* Returns whether the offscreen document already exists or not.
*
* See https://developer.chrome.com/docs/extensions/reference/api/offscreen#before_chrome_116_check_if_an_offscreen_document_is_open
*
* @returns True if the offscreen document already is has been opened, otherwise false.
*/
async function hasOffscreenDocument() {
const { chrome, clients } = globalThis;
// getContexts is only available in Chrome 116+
if ('getContexts' in chrome.runtime) {
const contexts = await chrome.runtime.getContexts({
contextTypes: ['OFFSCREEN_DOCUMENT'],
});
return contexts.length > 0;
}
const matchedClients = await clients.matchAll();
const url = chrome.runtime.getURL('offscreen.html');
return matchedClients.some((client) => client.url === url);
}

/**
* Creates an offscreen document that can be used to load additional scripts
* and iframes that can communicate with the extension through the chrome
Expand Down Expand Up @@ -41,6 +62,14 @@ export async function createOffscreen() {
});

try {
const offscreenExists = await hasOffscreenDocument();

// In certain cases the offscreen document may already exist during boot, if it does, we close it and recreate it.
if (offscreenExists) {
console.debug('Found existing offscreen document, closing.');
await chrome.offscreen.closeDocument();
}

await chrome.offscreen.createDocument({
url: './offscreen.html',
reasons: ['IFRAME_SCRIPTING'],
Expand All @@ -51,18 +80,10 @@ export async function createOffscreen() {
if (offscreenDocumentLoadedListener) {
chrome.runtime.onMessage.removeListener(offscreenDocumentLoadedListener);
}
if (
error?.message?.startsWith(
'Only a single offscreen document may be created',
)
) {
console.debug('Offscreen document already exists; skipping creation');
} else {
// Report unrecongized errors without halting wallet initialization
// Failures to create the offscreen document does not compromise wallet data integrity or
// core functionality, it's just needed for specific features.
captureException(error);
}
// Report unrecongized errors without halting wallet initialization
// Failures to create the offscreen document does not compromise wallet data integrity or
// core functionality, it's just needed for specific features.
captureException(error);
return;
}

Expand Down

0 comments on commit 41e7889

Please sign in to comment.