Convert ext main.js -> main.ts

This commit is contained in:
hensm
2019-02-26 19:28:33 +00:00
parent 2014566cc4
commit 3ea943c509
7 changed files with 112 additions and 60 deletions

6
ext/package-lock.json generated
View File

@@ -65,6 +65,12 @@
"es6-promise": "^2.0.1" "es6-promise": "^2.0.1"
} }
}, },
"@types/firefox-webext-browser": {
"version": "65.0.2",
"resolved": "https://registry.npmjs.org/@types/firefox-webext-browser/-/firefox-webext-browser-65.0.2.tgz",
"integrity": "sha512-pP8dInqFHvhI6X8UCWb12RHuHTukADWSF+INWt7VFkfYaFdy3ZJXAxujbFb063mh70O/F7R8rC14a7Giw8xo7Q==",
"dev": true
},
"@types/node": { "@types/node": {
"version": "10.12.7", "version": "10.12.7",
"resolved": "https://registry.npmjs.org/@types/node/-/node-10.12.7.tgz", "resolved": "https://registry.npmjs.org/@types/node/-/node-10.12.7.tgz",

View File

@@ -12,6 +12,7 @@
"lint": "node bin/lint.js" "lint": "node bin/lint.js"
}, },
"devDependencies": { "devDependencies": {
"@types/firefox-webext-browser": "^65.0.2",
"@types/react": "^16.8.4", "@types/react": "^16.8.4",
"@types/react-dom": "^16.8.2", "@types/react-dom": "^16.8.2",
"copy-webpack-plugin": "^4.6.0", "copy-webpack-plugin": "^4.6.0",

18
ext/src/global.d.ts vendored Normal file
View File

@@ -0,0 +1,18 @@
declare const EXTENSION_NAME: string;
declare const EXTENSION_ID: string;
declare const EXTENSION_VERSION: string;
declare const MIRRORING_APP_ID: string;
declare const APPLICATION_NAME: string;
declare const APPLICATION_VERSION: string;
// Fix issues with @types/firefox-webext-browser
declare namespace browser.events {
interface Event {
addListener (...args: any[]): void;
}
}
declare namespace browser.runtime {
interface Port {
error: { message: string };
}
}

26
ext/src/lib/userAgents.ts Normal file
View File

@@ -0,0 +1,26 @@
"use strict";
const PLATFORM_MAC = "Macintosh; Intel Mac OS X 10_14_1";
const PLATFORM_WIN = "Windows NT 10.0; Win64; x64";
const PLATFORM_LINUX = "Mozilla/5.0 (X11; Linux x86_64";
const UA_PREFIX = "Mozilla/5.0";
const UA_CHROME = "AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.67 Safari/537.36";
const UA_SAFARI = "AppleWebKit/605.1.15 (KHTML, like Gecko) Version/12.0 Safari/605.1.15";
export function getChromeUserAgent (platform: string): string {
let platformComponent: string;
switch (platform) {
case "mac": platformComponent = PLATFORM_MAC; break;
case "win": platformComponent = PLATFORM_WIN; break;
case "linux": platformComponent = PLATFORM_LINUX; break;
}
return `${UA_PREFIX} (${platformComponent}) ${UA_CHROME}`;
}
export function getSafariUserAgent (platform: string): string {
return `${UA_PREFIX} (${PLATFORM_MAC}) ${UA_SAFARI}`;
}

View File

@@ -1,9 +1,10 @@
"use strict"; "use strict";
import defaultOptions from "./options/defaultOptions";
import getBridgeInfo from "./lib/getBridgeInfo"; import getBridgeInfo from "./lib/getBridgeInfo";
import messageRouter from "./lib/messageRouter"; import messageRouter from "./lib/messageRouter";
import defaultOptions from "./options/defaultOptions";
import { getChromeUserAgent } from "./lib/userAgents";
import { getWindowCenteredProps } from "./lib/utils"; import { getWindowCenteredProps } from "./lib/utils";
import semver from "semver"; import semver from "semver";
@@ -14,21 +15,20 @@ const _ = browser.i18n.getMessage;
browser.runtime.onInstalled.addListener(async details => { browser.runtime.onInstalled.addListener(async details => {
switch (details.reason) { switch (details.reason) {
// Set default options // Set default options
case "install": { case "install": {
await browser.storage.sync.set({ await browser.storage.sync.set({
options: defaultOptions options: defaultOptions
}); });
break; break;
}; }
// Set newly added options // Set newly added options
case "update": { case "update": {
const { options: existingOptions } const { options: existingOptions }
= await browser.storage.sync.get("options"); = await browser.storage.sync.get("options");
const newOptions = {}; const newOptions: { [key: string]: any } = {};
// Find options not already in storage // Find options not already in storage
for (const [ key, val ] of Object.entries(defaultOptions)) { for (const [ key, val ] of Object.entries(defaultOptions)) {
@@ -46,7 +46,7 @@ browser.runtime.onInstalled.addListener(async details => {
}); });
break; break;
}; }
} }
// Call after default options have been set // Call after default options have been set
@@ -55,8 +55,8 @@ browser.runtime.onInstalled.addListener(async details => {
// Menu IDs // Menu IDs
let mirrorCastMenuId; let mirrorCastMenuId: string | number;
let mediaCastMenuId; let mediaCastMenuId: string | number;
const mediaCastTargetUrlPatterns = new Set([ const mediaCastTargetUrlPatterns = new Set([
"http://*/*" "http://*/*"
@@ -72,7 +72,9 @@ async function createMenus () {
* If options aren't set or menus have already been * If options aren't set or menus have already been
* created, return. * created, return.
*/ */
if (!options || mirrorCastMenuId || mediaCastMenuId) return; if (!options || mirrorCastMenuId || mediaCastMenuId) {
return;
}
if (options.localMediaEnabled) { if (options.localMediaEnabled) {
mediaCastTargetUrlPatterns.add(LOCAL_MEDIA_URL_PATTERN); mediaCastTargetUrlPatterns.add(LOCAL_MEDIA_URL_PATTERN);
@@ -121,7 +123,7 @@ const SENDER_SCRIPT_FRAMEWORK_URL =
browser.webRequest.onBeforeRequest.addListener( browser.webRequest.onBeforeRequest.addListener(
async details => { async details => {
switch (details.url) { switch (details.url) {
case SENDER_SCRIPT_URL: case SENDER_SCRIPT_URL: {
// Content/Page script bridge // Content/Page script bridge
await browser.tabs.executeScript(details.tabId, { await browser.tabs.executeScript(details.tabId, {
file: "shim/content.js" file: "shim/content.js"
@@ -132,13 +134,14 @@ browser.webRequest.onBeforeRequest.addListener(
return { return {
redirectUrl: browser.runtime.getURL("shim/bundle.js") redirectUrl: browser.runtime.getURL("shim/bundle.js")
}; };
}
case SENDER_SCRIPT_FRAMEWORK_URL: case SENDER_SCRIPT_FRAMEWORK_URL: {
// TODO: implement cast.framework // TODO: implement cast.framework
return { return {
cancel: true cancel: true
}; };
}
} }
} }
, { urls: [ , { urls: [
@@ -148,22 +151,8 @@ browser.webRequest.onBeforeRequest.addListener(
, [ "blocking" ]); , [ "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 // Current user agent string for all whitelisted requests
let currentUAString; let currentUAString: string;
/** /**
* Web apps usually only load the sender library and * Web apps usually only load the sender library and
@@ -171,13 +160,13 @@ let currentUAString;
* as Chrome, so we should rewrite the User-Agent header * as Chrome, so we should rewrite the User-Agent header
* to reflect this on whitelisted sites. * to reflect this on whitelisted sites.
*/ */
async function onBeforeSendHeaders (details) { async function onBeforeSendHeaders (details: any) {
const { options } = await browser.storage.sync.get("options"); const { options } = await browser.storage.sync.get("options");
const { os } = await browser.runtime.getPlatformInfo();
// Create Chrome UA from platform info on first run // Create Chrome UA from platform info on first run
if (!currentUAString) { if (!currentUAString) {
currentUAString = UA_STRINGS[ currentUAString = getChromeUserAgent(os);
(await browser.runtime.getPlatformInfo()).os]
} }
// Find and rewrite the User-Agent header // Find and rewrite the User-Agent header
@@ -193,11 +182,13 @@ async function onBeforeSendHeaders (details) {
}; };
} }
async function onOptionsUpdated (alteredOptions) { async function onOptionsUpdated (alteredOptions?: any[]) {
const { options } = await browser.storage.sync.get("options"); const { options } = await browser.storage.sync.get("options");
// If options aren't set yet, return // If options aren't set yet, return
if (!options) return; if (!options) {
return;
}
const registerFunctions = { const registerFunctions = {
onBeforeSendHeaders () { onBeforeSendHeaders () {
@@ -217,8 +208,10 @@ async function onOptionsUpdated (alteredOptions) {
} }
} else { } else {
if (alteredOptions.includes("userAgentWhitelist") if (alteredOptions.includes("userAgentWhitelist")
|| alteredOptions.includes("userAgentWhitelistEnabled")) { || alteredOptions.includes("userAgentWhitelistEnabled")) {
browser.webRequest.onBeforeSendHeaders.removeListener(onBeforeSendHeaders);
browser.webRequest.onBeforeSendHeaders.removeListener(
onBeforeSendHeaders);
registerFunctions.onBeforeSendHeaders(); registerFunctions.onBeforeSendHeaders();
} }
@@ -231,7 +224,7 @@ async function onOptionsUpdated (alteredOptions) {
if (alteredOptions.includes("mediaEnabled")) { if (alteredOptions.includes("mediaEnabled")) {
browser.menus.update(mediaCastMenuId, { browser.menus.update(mediaCastMenuId, {
visible: options.mediaEnabled visible: options.mediaEnabled
}) });
} }
if (alteredOptions.includes("localMediaEnabled")) { if (alteredOptions.includes("localMediaEnabled")) {
@@ -250,9 +243,10 @@ async function onOptionsUpdated (alteredOptions) {
browser.runtime.onMessage.addListener(message => { browser.runtime.onMessage.addListener(message => {
switch (message.subject) { switch (message.subject) {
case "optionsUpdated": case "optionsUpdated": {
onOptionsUpdated(message.data.alteredOptions); onOptionsUpdated(message.data.alteredOptions);
break; break;
}
} }
}); });
@@ -265,11 +259,11 @@ browser.contentScripts.register({
}); });
let mediaCastTabId; let mediaCastTabId: number;
let mediaCastFrameId; let mediaCastFrameId: number;
let mirrorCastTabId; let mirrorCastTabId: number;
let mirrorCastFrameId; let mirrorCastFrameId: number;
browser.menus.onClicked.addListener(async (info, tab) => { browser.menus.onClicked.addListener(async (info, tab) => {
@@ -283,13 +277,15 @@ browser.menus.onClicked.addListener(async (info, tab) => {
}); });
switch (info.menuItemId) { switch (info.menuItemId) {
case "contextCast": case "contextCast": {
mirrorCastTabId = tab.id; mirrorCastTabId = tab.id;
mirrorCastFrameId = frameId; mirrorCastFrameId = frameId;
await browser.tabs.executeScript(tab.id, { await browser.tabs.executeScript(tab.id, {
code: `var selectedMedia = "${info.pageUrl ? "tab" : "screen"}"; code: `
var FX_CAST_RECEIVER_APP_ID = "${options.mirroringAppId}";` var selectedMedia = "${info.pageUrl ? "tab" : "screen"}";
var FX_CAST_RECEIVER_APP_ID = "${options.mirroringAppId}";
`
, frameId , frameId
}); });
@@ -298,9 +294,11 @@ browser.menus.onClicked.addListener(async (info, tab) => {
file: "mirroringCast.js" file: "mirroringCast.js"
, frameId , frameId
}); });
break;
case "contextCastMedia": break;
}
case "contextCastMedia": {
mediaCastTabId = tab.id; mediaCastTabId = tab.id;
mediaCastFrameId = frameId; mediaCastFrameId = frameId;
@@ -316,7 +314,9 @@ browser.menus.onClicked.addListener(async (info, tab) => {
file: "mediaCast.js" file: "mediaCast.js"
, frameId , frameId
}); });
break; break;
}
} }
// Load cast API // Load cast API
@@ -327,16 +327,16 @@ browser.menus.onClicked.addListener(async (info, tab) => {
}); });
let popupWinId; let popupWinId: number;
let popupShimId; let popupShimId: string;
let popupPort; let popupPort: browser.runtime.Port;
/** /**
* Creates popup window for cast destination selection. * Creates popup window for cast destination selection.
* Refocusing other browser windows causes the popup window * Refocusing other browser windows causes the popup window
* to close and returns an API error. * to close and returns an API error.
*/ */
async function openPopup (shimId) { async function openPopup (shimId: string) {
// Current window to base centered position on // Current window to base centered position on
const win = await browser.windows.getCurrent(); const win = await browser.windows.getCurrent();
const centeredProps = getWindowCenteredProps(win, 350, 200); const centeredProps = getWindowCenteredProps(win, 350, 200);
@@ -382,7 +382,7 @@ browser.windows.onRemoved.addListener(id => {
const shimMap = new Map(); const shimMap = new Map();
async function onConnectShim (port) { async function onConnectShim (port: browser.runtime.Port) {
const bridgeInfo = await getBridgeInfo(); const bridgeInfo = await getBridgeInfo();
if (bridgeInfo && !bridgeInfo.isVersionCompatible) { if (bridgeInfo && !bridgeInfo.isVersionCompatible) {
return; return;
@@ -419,7 +419,7 @@ async function onConnectShim (port) {
console.error(`${APPLICATION_NAME} disconnected:` console.error(`${APPLICATION_NAME} disconnected:`
, bridgePort.error.message); , bridgePort.error.message);
} else { } else {
console.log(`${APPLICATION_NAME} disconnected`); console.info(`${APPLICATION_NAME} disconnected`);
} }
}); });
@@ -430,17 +430,17 @@ async function onConnectShim (port) {
}); });
bridgePort.onMessage.addListener(message => { bridgePort.onMessage.addListener((message: any) => {
port.postMessage(message); port.postMessage(message);
}); });
port.onMessage.addListener(async message => { port.onMessage.addListener(async (message: any) => {
const [ destination ] = message.subject.split(":/"); const [ destination ] = message.subject.split(":/");
switch (destination) { switch (destination) {
case "bridge": { case "bridge": {
bridgePort.postMessage(message); bridgePort.postMessage(message);
break; break;
}; }
} }
switch (message.subject) { switch (message.subject) {
@@ -471,7 +471,7 @@ async function onConnectShim (port) {
} }
break; break;
}; }
default: { default: {
// TODO: Remove need for this // TODO: Remove need for this
@@ -487,7 +487,7 @@ async function onConnectShim (port) {
}); });
} }
function onConnectPopup (port) { function onConnectPopup (port: browser.runtime.Port) {
if (popupPort) { if (popupPort) {
popupPort.disconnect(); popupPort.disconnect();
} }
@@ -506,17 +506,17 @@ function onConnectPopup (port) {
browser.runtime.onConnect.addListener(port => { browser.runtime.onConnect.addListener(port => {
switch (port.name) { switch (port.name) {
case "shim": onConnectShim(port); break; case "shim": onConnectShim(port); break;
case "popup": onConnectPopup(port); break; case "popup": onConnectPopup(port); break;
} }
}); });
messageRouter.register("mirrorCast", message => { messageRouter.register("mirrorCast", (message: object) => {
browser.tabs.sendMessage(mirrorCastTabId, message browser.tabs.sendMessage(mirrorCastTabId, message
, { frameId: mirrorCastFrameId }); , { frameId: mirrorCastFrameId });
}); });
messageRouter.register("mediaCast", message => { messageRouter.register("mediaCast", (message: object) => {
browser.tabs.sendMessage(mediaCastTabId, message browser.tabs.sendMessage(mediaCastTabId, message
, { frameId: mediaCastFrameId }); , { frameId: mediaCastFrameId });
}); });

View File

@@ -6,7 +6,7 @@ const CopyWebpackPlugin = require("copy-webpack-plugin");
module.exports = (env) => ({ module.exports = (env) => ({
entry: { entry: {
"main" : `${env.includePath}/main.js` "main" : `${env.includePath}/main.ts`
, "popup/bundle" : `${env.includePath}/popup/index.jsx` , "popup/bundle" : `${env.includePath}/popup/index.jsx`
, "options/bundle" : `${env.includePath}/options/index.jsx` , "options/bundle" : `${env.includePath}/options/index.jsx`
, "updater/bundle" : `${env.includePath}/updater/index.jsx` , "updater/bundle" : `${env.includePath}/updater/index.jsx`

View File

@@ -11,9 +11,10 @@
, "max-classes-per-file": false , "max-classes-per-file": false
, "max-line-length": [ true, { , "max-line-length": [ true, {
"limit": 80 "limit": 80
, "ignore-pattern": "//" , "ignore-pattern": "//|.*\";$"
}] }]
, "no-console": [ true, "log" ] , "no-console": [ true, "log" ]
, "no-namespace": [ true, "allow-declarations" ]
, "object-literal-sort-keys": false , "object-literal-sort-keys": false
, "radix": false , "radix": false
, "semicolon": [ true, "always" ] , "semicolon": [ true, "always" ]