From 88a5c68a1b1179095582e0248ea8434ae18a934c Mon Sep 17 00:00:00 2001 From: hensm Date: Tue, 11 Dec 2018 19:42:01 +0000 Subject: [PATCH] Centralize package info and do version checking between app/ext --- app/bin/build.js | 85 ++++++++++++++++++--- app/bin/install-manifest.js | 4 +- app/bin/lib/paths.js | 23 ++++-- app/package-lock.json | 14 +++- app/package.json | 6 ++ app/packaging/linux/deb/DEBIAN/control | 6 +- app/packaging/linux/rpm/fx_cast_bridge.spec | 20 ----- app/packaging/linux/rpm/package.spec | 20 +++++ app/packaging/mac/distribution.xml | 12 +-- app/packaging/mac/scripts/postinstall | 2 +- app/src/main.js | 12 +++ ext/build.js | 19 +++-- ext/package.json | 5 ++ ext/src/main.js | 47 ++++++++++-- ext/webpack.config.js | 14 ++-- package-lock.json | 6 ++ package.json | 3 +- 17 files changed, 222 insertions(+), 76 deletions(-) delete mode 100644 app/packaging/linux/rpm/fx_cast_bridge.spec create mode 100644 app/packaging/linux/rpm/package.spec diff --git a/app/bin/build.js b/app/bin/build.js index c2d454b..5102424 100644 --- a/app/bin/build.js +++ b/app/bin/build.js @@ -3,10 +3,14 @@ const os = require("os"); const path = require("path"); const minimist = require("minimist"); const glob = require("glob"); +const mustache = require("mustache"); const { spawnSync } = require("child_process"); const { exec: pkgExec } = require("pkg"); +const { __applicationName: applicationName + , __applicationVersion: applicationVersion } = require("../package.json"); + const { executableName , executablePath , manifestName @@ -126,10 +130,11 @@ function package (platform) { } function packageDarwin () { - const installerName = "fx_cast_bridge.pkg"; - const componentName = "fx_cast_bridge_component.pkg"; + const installerName = `${applicationName}.pkg`; + const componentName = `${applicationName}_component.pkg`; const packagingDir = path.join(__dirname, "../packaging/mac/"); + const packagingOutputDir = path.join(BUILD_PATH, "packaging"); // Create pkgbuild root const rootPath = path.join(BUILD_PATH, "root"); @@ -146,17 +151,41 @@ function packageDarwin () { fs.moveSync(path.join(BUILD_PATH, manifestName) , path.join(rootManifestPath, manifestName)); + + // Copy static files to be processed + fs.copySync(packagingDir, packagingOutputDir); + + const view = { + applicationName + , manifestName + , componentName + , packageId: `tf.matt.${applicationName}` + }; + + // Template paths + const templatePaths = [ + path.join(packagingOutputDir, "scripts/postinstall") + , path.join(packagingOutputDir, "distribution.xml") + ]; + + // Do templating on static files + for (const templatePath of templatePaths) { + const templateContent = fs.readFileSync(templatePath).toString(); + fs.writeFileSync(templatePath, mustache.render(templateContent, view)); + } + + // Build component package spawnSync( `pkgbuild --root ${rootPath} ` - + `--identifier "tf.matt.fx_cast_bridge" ` - + `--version "0.0.1" ` - + `--scripts ${path.join(packagingDir, "scripts")} ` + + `--identifier "tf.matt.${applicationName}" ` + + `--version "${applicationVersion}" ` + + `--scripts ${path.join(packagingOutputDir, "scripts")} ` + `${path.join(BUILD_PATH, componentName)}` , { shell: true }); // Distribution XML file - const distFilePath = path.join(packagingDir, "distribution.xml"); + const distFilePath = path.join(packagingOutputDir, "distribution.xml"); // Build installer package spawnSync( @@ -170,7 +199,7 @@ function packageDarwin () { } function packageLinuxDeb () { - const installerName = "fx_cast_bridge.deb"; + const installerName = `${applicationName}.deb`; // Create root const rootPath = path.join(BUILD_PATH, "root"); @@ -186,9 +215,26 @@ function packageLinuxDeb () { fs.moveSync(path.join(BUILD_PATH, manifestName) , path.join(rootManifestPath, manifestName)); + + const controlDir = path.join(__dirname, "../packaging/linux/deb/DEBIAN/"); + const controlOutputDir = path.join(rootPath, path.basename(controlDir)); + const controlFilePath = path.join(controlOutputDir, "control"); + // Copy package info to root - fs.copySync(path.join(__dirname, "../packaging/linux/deb/DEBIAN/") - , path.join(rootPath, "DEBIAN")); + fs.copySync(controlDir, controlOutputDir); + + const view = { + // Debian package names can't contain underscores + packageName: applicationName.replace(/_/g, "-") + , applicationName + , applicationVersion + }; + + // Do templating on control file + fs.writeFileSync(controlFilePath + , mustache.render( + fs.readFileSync(controlFilePath).toString() + , view)); // Build .deb package spawnSync( @@ -201,10 +247,27 @@ function packageLinuxDeb () { function packageLinuxRpm () { const specPath = path.join(__dirname - , "../packaging/linux/rpm/fx_cast_bridge.spec"); + , "../packaging/linux/rpm/package.spec"); + + const specOutputPath = path.join(BUILD_PATH, path.basename(specPath)); + + const view = { + packageName: applicationName + , applicationName + , applicationVersion + , executablePath: executablePath["linux"] + , manifestPath: manifestPath["linux"] + , executableName: executableName["linux"] + , manifestName + }; + + fs.writeFileSync(specOutputPath + , mustache.render( + fs.readFileSync(specPath).toString() + , view)); spawnSync( - `rpmbuild -bb ${specPath} ` + `rpmbuild -bb ${specOutputPath} ` + `--define "_distdir ${BUILD_PATH}" ` + `--define "_rpmdir ${BUILD_PATH}" ` , { shell: true }); diff --git a/app/bin/install-manifest.js b/app/bin/install-manifest.js index 4caaebc..a9088a0 100644 --- a/app/bin/install-manifest.js +++ b/app/bin/install-manifest.js @@ -5,7 +5,8 @@ const minimist = require("minimist"); const { manifestName , manifestPath - , DIST_PATH } = require("./lib/paths"); + , DIST_PATH + , WIN_REGISTRY_KEY } = require("./lib/paths"); const argv = minimist(process.argv.slice(2), { @@ -17,7 +18,6 @@ const argv = minimist(process.argv.slice(2), { const CURRENT_MANIFEST_PATH = path.join(DIST_PATH, manifestName); -const WIN_REGISTRY_KEY = "fx_cast_bridge"; if (!fs.existsSync(CURRENT_MANIFEST_PATH) && !argv.remove) { diff --git a/app/bin/lib/paths.js b/app/bin/lib/paths.js index 3e8a97e..406c985 100644 --- a/app/bin/lib/paths.js +++ b/app/bin/lib/paths.js @@ -1,23 +1,30 @@ const path = require("path"); +const { __applicationName + , __applicationDirectoryName + , __applicationExecutableName } = require("../../package.json"); + + exports.DIST_PATH = path.join(__dirname, "../../../dist/app"); +exports.WIN_REGISTRY_KEY = __applicationName; + exports.executableName = { - win32: "bridge.exe" - , darwin: "bridge" - , linux: "bridge" + win32: `${__applicationExecutableName}.exe` + , darwin: __applicationExecutableName + , linux: __applicationExecutableName }; exports.executablePath = { - win32: "C:\\Program Files\\fx_cast\\" - , darwin: "/Library/Application Support/fx_cast/" - , linux: "/opt/fx_cast/" + win32: `C:\\Program Files\\${__applicationDirectoryName}\\` + , darwin: `/Library/Application Support/${__applicationDirectoryName}/` + , linux: `/opt/${__applicationDirectoryName}/` }; -exports.manifestName = "fx_cast_bridge.json"; +exports.manifestName = `${__applicationName}.json`; exports.manifestPath = { - win32: "C:\\Program Files\\fx_cast\\" + win32: `C:\\Program Files\\${__applicationDirectoryName}\\` , darwin: "/Library/Application Support/Mozilla/NativeMessagingHosts/" , linux: "/usr/lib/mozilla/native-messaging-hosts/" }; diff --git a/app/package-lock.json b/app/package-lock.json index 5630a01..7eb6577 100644 --- a/app/package-lock.json +++ b/app/package-lock.json @@ -1,6 +1,6 @@ { - "lockfileVersion": 1, "requires": true, + "lockfileVersion": 1, "dependencies": { "@babel/cli": { "version": "7.2.0", @@ -3033,6 +3033,12 @@ "readable-stream": "^2.0.5" } }, + "mustache": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/mustache/-/mustache-3.0.1.tgz", + "integrity": "sha512-jFI/4UVRsRYdUbuDTKT7KzfOp7FiD5WzYmmwNwXyUVypC0xjoTL78Fqc0jHUPIvvGD+6DQSPHIt1NE7D1ArsqA==", + "dev": true + }, "nan": { "version": "2.11.1", "resolved": "https://registry.npmjs.org/nan/-/nan-2.11.1.tgz", @@ -3524,7 +3530,7 @@ "dependencies": { "jsesc": { "version": "0.5.0", - "resolved": "http://registry.npmjs.org/jsesc/-/jsesc-0.5.0.tgz", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-0.5.0.tgz", "integrity": "sha1-597mbjXW/Bb3EP6R1c9p9w8IkR0=", "dev": true } @@ -3616,7 +3622,7 @@ }, "safe-regex": { "version": "1.1.0", - "resolved": "http://registry.npmjs.org/safe-regex/-/safe-regex-1.1.0.tgz", + "resolved": "https://registry.npmjs.org/safe-regex/-/safe-regex-1.1.0.tgz", "integrity": "sha1-QKNmnzsHfR6UPURinhV91IAjvy4=", "dev": true, "requires": { @@ -3886,7 +3892,7 @@ }, "string_decoder": { "version": "1.1.1", - "resolved": "http://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", "dev": true, "requires": { diff --git a/app/package.json b/app/package.json index 7971803..d3964e3 100644 --- a/app/package.json +++ b/app/package.json @@ -1,4 +1,9 @@ { + "__applicationName": "fx_cast_bridge", + "__applicationVersion": "0.0.1", + "__applicationDirectoryName": "fx_cast", + "__applicationExecutableName": "bridge", + "scripts": { "build": "node bin/build.js", "package": "node bin/build.js --package", @@ -22,6 +27,7 @@ "@babel/register": "^7.0.0", "glob": "^7.1.3", "minimist": "^1.2.0", + "mustache": "^3.0.1", "pkg": "^4.3.5" }, "optionalDependencies": { diff --git a/app/packaging/linux/deb/DEBIAN/control b/app/packaging/linux/deb/DEBIAN/control index be8d49f..03346cf 100644 --- a/app/packaging/linux/deb/DEBIAN/control +++ b/app/packaging/linux/deb/DEBIAN/control @@ -1,5 +1,5 @@ -Package: fx-cast-bridge -Version: 0.0.1 +Package: {{packageName}} +Version: {{applicationVersion}} Priority: optional Architecture: amd64 -Description: fx_cast Bridge application +Description: {{applicationName}} diff --git a/app/packaging/linux/rpm/fx_cast_bridge.spec b/app/packaging/linux/rpm/fx_cast_bridge.spec deleted file mode 100644 index d644e30..0000000 --- a/app/packaging/linux/rpm/fx_cast_bridge.spec +++ /dev/null @@ -1,20 +0,0 @@ -Name: fx_cast_bridge -Summary: fx_cast Bridge application -Version: 0.0.1 -Release: 1 -License: MIT - -%description -fx_cast Bridge application - -%install -rm -rf $RPM_BUILD_ROOT -mkdir -p $RPM_BUILD_ROOT/opt/fx_cast/ \ - $RPM_BUILD_ROOT/usr/lib/mozilla/native-messaging-hosts/ - -cp %{_distdir}/bridge $RPM_BUILD_ROOT/opt/fx_cast/ -cp %{_distdir}/fx_cast_bridge.json $RPM_BUILD_ROOT/usr/lib/mozilla/native-messaging-hosts/ - -%files -/opt/fx_cast/bridge -/usr/lib/mozilla/native-messaging-hosts/fx_cast_bridge.json diff --git a/app/packaging/linux/rpm/package.spec b/app/packaging/linux/rpm/package.spec new file mode 100644 index 0000000..5bebc44 --- /dev/null +++ b/app/packaging/linux/rpm/package.spec @@ -0,0 +1,20 @@ +Name: {{packageName}} +Summary: {{applicationName}} +Version: {{applicationVersion}} +Release: 1 +License: MIT + +%description +{{applicationName}} + +%install +rm -rf $RPM_BUILD_ROOT +mkdir -p $RPM_BUILD_ROOT/{{{executablePath}}} \ + $RPM_BUILD_ROOT/{{{manifestPath}}} + +cp %{_distdir}/{{{executableName}}} $RPM_BUILD_ROOT/{{{executablePath}}} +cp %{_distdir}/{{{manifestName}}} $RPM_BUILD_ROOT/{{{manifestPath}}} + +%files +{{{executablePath}}}/{{{executableName}}} +{{{manifestPath}}}/{{{manifestName}}} diff --git a/app/packaging/mac/distribution.xml b/app/packaging/mac/distribution.xml index cec0ecb..239dcb6 100644 --- a/app/packaging/mac/distribution.xml +++ b/app/packaging/mac/distribution.xml @@ -1,17 +1,17 @@ - fx_cast Bridge + {{applicationName}} - + - + - - + + - fx_cast_bridge_default.pkg + {{componentName}} diff --git a/app/packaging/mac/scripts/postinstall b/app/packaging/mac/scripts/postinstall index a859cb4..c18e5dc 100755 --- a/app/packaging/mac/scripts/postinstall +++ b/app/packaging/mac/scripts/postinstall @@ -3,7 +3,7 @@ # If the target location isn't root, we need to rewrite # the manifest path to point to the user directory. if [ "$2" != "/" ]; then - manifestPath=$2"/Library/Application Support/Mozilla/NativeMessagingHosts/fx_cast_bridge.json" + manifestPath=$2"/Library/Application Support/Mozilla/NativeMessagingHosts/{{{manifestName}}}" sed -i.bak 's,"path": "/Library,"path": "'$2'/Library,g' "$manifestPath" rm "$manifestPath.bak" fi diff --git a/app/src/main.js b/app/src/main.js index 9bac810..0e3252d 100755 --- a/app/src/main.js +++ b/app/src/main.js @@ -8,6 +8,9 @@ import * as transforms from "./transforms"; import Media from "./Media"; import Session from "./Session"; +import { __applicationName + , __applicationVersion } from "../package.json"; + const browser = createBrowser(tcp("googlecast")); @@ -94,6 +97,15 @@ async function handleMessage (message) { switch (message.subject) { + case "bridge:initialize": { + const extensionVersion = message.data; + + return { + subject: "main:bridgeInitialized" + , data: __applicationVersion + }; + }; + case "bridge:discover": browser.discover(); break; diff --git a/ext/build.js b/ext/build.js index f0f0746..1a96483 100644 --- a/ext/build.js +++ b/ext/build.js @@ -4,6 +4,9 @@ const minimist = require("minimist"); const webpack = require("webpack"); const webExt = require("web-ext").default; +const package = require("./package.json"); +const appPackage = require("../app/package.json"); + const DIST_PATH = path.join(__dirname, "../dist/ext"); const UNPACKED_PATH = path.join(DIST_PATH, "unpacked"); @@ -13,10 +16,10 @@ const argv = minimist(process.argv.slice(2), { boolean: [ "package", "watch" ] , string: [ "mirroringAppId", "mode" ] , default: { - package: false // Should package with web-ext - , watch: false // Should run webpack in watch mode - , mirroringAppId: "19A6F4AE" // Chromecast mirroring receiver app ID - , mode: "development" // webpack mode + package: false // Should package with web-ext + , watch: false // Should run webpack in watch mode + , mirroringAppId: package.__mirroringAppId // Chromecast receiver app ID + , mode: "development" // webpack mode } }); @@ -41,9 +44,11 @@ const webpackConfig = require("./webpack.config.js")({ ? UNPACKED_PATH : DIST_PATH - , extensionName: "fx_cast" - , extensionId: "fx_cast@matt.tf" - , extensionVersion: "0.0.1" + , extensionName: package.__extensionName + , extensionId: package.__extensionId + , extensionVersion: package.__extensionVersion + , applicationName: appPackage.__applicationName + , applicationVersion: appPackage.__applicationVersion , mirroringAppId: argv.mirroringAppId }); diff --git a/ext/package.json b/ext/package.json index e9b3a12..b267bb5 100644 --- a/ext/package.json +++ b/ext/package.json @@ -1,4 +1,9 @@ { + "__extensionName": "fx_cast", + "__extensionId": "fx_cast@matt.tf", + "__extensionVersion": "0.0.1", + "__mirroringAppId": "19A6F4AE", + "scripts": { "build": "node build.js", "package": "node build.js --package", diff --git a/ext/src/main.js b/ext/src/main.js index b661bd3..d515d8a 100755 --- a/ext/src/main.js +++ b/ext/src/main.js @@ -3,6 +3,9 @@ import defaultOptions from "./options/defaultOptions"; import messageRouter from "./messageRouter"; +import semver from "semver"; + + const _ = browser.i18n.getMessage; @@ -277,7 +280,7 @@ browser.menus.onClicked.addListener(async (info, tab) => { await browser.tabs.executeScript(tab.id, { code: `let selectedMedia = "${info.pageUrl ? "tab" : "screen"}"; - let FX_CAST_RECEIVER_APP_ID = "${options.mirroringEnabled}";` + let FX_CAST_RECEIVER_APP_ID = "${options.mirroringAppId}";` , frameId }); @@ -329,19 +332,25 @@ function initBridge (tabId, frameId) { bridgeMap.delete(tabId); } - const port = browser.runtime.connectNative("fx_cast_bridge"); + const port = browser.runtime.connectNative(APPLICATION_NAME); if (port.error) { - console.error("Failed connect to fx_cast_bridge:", port.error.message); + console.error(`Failed connect to ${APPLICATION_NAME}:`, port.error.message); } else { bridgeMap.set(tabId, port); } + // Start version handoff + port.postMessage({ + subject: "bridge:initialize" + , data: EXTENSION_VERSION + }); + port.onDisconnect.addListener(p => { if (p.error) { - console.error("fx_cast_bridge disconnected:", p.error.message); + console.error(`${APPLICATION_NAME} disconnected:`, p.error.message); } else { - console.log("fx_cast_bridge disconnected"); + console.log(`${APPLICATION_NAME} disconnected`); } bridgeMap.delete(tabId); @@ -414,17 +423,39 @@ async function openPopup (tabId) { messageRouter.register("main", async (message, sender) => { - const tabId = sender.tab.id; + const tabId = sender && sender.tab.id; switch (message.subject) { - case "main:initialize": + case "main:initialize": { initBridge(tabId, sender.tab.frameId); break; + }; + + case "main:bridgeInitialized": { + const applicationVersion = message.data; + + /** + * Compare installed bridge version to the version the + * extension was built alongside and is known to be + * compatible with. + * + * TODO: Determine compatibility with semver and enforce/notify + * user. + */ + if (applicationVersion !== APPLICATION_VERSION) { + console.error(`Expecting ${APPLICATION_NAME} v${APPLICATION_VERSION}, found v${applicationVersion}.` + , semver.lt(applicationVersion, APPLICATION_VERSION) + ? "Try updating the native app to the latest version." + : "Try updating the extension to the latest version"); + } + + break; + }; case "main:openPopup": { await openPopup(tabId); break; - } + }; } }); diff --git a/ext/webpack.config.js b/ext/webpack.config.js index 554f34e..48bc5bb 100755 --- a/ext/webpack.config.js +++ b/ext/webpack.config.js @@ -25,10 +25,12 @@ module.exports = (env) => ({ } , plugins: [ new webpack.DefinePlugin({ - "EXTENSION_NAME" : JSON.stringify(env.extensionName) - , "EXTENSION_ID" : JSON.stringify(env.extensionId) - , "EXTENSION_VERSION" : JSON.stringify(env.extensionVersion) - , "MIRRORING_APP_ID" : JSON.stringify(env.mirroringAppId) + "EXTENSION_NAME" : JSON.stringify(env.extensionName) + , "EXTENSION_ID" : JSON.stringify(env.extensionId) + , "EXTENSION_VERSION" : JSON.stringify(env.extensionVersion) + , "MIRRORING_APP_ID" : JSON.stringify(env.mirroringAppId) + , "APPLICATION_NAME" : JSON.stringify(env.applicationName) + , "APPLICATION_VERSION" : JSON.stringify(env.applicationVersion) }) // Copy static assets @@ -43,7 +45,9 @@ module.exports = (env) => ({ .replace("EXTENSION_NAME", env.extensionName) .replace("EXTENSION_ID", env.extensionId) .replace("EXTENSION_VERSION", env.extensionVersion) - .replace("MIRRORING_APP_ID", env.mirroringAppId)); + .replace("MIRRORING_APP_ID", env.mirroringAppId) + .replace("APPLICATION_NAME", env.applicationName) + .replace("APPLICATION_VERSION", env.applicationVersion)); } return content; diff --git a/package-lock.json b/package-lock.json index 7e151ba..396c76d 100644 --- a/package-lock.json +++ b/package-lock.json @@ -237,6 +237,12 @@ "xml2js": "^0.4.17" } }, + "semver": { + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.6.0.tgz", + "integrity": "sha512-RS9R6R35NYgQn++fkDWaOmqGoj4Ek9gGs+DPxNUZKuwE183xjJroKvyo1IzVFeXvUrvmALy6FWD5xrdJT25gMg==", + "dev": true + }, "string_decoder": { "version": "0.10.31", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", diff --git a/package.json b/package.json index 0656bef..e5a5171 100644 --- a/package.json +++ b/package.json @@ -16,6 +16,7 @@ "devDependencies": { "fs-extra": "^7.0.1", "jasmine": "^3.3.0", - "selenium-webdriver": "^4.0.0-alpha.1" + "selenium-webdriver": "^4.0.0-alpha.1", + "semver": "^5.6.0" } }