|
- import delay from 'delay';
-
- async function tryUntilItWorks(func, delayBetweenTries = 1, maxTries = 10) {
- for (let i = 0; i < maxTries; i++) {
- try {
- return await func();
- } catch (err) {
- await delay(delayBetweenTries);
- continue;
- }
- }
- }
-
- async function insertOurAudioPlayer(tabId) {
- // 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',
- }));
- }
-
- // Load the player on any file with an audio/* mime type.
- async function onHeadersReceived({ responseHeaders, url, tabId }) {
- const isAudio = responseHeaders.some(header =>
- header.name.toLowerCase() === 'content-type' && header.value.toLowerCase().startsWith('audio/')
- );
-
- if (isAudio) {
- insertOurAudioPlayer(tabId);
- }
- }
-
- browser.webRequest.onHeadersReceived.addListener(
- onHeadersReceived,
- {
- urls: ['<all_urls>'],
- types: ['main_frame'],
- },
- ['responseHeaders'],
- );
-
- // As files loaded through file://… URLs do not have headers, we run a separate check for these.
- async function onVisitFileUrl({ url, tabId }) {
- // I don’t know how we could neatly test whether the file is an audio file. This expression is a
- // pragmatic solution working for (at least) the current versions of Firefox and Chromium.
- const isAudioPlayerExpression =
- `document.body.childElementCount === 1
- && document.body.firstElementChild instanceof HTMLVideoElement
- && document.body.firstElementChild.videoHeight === 0
- && document.body.firstElementChild.videoWidth === 0
- `;
- const [isAudio] = await tryUntilItWorks(() => browser.tabs.executeScript(tabId, {
- code: isAudioPlayerExpression,
- runAt: 'document_idle', // (at document_end it’s not clear yet whether it’s audio or video..)
- }));
- if (isAudio) {
- insertOurAudioPlayer(tabId);
- }
- }
-
- browser.webNavigation.onCommitted.addListener(
- onVisitFileUrl,
- { url: [{ schemes: ['file'] }] },
- );
|