diff --git a/installer/mac/preinstall.sh b/installer/mac/preinstall.sh index 42813dd9..204e1388 100755 --- a/installer/mac/preinstall.sh +++ b/installer/mac/preinstall.sh @@ -12,7 +12,7 @@ delete_app() compare_versions() { # Get the installer version: - CURRENT_VERSION=3.3.2 + CURRENT_VERSION=3.4.0 # Get the currently installed version: INSTALLED_VERSION=$(plutil -p /Applications/Symphony.app/Contents/Info.plist | awk '/CFBundleShortVersionString/ {print substr($3, 2, length($3)-2)}') diff --git a/js/cryptoLib.js b/js/cryptoLib.js index 15a41105..6cc9f673 100644 --- a/js/cryptoLib.js +++ b/js/cryptoLib.js @@ -106,7 +106,6 @@ const EncryptDecrypt = function (name, Base64IV, Base64AAD, Base64Key, Base64In) if (resultCode < 0) { log.send(logLevels.ERROR, `AESEncryptGCM, Failed to encrypt with exit code ${resultCode}`); } - log.send(logLevels.INFO, `Output from AESEncryptGCM ${resultCode}`); const bufferArray = [OutPtr, Tag]; return Buffer.concat(bufferArray).toString('base64'); } @@ -121,7 +120,6 @@ const EncryptDecrypt = function (name, Base64IV, Base64AAD, Base64Key, Base64In) if (resultCode < 0) { log.send(logLevels.ERROR, `AESDecryptGCM, Failed to decrypt with exit code ${resultCode}`); } - log.send(logLevels.INFO, `Output from AESDecryptGCM ${resultCode}`); return OutPtr.toString('base64'); } diff --git a/js/main.js b/js/main.js index 40653a04..08a0784d 100644 --- a/js/main.js +++ b/js/main.js @@ -26,7 +26,6 @@ const log = require('./log.js'); const logLevels = require('./enums/logLevels.js'); const autoLaunch = require('./autoLaunch'); const { handleCacheFailureCheckOnStartup, handleCacheFailureCheckOnExit} = require('./cacheHandler'); -const { monitorNetworkRequest } = require('./memoryMonitor'); require('electron-dl')(); @@ -52,6 +51,10 @@ require('./mainApiMgr.js'); require('./memoryMonitor.js'); const windowMgr = require('./windowMgr.js'); +const SpellChecker = require('./spellChecker').SpellCheckHelper; +const spellchecker = new SpellChecker(); +const { ContextMenuBuilder } = require('electron-spellchecker'); +const i18n = require('./translation/i18n'); getConfigField('url') .then(initializeCrashReporter) @@ -200,8 +203,7 @@ app.on('ready', () => { electron.powerMonitor.on('unlock-screen', () => { eventEmitter.emit('sys-unlocked'); }); - // Keeps track of active network request - monitorNetworkRequest(); + checkFirstTimeLaunch() .then(readConfigThenOpenMainWindow) .catch(readConfigThenOpenMainWindow); @@ -249,6 +251,32 @@ app.on('open-url', function (event, url) { handleProtocolAction(url); }); +app.on('web-contents-created', function (event, webContents) { + onWebContent(webContents); +}); + +function onWebContent(webContents) { + spellchecker.initializeSpellChecker(); + spellchecker.updateContextMenuLocale(i18n.getMessageFor('ContextMenu')); + const contextMenuBuilder = new ContextMenuBuilder(spellchecker.spellCheckHandler, webContents, false, spellchecker.processMenu.bind(spellchecker)); + let currentLocale = i18n.getLanguage(); + + const contextMenuListener = (event, info) => { + if (currentLocale !== i18n.getLanguage()) { + contextMenuBuilder.setAlternateStringFormatter(spellchecker.getStringTable(i18n.getMessageFor('ContextMenu'))); + spellchecker.updateContextMenuLocale(i18n.getMessageFor('ContextMenu')); + currentLocale = i18n.getLanguage(); + } + contextMenuBuilder.showPopupMenu(info); + }; + + webContents.on('context-menu', contextMenuListener); + + webContents.once('destroyed', () => { + webContents.removeListener('context-menu', contextMenuListener); + }); +} + /** * Reads the config fields that are required for the menu items * then opens the main window diff --git a/js/mainApiMgr.js b/js/mainApiMgr.js index a67459e1..27e19077 100644 --- a/js/mainApiMgr.js +++ b/js/mainApiMgr.js @@ -154,8 +154,9 @@ electron.ipcMain.on(apiName, (event, arg) => { case apiCmds.optimizeMemoryConsumption: if (typeof arg.memory === 'object' && typeof arg.cpuUsage === 'object' - && typeof arg.memory.workingSetSize === 'number') { - setPreloadMemoryInfo(arg.memory, arg.cpuUsage); + && typeof arg.memory.workingSetSize === 'number' + && typeof arg.activeRequests === 'number') { + setPreloadMemoryInfo(arg.memory, arg.cpuUsage, arg.activeRequests); } break; case apiCmds.optimizeMemoryRegister: diff --git a/js/memoryMonitor.js b/js/memoryMonitor.js index 9abcb4fe..e4e48b52 100644 --- a/js/memoryMonitor.js +++ b/js/memoryMonitor.js @@ -1,6 +1,5 @@ 'use strict'; -const { session } = require('electron'); const eventEmitter = require('./eventEmitter'); const log = require('./log.js'); @@ -19,7 +18,6 @@ let appMinimizedTimer; let powerMonitorTimer; let preloadMemory; let preloadWindow; -let networkRequestCount = 0; // once a minute setInterval(gatherMemory, 1000 * 60); @@ -51,13 +49,14 @@ function optimizeMemory() { const memoryConsumed = (preloadMemory.memoryInfo && preloadMemory.memoryInfo.workingSetSize / 1024) || 0; const cpuUsagePercentage = preloadMemory.cpuUsage.percentCPUUsage; + const activeNetworkRequest = preloadMemory.activeRequests === 0; if (memoryConsumed > maxMemory && cpuUsagePercentage <= cpuUsageThreshold && !isInMeeting && getIsOnline() && canReload - && networkRequestCount <= 0 + && activeNetworkRequest ) { getConfigField('memoryRefresh') .then((enabled) => { @@ -70,7 +69,7 @@ function optimizeMemory() { memory consumption was ${memoryConsumed} CPU usage percentage was ${preloadMemory.cpuUsage.percentCPUUsage} user was in a meeting? ${isInMeeting} - pending network request on the client was ${networkRequestCount} + pending network request on the client was ${preloadMemory.activeRequests} is network online? ${getIsOnline()}`); mainWindow.reload(); @@ -89,7 +88,7 @@ function optimizeMemory() { memory consumption was ${memoryConsumed} CPU usage percentage was ${preloadMemory.cpuUsage.percentCPUUsage} user was in a meeting? ${isInMeeting} - pending network request on the client was ${networkRequestCount} + pending network request on the client was ${preloadMemory.activeRequests} is network online? ${getIsOnline()}`); } } @@ -107,10 +106,11 @@ function setIsInMeeting(meetingStatus) { * * @param memoryInfo - memory consumption of the preload main script * @param cpuUsage - CPU usage of the preload main script + * @param activeRequests - pending active network requests on the client */ -function setPreloadMemoryInfo(memoryInfo, cpuUsage) { +function setPreloadMemoryInfo(memoryInfo, cpuUsage, activeRequests) { log.send(logLevels.INFO, 'Memory info received from preload process now running optimize memory logic'); - preloadMemory = { memoryInfo, cpuUsage }; + preloadMemory = { memoryInfo, cpuUsage, activeRequests }; optimizeMemory(); } @@ -189,44 +189,8 @@ function requestMemoryInfo() { } } -/** - * Monitors and Keeps track of active network requests - */ -function monitorNetworkRequest() { - let ids = []; - - // network request started - session.defaultSession.webRequest.onSendHeaders((details) => { - networkRequestCount++; - ids.push(details.id); - }); - - // decrease network request count on complete - session.defaultSession.webRequest.onCompleted((details) => { - if (ids.includes(details.id)) { - networkRequestCount--; - ids = ids.filter((value) => value !== details.id); - } - }); - - // decrease network request count on error - session.defaultSession.webRequest.onErrorOccurred((details) => { - if (ids.includes(details.id)) { - networkRequestCount--; - ids = ids.filter((value) => value !== details.id); - } - }); - - // Resets network request on redirect - session.defaultSession.webRequest.onBeforeRedirect(() => { - networkRequestCount = 0; - ids = []; - }); -} - module.exports = { setIsInMeeting, setPreloadMemoryInfo, setPreloadWindow, - monitorNetworkRequest, }; \ No newline at end of file diff --git a/js/preload/preloadMain.js b/js/preload/preloadMain.js index d5db298c..70d3f49a 100644 --- a/js/preload/preloadMain.js +++ b/js/preload/preloadMain.js @@ -31,7 +31,6 @@ const KeyCodes = { let Search; let SearchUtils; let CryptoLib; -let spellChecker; let isAltKey = false; let isMenuOpen = false; @@ -60,24 +59,6 @@ try { require('../downloadManager'); let snackBar; -/** - * Loads up the spell checker module - */ -function loadSpellChecker() { - try { - /* eslint-disable global-require */ - const SpellCheckerHelper = require('../spellChecker').SpellCheckHelper; - /* eslint-enable global-require */ - // Method to initialize spell checker - spellChecker = new SpellCheckerHelper(); - spellChecker.initializeSpellChecker(); - } catch (err) { - /* eslint-disable no-console */ - console.error('unable to load the spell checker module, hence, skipping the spell check feature ' + err); - /* eslint-enable no-console */ - } -} - // hold ref so doesn't get GC'ed const local = { ipcRenderer: ipcRenderer @@ -102,7 +83,6 @@ const throttledSetIsInMeetingStatus = throttle(1000, function (isInMeeting) { * an event triggered by the main process onload event */ local.ipcRenderer.on('on-page-load', () => { - loadSpellChecker(); snackBar = new SnackBar(); // only registers main window's preload @@ -366,6 +346,18 @@ function createAPI() { throttledSetLocale(locale); } }, + + /** + * Allows JS to register activeRequests that can be used by electron to + * get the active network request from the client + * + * @param activeRequests + */ + registerActiveRequests: function (activeRequests) { + if (typeof activeRequests === 'function') { + local.activeRequests = activeRequests; + } + }, }; // add support for both ssf and SYM_API name-space. @@ -487,10 +479,6 @@ function createAPI() { if (dataObj.titleBar) { titleBar.updateLocale(dataObj.titleBar); } - - if (dataObj.contextMenu && spellChecker) { - spellChecker.updateContextMenuLocale(dataObj.contextMenu); - } } }); @@ -518,10 +506,12 @@ function createAPI() { if (window.name === 'main') { const memory = process.getProcessMemoryInfo(); const cpuUsage = process.getCPUUsage(); + const activeRequests = local.activeRequests(); local.ipcRenderer.send(apiName, { cmd: apiCmds.optimizeMemoryConsumption, memory, cpuUsage, + activeRequests, }); } }); diff --git a/js/spellChecker/index.js b/js/spellChecker/index.js index b9701dce..78fff6ad 100644 --- a/js/spellChecker/index.js +++ b/js/spellChecker/index.js @@ -1,7 +1,6 @@ -const { remote } = require('electron'); -const { MenuItem } = remote; +const { app, MenuItem } = require('electron'); const { isMac } = require('./../utils/misc'); -const { SpellCheckHandler, ContextMenuListener, ContextMenuBuilder } = require('electron-spellchecker'); +const { SpellCheckHandler } = require('electron-spellchecker'); const stringFormat = require('./../utils/stringFormat'); class SpellCheckHelper { @@ -18,7 +17,6 @@ class SpellCheckHelper { */ initializeSpellChecker() { this.spellCheckHandler.automaticallyIdentifyLanguages = false; - this.spellCheckHandler.attachToInput(); // This is only for window as in mac the // language is switched w.r.t to the current system language. @@ -26,14 +24,9 @@ class SpellCheckHelper { // In windows we need to implement RxJS observable // in order to switch language dynamically if (!isMac) { - const sysLocale = remote.app.getLocale() || 'en-US'; + const sysLocale = app.getLocale() || 'en-US'; this.spellCheckHandler.switchLanguage(sysLocale); } - - this.contextMenuBuilder = new ContextMenuBuilder(this.spellCheckHandler, null, false, this.processMenu.bind(this)); - this.contextMenuListener = new ContextMenuListener((info) => { - this.contextMenuBuilder.showPopupMenu(info); - }); } /** @@ -42,7 +35,6 @@ class SpellCheckHelper { */ updateContextMenuLocale(content) { this.localeContent = content; - this.contextMenuBuilder.setAlternateStringFormatter(SpellCheckHelper.getStringTable(content)); } /** @@ -51,7 +43,8 @@ class SpellCheckHelper { * @param content {Object} - locale content for context menu * @return {Object} - String table for context menu */ - static getStringTable(content) { + // eslint-disable-next-line class-methods-use-this + getStringTable(content) { return { copyMail: () => content['Copy Email Address'] || `Copy Email Address`, copyLinkUrl: () => content['Copy Link'] || 'Copy Link', diff --git a/js/windowMgr.js b/js/windowMgr.js index 5b3b9dcc..3cd87c6a 100644 --- a/js/windowMgr.js +++ b/js/windowMgr.js @@ -21,7 +21,7 @@ const notify = require('./notify/electron-notify.js'); const eventEmitter = require('./eventEmitter'); const throttle = require('./utils/throttle.js'); const { getConfigField, updateConfigField, readConfigFileSync, getMultipleConfigField } = require('./config.js'); -const { isMac, isNodeEnv, isWindowsOS, isDevEnv } = require('./utils/misc'); +const { isMac, isWindowsOS, isDevEnv } = require('./utils/misc'); const { isWhitelisted, parseDomain } = require('./utils/whitelistHandler'); const { initCrashReporterMain, initCrashReporterRenderer } = require('./crashReporter.js'); const i18n = require('./translation/i18n'); @@ -41,7 +41,6 @@ let boundsChangeWindow; let alwaysOnTop = false; let position = 'lower-right'; let display; -let sandboxed = false; let isAutoReload = false; let devToolsEnabled = true; let isCustomTitleBarEnabled = true; @@ -163,10 +162,9 @@ function doCreateMainWindow(initialUrl, initialBounds, isCustomTitleBar) { frame: !isCustomTitleBarEnabled, alwaysOnTop: false, webPreferences: { - sandbox: sandboxed, - nodeIntegration: isNodeEnv, + sandbox: true, + nodeIntegration: false, preload: preloadMainScript, - nativeWindowOpen: true } }; diff --git a/package.json b/package.json index 13f005e8..cdd013ca 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "Symphony", "productName": "Symphony", - "version": "3.3.2", + "version": "3.4.0", "buildNumber": "0", "description": "Symphony desktop app (Foundation ODP)", "author": "Symphony", @@ -75,11 +75,17 @@ "url": "https://support.symphony.com" }, "devDependencies": { + "babel-cli": "^6.18.0", + "babel-eslint": "^7.1.1", + "babel-plugin-transform-async-to-generator": "^6.16.0", + "babel-plugin-transform-runtime": "^6.15.0", + "babel-preset-es2016-node5": "^1.1.2", + "babel-register": "^6.18.0", "bluebird": "3.5.2", "browserify": "16.2.3", "chromedriver": "2.42.0", "cross-env": "5.2.0", - "electron": "3.0.2", + "electron": "3.0.5", "electron-builder": "20.28.4", "electron-builder-squirrel-windows": "12.3.0", "electron-chromedriver": "3.0.0-beta.1", @@ -107,7 +113,7 @@ "auto-launch": "5.0.5", "electron-dl": "1.12.0", "electron-log": "2.2.17", - "electron-spellchecker": "1.1.2", + "electron-spellchecker": "git+https://github.com/KiranNiranjan/electron-spellchecker.git#v3.0.5", "ffi": "git+https://github.com/keerthi16/node-ffi.git#v1.2.8", "filesize": "3.6.1", "keymirror": "0.1.1",