import delay from 'delay'; async function tryUntilItWorks(func, delayBetweenTries = 1, maxTries = 10) { for (let i = 0; i < maxTries; i++) { try { await func(); return; } catch (err) { await delay(delayBetweenTries); continue; } } } async function onHeadersReceived({ responseHeaders, url, tabId }) { const isAudio = responseHeaders.some(header => header.name.toLowerCase() === 'content-type' && header.value.toLowerCase().startsWith('audio/') ); if (isAudio) { // Avoid any short glitch of sound (observed in Firefox) before our injected script executes. await browser.tabs.update(tabId, { muted: true }); // Too quickly executing the script may fail (bug in Firefox), so we retry if necessary. await tryUntilItWorks(() => browser.tabs.executeScript(tabId, { runAt: 'document_end', file: '/scripts/contentscript.js', })); // Unmute again. await browser.tabs.update(tabId, { muted: false }); await tryUntilItWorks(() => browser.tabs.insertCSS(tabId, { runAt: 'document_end', file: '/assets/waveform-playlist.css', })); await tryUntilItWorks(() => browser.tabs.insertCSS(tabId, { runAt: 'document_end', file: '/assets/main.css', })); } } browser.webRequest.onHeadersReceived.addListener( onHeadersReceived, { urls: [''], types: ['main_frame'], }, ['responseHeaders'], );