"use strict"; import messageRouter from "./messageRouter"; const _ = browser.i18n.getMessage; browser.runtime.onInstalled.addListener(async details => { const initialOptions = { option_localMediaEnabled: true , option_localMediaServerPort: 9555 , option_uaWhitelistEnabled: true , option_uaWhitelist: [ "www.netflix.com" ].join("\n") }; switch (details.reason) { // Set initial options case "install": browser.storage.sync.set({ options: initialOptions }); break; // Set newly added options case "update": const { options } = await browser.storage.sync.get("options"); const newOptions = {}; // Find options not already in storage for (const [ key, val ] of Object.entries(initialOptions)) { if (!options.hasOwnProperty(key)) { newOptions[key] = val; } } // Update storage with default values of new options browser.storage.sync.set({ options: { ...options , ...newOptions } }); break; } }); // Google-hosted API loader script const SENDER_SCRIPT_URL = "https://www.gstatic.com/cv/js/sender/v1/cast_sender.js"; const SENDER_SCRIPT_FRAMEWORK_URL = `${SENDER_SCRIPT_URL}?loadCastFramework=1`; /** * Sender applications load a cast_sender.js script that * functions as a loader for the internal chrome-extension: * hosted script. * * We can redirect this and inject our own script to setup * the API shim. */ browser.webRequest.onBeforeRequest.addListener( async details => { switch (details.url) { case SENDER_SCRIPT_URL: // Content/Page script bridge await browser.tabs.executeScript(details.tabId, { file: "content.js" , frameId: details.frameId , runAt: "document_start" }); return { redirectUrl: browser.runtime.getURL("shim/bundle.js") }; case SENDER_SCRIPT_FRAMEWORK_URL: // TODO: implement cast.framework return { cancel: true }; } } , { urls: [ SENDER_SCRIPT_URL , SENDER_SCRIPT_FRAMEWORK_URL ]} , [ "blocking" ]); /** * Returns a Chrome user agent string with the provided platform. */ function getChromeUA (platform) { return `Mozilla/5.0 (${platform}) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.67 Safari/537.36`; } // Desktop platform Chrome UA strings const UA_STRINGS = { "mac" : getChromeUA("Macintosh; Intel Mac OS X 10_14_1") , "win" : getChromeUA("Windows NT 10.0; Win64; x64") , "linux" : getChromeUA("Mozilla/5.0 (X11; Linux x86_64") }; // Current user agent string for all whitelisted requests let currentUAString; /** * Web apps usually only load the sender library and * provide cast functionality if the browser is detected * as Chrome, so we should rewrite the User-Agent header * to reflect this on whitelisted sites. * * TODO: Inject script to change navigator.userAgent * property. */ browser.webRequest.onBeforeSendHeaders.addListener( async details => { const { options } = await browser.storage.sync.get("options"); // Cancel if feature is disabled if (!options.option_uaWhitelistEnabled) return; // Cancel if not on whitelist // TODO: Do this with the built in filter const { hostname } = new URL(details.url); if (!options.option_uaWhitelist.split("\n").includes(hostname)) return; // Create Chrome UA from platform info on first run if (!currentUAString) { currentUAString = UA_STRINGS[ (await browser.runtime.getPlatformInfo()).os] } // Find and rewrite the User-Agent header for (const header of details.requestHeaders) { if (header.name.toLowerCase() === "user-agent") { header.value = currentUAString; break; } } return { requestHeaders: details.requestHeaders }; } , { urls: [ "" ]} , [ "blocking", "requestHeaders" ]); // Defines window.chrome for site compatibility browser.contentScripts.register({ allFrames: true , js: [{ file: "contentSetup.js" }] , matches: [ "" ] , runAt: "document_start" }); // Screen/Tab mirroring "Cast..." context menu item browser.menus.create({ contexts: [ "browser_action", "page" ] , id: "contextCast" , title: _("context_media_cast") }); //