diff --git a/Composer/packages/electron-server/.gitignore b/Composer/packages/electron-server/.gitignore index d5bff0464b..a0029fa641 100644 --- a/Composer/packages/electron-server/.gitignore +++ b/Composer/packages/electron-server/.gitignore @@ -3,3 +3,5 @@ dist/ locales/en-US-pseudo.json l10ntemp/ oneauth-temp +customElectron +electron-builder-config-*.json diff --git a/Composer/packages/electron-server/electron-builder-config.json b/Composer/packages/electron-server/electron-builder-config.json index 3e7ab9c4f3..38d1f6bb61 100644 --- a/Composer/packages/electron-server/electron-builder-config.json +++ b/Composer/packages/electron-server/electron-builder-config.json @@ -3,9 +3,6 @@ "asar": true, "appId": "com.microsoft.botframework.composer", "copyright": "Copyright © 2020 Microsoft Corporation", - "electronDownload": { - "version": "8.2.4" - }, "directories": { "buildResources": "resources", "output": "dist" diff --git a/Composer/packages/electron-server/package.json b/Composer/packages/electron-server/package.json index 594b68bc50..7deb844410 100644 --- a/Composer/packages/electron-server/package.json +++ b/Composer/packages/electron-server/package.json @@ -48,7 +48,7 @@ "@types/node": "13.9.3", "@types/rimraf": "^2.0.2", "cross-env": "7.0.2", - "electron": "8.2.4", + "electron": "14.2.6", "electron-builder": "^22.6.0", "globby": "^11.0.1", "js-yaml": "^3.13.1", @@ -74,7 +74,7 @@ "node-fetch": "2.6.1", "semver": "7.3.2", "tslib": "2.0.3", - "uuid": "^8.3.1" + "uuid": "7.0.0" }, "peerDependencies": { "oneauth-mac": "1.11.0", diff --git a/Composer/packages/electron-server/scripts/createBuilderConfig.js b/Composer/packages/electron-server/scripts/createBuilderConfig.js new file mode 100644 index 0000000000..09e8f8f13e --- /dev/null +++ b/Composer/packages/electron-server/scripts/createBuilderConfig.js @@ -0,0 +1,35 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +const { join, resolve } = require('path'); +const { writeFileSync } = require('fs'); + +const packageJson = require('../package.json'); + +const electronVersion = packageJson.devDependencies.electron; + +const electronServerDir = resolve(__dirname, '..'); + +const createBuilderConfig = (platform) => { + const builderConfig = require('../electron-builder-config.json'); + const configName = `electron-builder-config-${platform}.json`; + switch (platform) { + case 'mac': + case 'linux': + builderConfig.electronDownload = { + version: electronVersion, + }; + break; + case 'win': + builderConfig.electronDist = 'customElectron'; + break; + default: + throw new Error( + `Invalid platform specified for builder config generation (${platform}). Supported platforms are: mac, linux and windows` + ); + } + writeFileSync(join(electronServerDir, configName), JSON.stringify(builderConfig, null, 2)); + return configName; +}; + +exports.createBuilderConfig = createBuilderConfig; diff --git a/Composer/packages/electron-server/scripts/downloadAndExtractElectron.js b/Composer/packages/electron-server/scripts/downloadAndExtractElectron.js new file mode 100644 index 0000000000..198d1da206 --- /dev/null +++ b/Composer/packages/electron-server/scripts/downloadAndExtractElectron.js @@ -0,0 +1,41 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +// Copyright (c) Microsoft. All rights reserved. +// Licensed under the MIT license. + +const { join } = require('path'); + +const { download } = require('@electron/get'); +const extract = require('extract-zip'); + +const packageJson = require('../package.json'); + +const { log } = require('./common'); + +const electronVersion = packageJson.devDependencies.electron; + +async function downloadAndExtract() { + // download the custom build of Electron + const zipPath = await download(electronVersion, { + mirrorOptions: { + mirror: process.env.MSFT_ELECTRON_MIRROR, + customDir: process.env.MSFT_ELECTRON_DIR, + }, + }); + log.info(`Electron successfully downloaded to ${zipPath}`); + + // extract the custom build into a local directory + const extractPath = join(__dirname, '..', 'customElectron'); + await extract(zipPath, { dir: extractPath }); + log.info(`Electron successfully unzipped in ${extractPath}`); + + return extractPath; +} + +downloadAndExtract() + .then((extractPath) => log.info(`Downloaded and extracted the internal Electron build to ${extractPath}`)) + .catch((err) => { + log.error(`Error downloading and extracting the internal Electron build: ${err}`); + throw err; + }); diff --git a/Composer/packages/electron-server/scripts/electronBuilderDist.js b/Composer/packages/electron-server/scripts/electronBuilderDist.js index 95bb1451ec..7b40ee3367 100644 --- a/Composer/packages/electron-server/scripts/electronBuilderDist.js +++ b/Composer/packages/electron-server/scripts/electronBuilderDist.js @@ -7,6 +7,7 @@ const { resolve } = require('path'); const { execSync } = require('child_process'); const { log } = require('./common'); +const { createBuilderConfig } = require('./createBuilderConfig'); /* * Calls electron-builder to take the pre-packed app contents and turn them into @@ -39,8 +40,9 @@ try { throw new Error('Platform detected is not Mac, Linux, or Windows.'); } - // call electron-builder . --prepackaged --config electron-builder-config.json - const cmd = `"${electronBuilderBinary}" --projectDir "${electronServerDir}" --${platform} --x64 --prepackaged "${unpackedAppDir}" --config electron-builder-config.json`; + const configName = createBuilderConfig(platform); + // call electron-builder . --prepackaged --config electron-builder-config-{platform}.json + const cmd = `"${electronBuilderBinary}" --projectDir "${electronServerDir}" --${platform} --x64 --prepackaged "${unpackedAppDir}" --config ${configName}`; log.info('Executing command: ', cmd); execSync(cmd, { stdio: 'inherit' }); // lgtm [js/shell-command-injection-from-environment] diff --git a/Composer/packages/electron-server/scripts/electronBuilderPack.js b/Composer/packages/electron-server/scripts/electronBuilderPack.js index f088106c7c..94d1114cc9 100644 --- a/Composer/packages/electron-server/scripts/electronBuilderPack.js +++ b/Composer/packages/electron-server/scripts/electronBuilderPack.js @@ -7,6 +7,7 @@ const { resolve } = require('path'); const { execSync } = require('child_process'); const { log } = require('./common'); +const { createBuilderConfig } = require('./createBuilderConfig'); /* * Calls electron-builder to pre-pack the app contents into what @@ -35,8 +36,9 @@ try { throw new Error('Platform detected is not Mac, Linux, or Windows.'); } - // call electron-builder . --dir --config electron-builder-config.json - const cmd = `"${electronBuilderBinary}" --projectDir "${electronServerDir}" --dir --${platform} --x64 --config electron-builder-config.json`; + const configName = createBuilderConfig(platform); + // call electron-builder . --prepackaged --config electron-builder-config-{platform}.json + const cmd = `"${electronBuilderBinary}" --projectDir "${electronServerDir}" --dir --${platform} --x64 --config ${configName}`; log.info('Executing command: ', cmd); execSync(cmd, { stdio: 'inherit' }); // lgtm [js/shell-command-injection-from-environment] diff --git a/Composer/packages/electron-server/scripts/sign-mac.js b/Composer/packages/electron-server/scripts/sign-mac.js index 535c6240da..6309e2a9e9 100644 --- a/Composer/packages/electron-server/scripts/sign-mac.js +++ b/Composer/packages/electron-server/scripts/sign-mac.js @@ -111,6 +111,7 @@ try { for (const fw of frameworks) { const fwPath = path.join(baseBundlePath, 'Contents/Frameworks', fw, 'Versions/A'); const dylibs = glob.sync('Libraries/*.dylib', { cwd: fwPath }); + const helpers = glob.sync('Helpers/*', { cwd: fwPath }); for (const lib of dylibs) { log.info(`codesign -s ******* --timestamp=none --force "${path.join(fwPath, lib)}"`); @@ -119,6 +120,13 @@ try { }); } + for (const lib of helpers) { + log.info(`codesign -s ******* --timestamp=none --force "${path.join(fwPath, lib)}"`); + execSync(`codesign -s $DEV_CERT_ID --timestamp=none --force "${path.join(fwPath, lib)}"`, { + stdio: 'inherit', + }); + } + log.info(`codesign -s ******* --timestamp=none --force "${fwPath}"`); execSync(`codesign -s $DEV_CERT_ID --timestamp=none --force "${fwPath}"`, { stdio: 'inherit', diff --git a/Composer/packages/electron-server/src/appMenu.ts b/Composer/packages/electron-server/src/appMenu.ts index 296b31764b..efc8fe9cf8 100644 --- a/Composer/packages/electron-server/src/appMenu.ts +++ b/Composer/packages/electron-server/src/appMenu.ts @@ -257,10 +257,10 @@ export function initAppMenu(win?: Electron.BrowserWindow) { ['Cut', 'Copy', 'Delete'].forEach((label) => { const nativeModeId = label + '-native'; const actionModeId = label; - menu.getMenuItemById(nativeModeId).visible = mode === 'native'; - menu.getMenuItemById(actionModeId).visible = mode === 'action'; + menu.getMenuItemById(nativeModeId)!.visible = mode === 'native'; + menu.getMenuItemById(actionModeId)!.visible = mode === 'action'; }); - menu.getMenuItemById('Paste-native').visible = mode === 'native'; + menu.getMenuItemById('Paste-native')!.visible = mode === 'native'; }; // Turn shortcuts to Action editing mode when Flow Editor is focused. @@ -271,7 +271,7 @@ export function initAppMenu(win?: Electron.BrowserWindow) { // Let menu enable/disable status reflects action selection states. const actionSelected = !!state.actionSelected; ['Cut', 'Copy', 'Delete'].forEach((id) => { - menu.getMenuItemById(id).enabled = actionSelected; + menu.getMenuItemById(id)!.enabled = actionSelected; }); } else { toggleEditingMode(menu, 'native'); @@ -279,9 +279,9 @@ export function initAppMenu(win?: Electron.BrowserWindow) { // Let menu undo/redo status reflects history status const canUndo = !!state.canUndo; - menu.getMenuItemById('Undo').enabled = canUndo; + menu.getMenuItemById('Undo')!.enabled = canUndo; const canRedo = !!state.canRedo; - menu.getMenuItemById('Redo').enabled = canRedo; + menu.getMenuItemById('Redo')!.enabled = canRedo; Menu.setApplicationMenu(menu); }); diff --git a/Composer/packages/electron-server/src/electronWindow.ts b/Composer/packages/electron-server/src/electronWindow.ts index 7a610382d9..f7b0ccee2a 100644 --- a/Composer/packages/electron-server/src/electronWindow.ts +++ b/Composer/packages/electron-server/src/electronWindow.ts @@ -35,6 +35,7 @@ export default class ElectronWindow { nodeIntegrationInWorker: false, nodeIntegration: false, preload: join(__dirname, 'preload.js'), + nativeWindowOpen: true, }, show: false, title: `Bot Framework Composer (v${app.getVersion()})`, diff --git a/Composer/packages/electron-server/src/splash/splashScreen.ts b/Composer/packages/electron-server/src/splash/splashScreen.ts index a66ca2bbfb..237d60f8fe 100644 --- a/Composer/packages/electron-server/src/splash/splashScreen.ts +++ b/Composer/packages/electron-server/src/splash/splashScreen.ts @@ -50,6 +50,7 @@ export const initSplashScreen = async ({ webPreferences: { // This is necessary to enable loading local images in the url protocol (window.loadURL) webSecurity: false, // lgtm [js/disabling-electron-websecurity] + nativeWindowOpen: true, }, }); diff --git a/Composer/yarn-berry.lock b/Composer/yarn-berry.lock index b4c895dac9..929ca60576 100644 --- a/Composer/yarn-berry.lock +++ b/Composer/yarn-berry.lock @@ -2530,7 +2530,7 @@ __metadata: cross-env: 7.0.2 crypto: ^1.0.1 debug: 4.1.1 - electron: 8.2.4 + electron: 14.2.6 electron-builder: ^22.6.0 electron-updater: 4.2.5 fix-path: ^3.0.0 @@ -2549,7 +2549,7 @@ __metadata: source-map-explorer: ^2.4.2 ts-node: ^8.4.1 tslib: 2.0.3 - uuid: ^8.3.1 + uuid: 7.0.0 peerDependencies: oneauth-mac: 1.11.0 oneauth-win64: 1.14.0 @@ -12208,16 +12208,16 @@ __metadata: languageName: node linkType: hard -"electron@npm:8.2.4": - version: 8.2.4 - resolution: "electron@npm:8.2.4" +"electron@npm:14.2.6": + version: 14.2.6 + resolution: "electron@npm:14.2.6" dependencies: "@electron/get": ^1.0.1 - "@types/node": ^12.0.12 + "@types/node": ^14.6.2 extract-zip: ^1.0.3 bin: electron: cli.js - checksum: 0adefca28eed9fe5a38fe89080ca79a5b29f0315716348f725c337cc4c82aad128da1579db2041f5a991a64b40b0409e2a06d0ba7a4bf9614de94b9b9c038253 + checksum: f0ce42459502f9f7d937374699eefbb56dacc03b21c7e7933f5a865c4f1f05aba00eafa3a217fa97d91559ffffe5f57ab17c2001a5e122118957932e360bb707 languageName: node linkType: hard @@ -27282,7 +27282,16 @@ __metadata: languageName: node linkType: hard -"uuid@npm:8.3.2, uuid@npm:^8.3.0, uuid@npm:^8.3.1, uuid@npm:^8.3.2": +"uuid@npm:7.0.0": + version: 7.0.0 + resolution: "uuid@npm:7.0.0" + bin: + uuid: dist/bin/uuid + checksum: ff663dd21aec8ca725b3bec22bbbabc21a2997a75ce49e839bf73420faf4b03cd919a7a8ad4e03c606485a695db56fb1e7bfd419742386df49145e98e8120e70 + languageName: node + linkType: hard + +"uuid@npm:8.3.2, uuid@npm:^8.3.0, uuid@npm:^8.3.2": version: 8.3.2 resolution: "uuid@npm:8.3.2" bin: diff --git a/Composer/yarn.lock b/Composer/yarn.lock index 290580f661..18e948f347 100644 --- a/Composer/yarn.lock +++ b/Composer/yarn.lock @@ -5408,7 +5408,7 @@ "@types/node" "*" form-data "^3.0.0" -"@types/node@*", "@types/node@13.9.3", "@types/node@^12.0.12", "@types/node@^14.14.31": +"@types/node@*", "@types/node@13.9.3", "@types/node@^14.14.31", "@types/node@^14.6.2": version "13.9.3" resolved "https://registry.yarnpkg.com/@types/node/-/node-13.9.3.tgz#6356df2647de9eac569f9a52eda3480fa9e70b4d" integrity sha512-01s+ac4qerwd6RHD+mVbOEsraDHSgUaefQlEdBbUolnQFjKwCr7luvAlEwW1RFojh67u0z4OUTjPn9LEl4zIkA== @@ -10861,13 +10861,13 @@ electron-updater@4.2.5: pako "^1.0.11" semver "^7.1.3" -electron@8.2.4: - version "8.2.4" - resolved "https://registry.yarnpkg.com/electron/-/electron-8.2.4.tgz#c4e51ca8e84b5a5beaaabdae1024bd52ba487ba4" - integrity sha512-Lle0InIgSAHZxD5KDY0wZ1A2Zlc6GHwMhAxoHMzn05mndyP1YBkCYHc0TDDofzUTrsLFofduPjlknO5Oj9fTPA== +electron@14.2.6: + version "14.2.6" + resolved "https://registry.yarnpkg.com/electron/-/electron-14.2.6.tgz#d134da424d79f2ea59758899a9ba0cf18170bbec" + integrity sha512-yTPmuBO6/7baUUjhQ1E2URsNjEPsj+DMcleLf3VexVPU1Py0mXc5OpwI6LCq/jvuwyGiXOLK2Vx6h4bel6DoEw== dependencies: "@electron/get" "^1.0.1" - "@types/node" "^12.0.12" + "@types/node" "^14.6.2" extract-zip "^1.0.3" elegant-spinner@^1.0.1: @@ -22837,6 +22837,11 @@ utils-merge@1.0.1: resolved "https://registry.yarnpkg.com/utils-merge/-/utils-merge-1.0.1.tgz#9f95710f50a267947b2ccc124741c1028427e713" integrity sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM= +uuid@7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/uuid/-/uuid-7.0.0.tgz#1833d4b9ce50b732bfaa271f9cb74e974d303c79" + integrity sha512-LNUrNsXdI/fUsypJbWM8Jt4DgQdFAZh41p9C7WE9Cn+CULOEkoG2lgQyH68v3wnIy5K3fN4jdSt270K6IFA3MQ== + uuid@8.3.2, uuid@^8.3.2: version "8.3.2" resolved "https://botbuilder.myget.org/F/botbuilder-v4-js-daily/npm/uuid/-/uuid-8.3.2.tgz#80d5b5ced271bb9af6c445f21a1a04c606cefbe2" @@ -22857,11 +22862,6 @@ uuid@^8.3.0: resolved "https://registry.yarnpkg.com/uuid/-/uuid-8.3.0.tgz#ab738085ca22dc9a8c92725e459b1d507df5d6ea" integrity sha512-fX6Z5o4m6XsXBdli9g7DtWgAx+osMsRRZFKma1mIUsLCz6vRvv+pz5VNbyu9UEDzpMWulZfvpgb/cmDXVulYFQ== -uuid@^8.3.1: - version "8.3.1" - resolved "https://registry.yarnpkg.com/uuid/-/uuid-8.3.1.tgz#2ba2e6ca000da60fce5a196954ab241131e05a31" - integrity sha512-FOmRr+FmWEIG8uhZv6C2bTgEVXsHk08kE7mPlrBbEe+c3r9pjceVPgupIfNIhc4yx55H69OXANrUaSuu9eInKg== - v8-compile-cache@^2.0.3: version "2.1.0" resolved "https://registry.yarnpkg.com/v8-compile-cache/-/v8-compile-cache-2.1.0.tgz#e14de37b31a6d194f5690d67efc4e7f6fc6ab30e"