diff --git a/src/main/preload/mainWindow.js b/src/main/preload/mainWindow.js new file mode 100644 index 00000000..e93e1140 --- /dev/null +++ b/src/main/preload/mainWindow.js @@ -0,0 +1,28 @@ +// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved. +// See LICENSE.txt for license information. +// Copyright (c) 2015-2016 Yuya Ochiai + +'use strict'; + +import os from 'os'; +import {ipcRenderer, contextBridge} from 'electron'; + +contextBridge.exposeInMainWorld('ipcRenderer', { + send: ipcRenderer.send, + on: (channel, listener) => ipcRenderer.on(channel, (_, ...args) => listener(null, ...args)), + invoke: ipcRenderer.invoke, +}); + +contextBridge.exposeInMainWorld('os', { + isWindows10: os.platform() === 'win32' && os.release().startsWith('10'), +}); + +contextBridge.exposeInMainWorld('process', { + platform: process.platform, + env: process.env, +}); + +contextBridge.exposeInMainWorld('timers', { + setImmediate, +}); + diff --git a/src/main/views/MattermostView.js b/src/main/views/MattermostView.js index cf0c2041..13042fd4 100644 --- a/src/main/views/MattermostView.js +++ b/src/main/views/MattermostView.js @@ -43,7 +43,7 @@ export class MattermostView extends EventEmitter { `version=${app.version}`, `appName=${app.name}`, ], - enableRemoteModule: true, + enableRemoteModule: process.env.NODE_ENV === 'test', nodeIntegration: process.env.NODE_ENV === 'test', }, ...options, diff --git a/src/main/views/webContentEvents.js b/src/main/views/webContentEvents.js index 0adf9ef6..6886b4c9 100644 --- a/src/main/views/webContentEvents.js +++ b/src/main/views/webContentEvents.js @@ -242,8 +242,8 @@ export const addWebContentsEventListeners = (mmview, getServersFunction) => { listeners[contents.id] = removeListeners; contents.once('render-process-gone', (event, details) => { - if (details !== 'clean-exit') { - log.error(`Renderer process for a webcontent is no longer available: ${details}`); + if (details.reason !== 'clean-exit') { + log.error('Renderer process for a webcontent is no longer available:', details.reason); } removeListeners(); }); diff --git a/src/main/windows/mainWindow.js b/src/main/windows/mainWindow.js index f17cb392..7619f828 100644 --- a/src/main/windows/mainWindow.js +++ b/src/main/windows/mainWindow.js @@ -13,7 +13,7 @@ import {SELECT_NEXT_TAB, SELECT_PREVIOUS_TAB} from 'common/communication'; import * as Validator from '../Validator'; import contextMenu from '../contextMenu'; -import {getLocalURLString} from '../utils'; +import {getLocalPreload, getLocalURLString} from '../utils'; function saveWindowState(file, window) { const windowState = window.getBounds(); @@ -37,6 +37,7 @@ function createMainWindow(config, options) { const minimumWindowHeight = 240; // Create the browser window. + const preload = getLocalPreload('mainWindow.js'); const boundsInfoPath = path.join(app.getPath('userData'), 'bounds-info.json'); let windowOptions; try { @@ -70,9 +71,10 @@ function createMainWindow(config, options) { trafficLightPosition: {x: 12, y: 24}, backgroundColor: '#fff', // prevents blurry text: https://electronjs.org/docs/faq#the-font-looks-blurry-what-is-this-and-what-can-i-do webPreferences: { - nodeIntegration: true, - contextIsolation: false, + nodeIntegration: process.env.NODE_ENV === 'test', + contextIsolation: process.env.NODE_ENV !== 'test', disableBlinkFeatures: 'Auxclick', + preload, spellcheck, enableRemoteModule: process.env.NODE_ENV === 'test', }, diff --git a/src/main/windows/settingsWindow.js b/src/main/windows/settingsWindow.js index 7c384613..30181082 100644 --- a/src/main/windows/settingsWindow.js +++ b/src/main/windows/settingsWindow.js @@ -4,17 +4,19 @@ import {BrowserWindow} from 'electron'; import log from 'electron-log'; -import {getLocalURLString} from '../utils'; +import {getLocalPreload, getLocalURLString} from '../utils'; export function createSettingsWindow(mainWindow, config, withDevTools) { + const preload = getLocalPreload('mainWindow.js'); const spellcheck = (typeof config.useSpellChecker === 'undefined' ? true : config.useSpellChecker); const settingsWindow = new BrowserWindow({ ...config.data, parent: mainWindow, title: 'Desktop App Settings', webPreferences: { - nodeIntegration: true, - contextIsolation: false, + nodeIntegration: false, + contextIsolation: true, + preload, spellcheck, enableRemoteModule: process.env.NODE_ENV === 'test', }}); diff --git a/src/renderer/components/MainPage.jsx b/src/renderer/components/MainPage.jsx index 320cdce7..1731b792 100644 --- a/src/renderer/components/MainPage.jsx +++ b/src/renderer/components/MainPage.jsx @@ -2,15 +2,11 @@ // See LICENSE.txt for license information. // Copyright (c) 2015-2016 Yuya Ochiai -import os from 'os'; - import React, {Fragment} from 'react'; import PropTypes from 'prop-types'; import {Grid, Row} from 'react-bootstrap'; import DotsVerticalIcon from 'mdi-react/DotsVerticalIcon'; -import {ipcRenderer} from 'electron'; - import { FOCUS_BROWSERVIEW, MAXIMIZE_CHANGE, @@ -87,7 +83,7 @@ export default class MainPage extends React.PureComponent { componentDidMount() { // set page on retry - ipcRenderer.on(LOAD_RETRY, (_, server, retry, err, loadUrl) => { + window.ipcRenderer.on(LOAD_RETRY, (_, server, retry, err, loadUrl) => { console.log(`${server}: failed to load ${err}, but retrying`); const status = this.state.tabStatus; const statusValue = { @@ -102,13 +98,13 @@ export default class MainPage extends React.PureComponent { this.setState({tabStatus: status}); }); - ipcRenderer.on(LOAD_SUCCESS, (_, server) => { + window.ipcRenderer.on(LOAD_SUCCESS, (_, server) => { const status = this.state.tabStatus; status.set(server, {status: DONE}); this.setState({tabStatus: status}); }); - ipcRenderer.on(LOAD_FAILED, (_, server, err, loadUrl) => { + window.ipcRenderer.on(LOAD_FAILED, (_, server, err, loadUrl) => { console.log(`${server}: failed to load ${err}`); const status = this.state.tabStatus; const statusValue = { @@ -122,16 +118,16 @@ export default class MainPage extends React.PureComponent { this.setState({tabStatus: status}); }); - ipcRenderer.on(DARK_MODE_CHANGE, (_, darkMode) => { + window.ipcRenderer.on(DARK_MODE_CHANGE, (_, darkMode) => { this.setState({darkMode}); }); // can't switch tabs sequentially for some reason... - ipcRenderer.on(SET_SERVER_KEY, (event, key) => { + window.ipcRenderer.on(SET_SERVER_KEY, (event, key) => { const nextIndex = this.props.teams.findIndex((team) => team.order === key); this.handleSetServerKey(nextIndex); }); - ipcRenderer.on(SELECT_NEXT_TAB, () => { + window.ipcRenderer.on(SELECT_NEXT_TAB, () => { const currentOrder = this.props.teams[this.state.key].order; const nextOrder = ((currentOrder + 1) % this.props.teams.length); const nextIndex = this.props.teams.findIndex((team) => team.order === nextOrder); @@ -139,7 +135,7 @@ export default class MainPage extends React.PureComponent { this.handleSelect(team.name, nextIndex); }); - ipcRenderer.on(SELECT_PREVIOUS_TAB, () => { + window.ipcRenderer.on(SELECT_PREVIOUS_TAB, () => { const currentOrder = this.props.teams[this.state.key].order; // js modulo operator returns a negative number if result is negative, so we have to ensure it's positive @@ -149,32 +145,32 @@ export default class MainPage extends React.PureComponent { this.handleSelect(team.name, nextIndex); }); - ipcRenderer.on(MAXIMIZE_CHANGE, this.handleMaximizeState); + window.ipcRenderer.on(MAXIMIZE_CHANGE, this.handleMaximizeState); - ipcRenderer.on('enter-full-screen', () => this.handleFullScreenState(true)); - ipcRenderer.on('leave-full-screen', () => this.handleFullScreenState(false)); + window.ipcRenderer.on('enter-full-screen', () => this.handleFullScreenState(true)); + window.ipcRenderer.on('leave-full-screen', () => this.handleFullScreenState(false)); - ipcRenderer.on(ADD_SERVER, () => { + window.ipcRenderer.on(ADD_SERVER, () => { this.addServer(); }); - ipcRenderer.on(PLAY_SOUND, (_event, soundName) => { + window.ipcRenderer.on(PLAY_SOUND, (_event, soundName) => { playSound(soundName); }); - ipcRenderer.on(MODAL_OPEN, () => { + window.ipcRenderer.on(MODAL_OPEN, () => { this.setState({modalOpen: true}); }); - ipcRenderer.on(MODAL_CLOSE, () => { + window.ipcRenderer.on(MODAL_CLOSE, () => { this.setState({modalOpen: false}); }); - ipcRenderer.on(TOGGLE_BACK_BUTTON, (event, showExtraBar) => { + window.ipcRenderer.on(TOGGLE_BACK_BUTTON, (event, showExtraBar) => { this.setState({showExtraBar}); }); - ipcRenderer.on(UPDATE_MENTIONS, (_event, team, mentions, unreads, isExpired) => { + window.ipcRenderer.on(UPDATE_MENTIONS, (_event, team, mentions, unreads, isExpired) => { const key = this.props.teams.findIndex((server) => server.name === team); const {unreadCounts, mentionCounts, sessionsExpired} = this.state; @@ -190,8 +186,8 @@ export default class MainPage extends React.PureComponent { this.setState({unreadCounts: newUnreads, mentionCounts: newMentionCounts, sessionsExpired: expired}); }); - if (process.platform !== 'darwin') { - ipcRenderer.on(FOCUS_THREE_DOT_MENU, () => { + if (window.process.platform !== 'darwin') { + window.ipcRenderer.on(FOCUS_THREE_DOT_MENU, () => { if (this.threeDotMenu.current) { this.threeDotMenu.current.focus(); } @@ -213,7 +209,7 @@ export default class MainPage extends React.PureComponent { } handleSelect = (name, key) => { - ipcRenderer.send(SWITCH_SERVER, name); + window.ipcRenderer.send(SWITCH_SERVER, name); this.handleSetServerKey(key); } @@ -228,40 +224,40 @@ export default class MainPage extends React.PureComponent { handleClose = (e) => { e.stopPropagation(); // since it is our button, the event goes into MainPage's onclick event, getting focus back. - ipcRenderer.send(WINDOW_CLOSE); + window.ipcRenderer.send(WINDOW_CLOSE); } handleMinimize = (e) => { e.stopPropagation(); - ipcRenderer.send(WINDOW_MINIMIZE); + window.ipcRenderer.send(WINDOW_MINIMIZE); } handleMaximize = (e) => { e.stopPropagation(); - ipcRenderer.send(WINDOW_MAXIMIZE); + window.ipcRenderer.send(WINDOW_MAXIMIZE); } handleRestore = () => { - ipcRenderer.send(WINDOW_RESTORE); + window.ipcRenderer.send(WINDOW_RESTORE); } openMenu = () => { - if (process.platform !== 'darwin') { + if (window.process.platform !== 'darwin') { this.threeDotMenu.current.blur(); } this.props.openMenu(); } handleDoubleClick = () => { - ipcRenderer.send(DOUBLE_CLICK_ON_WINDOW); + window.ipcRenderer.send(DOUBLE_CLICK_ON_WINDOW); } addServer = () => { - ipcRenderer.send(SHOW_NEW_SERVER_MODAL); + window.ipcRenderer.send(SHOW_NEW_SERVER_MODAL); } focusOnWebView = () => { - ipcRenderer.send(FOCUS_BROWSERVIEW); + window.ipcRenderer.send(FOCUS_BROWSERVIEW); } setInputRef = (ref) => { @@ -287,7 +283,7 @@ export default class MainPage extends React.PureComponent { ); let topBarClassName = 'topBar'; - if (process.platform === 'darwin') { + if (window.process.platform === 'darwin') { topBarClassName += ' macOS'; } if (this.state.darkMode) { @@ -319,14 +315,14 @@ export default class MainPage extends React.PureComponent { } let overlayGradient; - if (process.platform !== 'darwin') { + if (window.process.platform !== 'darwin') { overlayGradient = ( ); } let titleBarButtons; - if (os.platform() === 'win32' && os.release().startsWith('10')) { + if (window.os.isWindows10) { titleBarButtons = (
{ - ipcRenderer.send(HISTORY, -1); + window.ipcRenderer.send(HISTORY, -1); }} /> diff --git a/src/renderer/components/SettingsPage.jsx b/src/renderer/components/SettingsPage.jsx index 48507cc6..906b027b 100644 --- a/src/renderer/components/SettingsPage.jsx +++ b/src/renderer/components/SettingsPage.jsx @@ -8,7 +8,6 @@ import React from 'react'; import PropTypes from 'prop-types'; import {Checkbox, Col, FormGroup, Grid, HelpBlock, Navbar, Radio, Row, Button} from 'react-bootstrap'; -import {ipcRenderer} from 'electron'; import {debounce} from 'underscore'; import {GET_LOCAL_CONFIGURATION, UPDATE_CONFIGURATION, DOUBLE_CLICK_ON_WINDOW, GET_DOWNLOAD_LOCATION, SWITCH_SERVER, ADD_SERVER, RELOAD_CONFIGURATION} from 'common/communication'; @@ -20,7 +19,7 @@ const CONFIG_TYPE_SERVERS = 'servers'; const CONFIG_TYPE_APP_OPTIONS = 'appOptions'; function backToIndex(serverName) { - ipcRenderer.send(SWITCH_SERVER, serverName); + window.ipcRenderer.send(SWITCH_SERVER, serverName); window.close(); } @@ -54,20 +53,20 @@ export default class SettingsPage extends React.PureComponent { } componentDidMount() { - ipcRenderer.on(ADD_SERVER, () => { + window.ipcRenderer.on(ADD_SERVER, () => { this.setState({ showAddTeamForm: true, }); }); - ipcRenderer.on(RELOAD_CONFIGURATION, () => { + window.ipcRenderer.on(RELOAD_CONFIGURATION, () => { this.updateSaveState(); this.getConfig(); }); } getConfig = () => { - ipcRenderer.invoke(GET_LOCAL_CONFIGURATION).then((config) => { + window.ipcRenderer.invoke(GET_LOCAL_CONFIGURATION).then((config) => { this.setState({ready: true, maximized: false, ...this.convertConfigDataToState(config)}); }); } @@ -98,7 +97,7 @@ export default class SettingsPage extends React.PureComponent { } processSaveQueue = debounce(() => { - ipcRenderer.send(UPDATE_CONFIGURATION, this.saveQueue.splice(0, this.saveQueue.length)); + window.ipcRenderer.send(UPDATE_CONFIGURATION, this.saveQueue.splice(0, this.saveQueue.length)); }, 500); updateSaveState = () => { @@ -135,7 +134,7 @@ export default class SettingsPage extends React.PureComponent { }, 2000); handleTeamsChange = (teams) => { - setImmediate(this.saveSetting, CONFIG_TYPE_SERVERS, {key: 'teams', data: teams}); + window.timers.setImmediate(this.saveSetting, CONFIG_TYPE_SERVERS, {key: 'teams', data: teams}); this.setState({ showAddTeamForm: false, teams, @@ -147,12 +146,12 @@ export default class SettingsPage extends React.PureComponent { handleChangeShowTrayIcon = () => { const shouldShowTrayIcon = !this.showTrayIconRef.current.props.checked; - setImmediate(this.saveSetting, CONFIG_TYPE_APP_OPTIONS, {key: 'showTrayIcon', data: shouldShowTrayIcon}); + window.timers.setImmediate(this.saveSetting, CONFIG_TYPE_APP_OPTIONS, {key: 'showTrayIcon', data: shouldShowTrayIcon}); this.setState({ showTrayIcon: shouldShowTrayIcon, }); - if (process.platform === 'darwin' && !shouldShowTrayIcon) { + if (window.process.platform === 'darwin' && !shouldShowTrayIcon) { this.setState({ minimizeToTray: false, }); @@ -160,14 +159,14 @@ export default class SettingsPage extends React.PureComponent { } handleChangeTrayIconTheme = (theme) => { - setImmediate(this.saveSetting, CONFIG_TYPE_APP_OPTIONS, {key: 'trayIconTheme', data: theme}); + window.timers.setImmediate(this.saveSetting, CONFIG_TYPE_APP_OPTIONS, {key: 'trayIconTheme', data: theme}); this.setState({ trayIconTheme: theme, }); } handleChangeAutoStart = () => { - setImmediate(this.saveSetting, CONFIG_TYPE_APP_OPTIONS, {key: 'autostart', data: !this.autostartRef.current.props.checked}); + window.timers.setImmediate(this.saveSetting, CONFIG_TYPE_APP_OPTIONS, {key: 'autostart', data: !this.autostartRef.current.props.checked}); this.setState({ autostart: !this.autostartRef.current.props.checked, }); @@ -176,7 +175,7 @@ export default class SettingsPage extends React.PureComponent { handleChangeMinimizeToTray = () => { const shouldMinimizeToTray = this.state.showTrayIcon && !this.minimizeToTrayRef.current.props.checked; - setImmediate(this.saveSetting, CONFIG_TYPE_APP_OPTIONS, {key: 'minimizeToTray', data: shouldMinimizeToTray}); + window.timers.setImmediate(this.saveSetting, CONFIG_TYPE_APP_OPTIONS, {key: 'minimizeToTray', data: shouldMinimizeToTray}); this.setState({ minimizeToTray: shouldMinimizeToTray, }); @@ -196,7 +195,7 @@ export default class SettingsPage extends React.PureComponent { } handleFlashWindow = () => { - setImmediate(this.saveSetting, CONFIG_TYPE_APP_OPTIONS, { + window.timers.setImmediate(this.saveSetting, CONFIG_TYPE_APP_OPTIONS, { key: 'notifications', data: { ...this.state.notifications, @@ -212,7 +211,7 @@ export default class SettingsPage extends React.PureComponent { } handleBounceIcon = () => { - setImmediate(this.saveSetting, CONFIG_TYPE_APP_OPTIONS, { + window.timers.setImmediate(this.saveSetting, CONFIG_TYPE_APP_OPTIONS, { key: 'notifications', data: { ...this.state.notifications, @@ -228,7 +227,7 @@ export default class SettingsPage extends React.PureComponent { } handleBounceIconType = (event) => { - setImmediate(this.saveSetting, CONFIG_TYPE_APP_OPTIONS, { + window.timers.setImmediate(this.saveSetting, CONFIG_TYPE_APP_OPTIONS, { key: 'notifications', data: { ...this.state.notifications, @@ -244,21 +243,21 @@ export default class SettingsPage extends React.PureComponent { } handleShowUnreadBadge = () => { - setImmediate(this.saveSetting, CONFIG_TYPE_APP_OPTIONS, {key: 'showUnreadBadge', data: !this.showUnreadBadgeRef.current.props.checked}); + window.timers.setImmediate(this.saveSetting, CONFIG_TYPE_APP_OPTIONS, {key: 'showUnreadBadge', data: !this.showUnreadBadgeRef.current.props.checked}); this.setState({ showUnreadBadge: !this.showUnreadBadgeRef.current.props.checked, }); } handleChangeUseSpellChecker = () => { - setImmediate(this.saveSetting, CONFIG_TYPE_APP_OPTIONS, {key: 'useSpellChecker', data: !this.useSpellCheckerRef.current.props.checked}); + window.timers.setImmediate(this.saveSetting, CONFIG_TYPE_APP_OPTIONS, {key: 'useSpellChecker', data: !this.useSpellCheckerRef.current.props.checked}); this.setState({ useSpellChecker: !this.useSpellCheckerRef.current.props.checked, }); } handleChangeEnableHardwareAcceleration = () => { - setImmediate(this.saveSetting, CONFIG_TYPE_APP_OPTIONS, {key: 'enableHardwareAcceleration', data: !this.enableHardwareAccelerationRef.current.props.checked}); + window.timers.setImmediate(this.saveSetting, CONFIG_TYPE_APP_OPTIONS, {key: 'enableHardwareAcceleration', data: !this.enableHardwareAccelerationRef.current.props.checked}); this.setState({ enableHardwareAcceleration: !this.enableHardwareAccelerationRef.current.props.checked, }); @@ -268,7 +267,7 @@ export default class SettingsPage extends React.PureComponent { this.setState({ downloadLocation: location, }); - setImmediate(this.saveSetting, CONFIG_TYPE_APP_OPTIONS, {key: 'downloadLocation', data: location}); + window.timers.setImmediate(this.saveSetting, CONFIG_TYPE_APP_OPTIONS, {key: 'downloadLocation', data: location}); } handleChangeDownloadLocation = (e) => { @@ -277,7 +276,7 @@ export default class SettingsPage extends React.PureComponent { selectDownloadLocation = () => { if (!this.state.userOpenedDownloadDialog) { - ipcRenderer.invoke(GET_DOWNLOAD_LOCATION, `/Users/${process.env.USER || process.env.USERNAME}/Downloads`).then((result) => this.saveDownloadLocation(result)); + window.ipcRenderer.invoke(GET_DOWNLOAD_LOCATION, `/Users/${window.process.env.USER || window.process.env.USERNAME}/Downloads`).then((result) => this.saveDownloadLocation(result)); this.setState({userOpenedDownloadDialog: true}); } this.setState({userOpenedDownloadDialog: false}); @@ -286,7 +285,7 @@ export default class SettingsPage extends React.PureComponent { updateTeam = (index, newData) => { const teams = this.state.teams; teams[index] = newData; - setImmediate(this.saveSetting, CONFIG_TYPE_SERVERS, {key: 'teams', data: teams}); + window.timers.setImmediate(this.saveSetting, CONFIG_TYPE_SERVERS, {key: 'teams', data: teams}); this.setState({ teams, }); @@ -295,7 +294,7 @@ export default class SettingsPage extends React.PureComponent { addServer = (team) => { const teams = this.state.teams; teams.push(team); - setImmediate(this.saveSetting, CONFIG_TYPE_SERVERS, {key: 'teams', data: teams}); + window.timers.setImmediate(this.saveSetting, CONFIG_TYPE_SERVERS, {key: 'teams', data: teams}); this.setState({ teams, }); @@ -308,7 +307,7 @@ export default class SettingsPage extends React.PureComponent { } handleDoubleClick = () => { - ipcRenderer.send(DOUBLE_CLICK_ON_WINDOW, 'settings'); + window.ipcRenderer.send(DOUBLE_CLICK_ON_WINDOW, 'settings'); } render() { @@ -431,7 +430,7 @@ export default class SettingsPage extends React.PureComponent { const options = []; // MacOS has an option in the Dock, to set the app to autostart, so we choose to not support this option for OSX - if (process.platform === 'win32' || process.platform === 'linux') { + if (window.process.platform === 'win32' || window.process.platform === 'linux') { options.push( ); - if (process.platform === 'darwin' || process.platform === 'win32') { - const TASKBAR = process.platform === 'win32' ? 'taskbar' : 'Dock'; + if (window.process.platform === 'darwin' || window.process.platform === 'win32') { + const TASKBAR = window.process.platform === 'win32' ? 'taskbar' : 'Dock'; options.push( ); } - if (process.platform === 'win32' || process.platform === 'linux') { + if (window.process.platform === 'win32' || window.process.platform === 'linux') { options.push( ); } - if (process.platform === 'darwin') { + if (window.process.platform === 'darwin') { options.push( - {process.platform === 'darwin' ? `Show ${this.state.appName} icon in the menu bar` : 'Show icon in the notification area'} + {window.process.platform === 'darwin' ? `Show ${this.state.appName} icon in the menu bar` : 'Show icon in the notification area'} {'Setting takes effect after restarting the app.'} ); } - if (process.platform === 'linux') { + if (window.process.platform === 'linux') { options.push( { + window.ipcRenderer.invoke(GET_CONFIGURATION).then((config) => { this.setState({hasGPOTeams: config.registryTeams && config.registryTeams.length > 0}); }); } diff --git a/src/renderer/index.html b/src/renderer/index.html index 0c400db8..4f71f109 100644 --- a/src/renderer/index.html +++ b/src/renderer/index.html @@ -2,9 +2,10 @@ + <%= htmlWebpackPlugin.options.title %>
- \ No newline at end of file + diff --git a/src/renderer/index.jsx b/src/renderer/index.jsx index 4e17551b..ff85511a 100644 --- a/src/renderer/index.jsx +++ b/src/renderer/index.jsx @@ -5,17 +5,8 @@ import 'bootstrap/dist/css/bootstrap.min.css'; import 'renderer/css/index.css'; -if (process.env.NODE_ENV === 'production') { - window.eval = global.eval = () => { // eslint-disable-line no-multi-assign, no-eval - throw new Error('Sorry, Mattermost does not support window.eval() for security reasons.'); - }; -} else if (module.hot) { - module.hot.accept(); -} - import React from 'react'; import ReactDOM from 'react-dom'; -import {ipcRenderer} from 'electron'; import {GET_CONFIGURATION, UPDATE_TEAMS, QUIT, RELOAD_CONFIGURATION} from 'common/communication'; @@ -29,11 +20,11 @@ class Root extends React.PureComponent { async componentDidMount() { await this.setInitialConfig(); - ipcRenderer.on('synchronize-config', () => { + window.ipcRenderer.on('synchronize-config', () => { this.reloadConfig(); }); - ipcRenderer.on(RELOAD_CONFIGURATION, () => { + window.ipcRenderer.on(RELOAD_CONFIGURATION, () => { this.reloadConfig(); }); @@ -72,7 +63,7 @@ class Root extends React.PureComponent { }; teamConfigChange = async (updatedTeams, callback) => { - const updatedConfig = await ipcRenderer.invoke(UPDATE_TEAMS, updatedTeams); + const updatedConfig = await window.ipcRenderer.invoke(UPDATE_TEAMS, updatedTeams); await this.reloadConfig(); if (callback) { callback(updatedConfig); @@ -87,20 +78,20 @@ class Root extends React.PureComponent { requestConfig = async (exitOnError) => { // todo: should we block? try { - const configRequest = await ipcRenderer.invoke(GET_CONFIGURATION); + const configRequest = await window.ipcRenderer.invoke(GET_CONFIGURATION); return configRequest; } catch (err) { console.log(`there was an error with the config: ${err}`); if (exitOnError) { - ipcRenderer.send(QUIT, `unable to load configuration: ${err}`, err.stack); + window.ipcRenderer.send(QUIT, `unable to load configuration: ${err}`, err.stack); } } return null; }; openMenu = () => { - if (process.platform !== 'darwin') { - ipcRenderer.send('open-app-menu'); + if (window.process.platform !== 'darwin') { + window.ipcRenderer.send('open-app-menu'); } } @@ -122,7 +113,7 @@ class Root extends React.PureComponent { ); } } -ipcRenderer.invoke('get-app-version').then(({name, version}) => { +window.ipcRenderer.invoke('get-app-version').then(({name, version}) => { // eslint-disable-next-line no-undef console.log(`Starting ${name} v${version} commit: ${__HASH_VERSION__}`); }); diff --git a/src/renderer/settings.jsx b/src/renderer/settings.jsx index deea2a97..d579a400 100644 --- a/src/renderer/settings.jsx +++ b/src/renderer/settings.jsx @@ -2,28 +2,18 @@ // See LICENSE.txt for license information. // Copyright (c) 2015-2016 Yuya Ochiai -import {ipcRenderer} from 'electron'; - import 'bootstrap/dist/css/bootstrap.min.css'; import 'renderer/css/index.css'; import 'renderer/css/settings.css'; -if (process.env.NODE_ENV === 'production') { - window.eval = global.eval = () => { // eslint-disable-line no-multi-assign, no-eval - throw new Error('Sorry, Mattermost does not support window.eval() for security reasons.'); - }; -} else if (module.hot) { - module.hot.accept(); -} - import React from 'react'; import ReactDOM from 'react-dom'; import SettingsPage from './components/SettingsPage.jsx'; function openMenu() { - if (process.platform !== 'darwin') { - ipcRenderer.send('open-app-menu'); + if (window.process.platform !== 'darwin') { + window.ipcRenderer.send('open-app-menu'); } } diff --git a/src/renderer/updater.jsx b/src/renderer/updater.jsx index 7d2456db..70d9d078 100644 --- a/src/renderer/updater.jsx +++ b/src/renderer/updater.jsx @@ -25,17 +25,17 @@ class UpdaterPageContainer extends React.PureComponent { } componentDidMount() { - ipcRenderer.on('start-download', () => { + window.ipcRenderer.on('start-download', () => { this.setState({ isDownloading: true, }); }); - ipcRenderer.on('progress', (event, progress) => { + window.ipcRenderer.on('progress', (event, progress) => { this.setState({ progress, }); }); - ipcRenderer.on('zoom-in', () => { + window.ipcRenderer.on('zoom-in', () => { const activeTabWebContents = this.getTabWebContents(); if (!activeTabWebContents) { return; @@ -46,7 +46,7 @@ class UpdaterPageContainer extends React.PureComponent { activeTabWebContents.zoomLevel += 1; }); - ipcRenderer.on('zoom-out', () => { + window.ipcRenderer.on('zoom-out', () => { const activeTabWebContents = this.getTabWebContents(); if (!activeTabWebContents) { return; @@ -57,7 +57,7 @@ class UpdaterPageContainer extends React.PureComponent { activeTabWebContents.zoomLevel -= 1; }); - ipcRenderer.on('zoom-reset', () => { + window.ipcRenderer.on('zoom-reset', () => { const activeTabWebContents = this.getTabWebContents(); if (!activeTabWebContents) { return; @@ -65,7 +65,7 @@ class UpdaterPageContainer extends React.PureComponent { activeTabWebContents.zoomLevel = 0; }); - ipcRenderer.on('undo', () => { + window.ipcRenderer.on('undo', () => { const activeTabWebContents = this.getTabWebContents(); if (!activeTabWebContents) { return; @@ -73,7 +73,7 @@ class UpdaterPageContainer extends React.PureComponent { activeTabWebContents.undo(); }); - ipcRenderer.on('redo', () => { + window.ipcRenderer.on('redo', () => { const activeTabWebContents = this.getTabWebContents(); if (!activeTabWebContents) { return; @@ -81,7 +81,7 @@ class UpdaterPageContainer extends React.PureComponent { activeTabWebContents.redo(); }); - ipcRenderer.on('cut', () => { + window.ipcRenderer.on('cut', () => { const activeTabWebContents = this.getTabWebContents(); if (!activeTabWebContents) { return; @@ -89,7 +89,7 @@ class UpdaterPageContainer extends React.PureComponent { activeTabWebContents.cut(); }); - ipcRenderer.on('copy', () => { + window.ipcRenderer.on('copy', () => { const activeTabWebContents = this.getTabWebContents(); if (!activeTabWebContents) { return; @@ -97,7 +97,7 @@ class UpdaterPageContainer extends React.PureComponent { activeTabWebContents.copy(); }); - ipcRenderer.on('paste', () => { + window.ipcRenderer.on('paste', () => { const activeTabWebContents = this.getTabWebContents(); if (!activeTabWebContents) { return; @@ -105,7 +105,7 @@ class UpdaterPageContainer extends React.PureComponent { activeTabWebContents.paste(); }); - ipcRenderer.on('paste-and-match', () => { + window.ipcRenderer.on('paste-and-match', () => { const activeTabWebContents = this.getTabWebContents(); if (!activeTabWebContents) { return; @@ -121,22 +121,22 @@ class UpdaterPageContainer extends React.PureComponent { notifyOnly={this.props.notifyOnly} {...this.state} onClickReleaseNotes={() => { - ipcRenderer.send('click-release-notes'); + window.ipcRenderer.send('click-release-notes'); }} onClickSkip={() => { - ipcRenderer.send('click-skip'); + window.ipcRenderer.send('click-skip'); }} onClickRemind={() => { - ipcRenderer.send('click-remind'); + window.ipcRenderer.send('click-remind'); }} onClickInstall={() => { - ipcRenderer.send('click-install'); + window.ipcRenderer.send('click-install'); }} onClickDownload={() => { - ipcRenderer.send('click-download'); + window.ipcRenderer.send('click-download'); }} onClickCancel={() => { - ipcRenderer.send('click-cancel'); + window.ipcRenderer.send('click-cancel'); }} /> ); diff --git a/webpack.config.main.js b/webpack.config.main.js index 652007b4..0650f0c0 100644 --- a/webpack.config.main.js +++ b/webpack.config.main.js @@ -17,6 +17,7 @@ const base = require('./webpack.config.base'); module.exports = merge(base, { entry: { index: './src/main/main.js', + mainWindow: './src/main/preload/mainWindow.js', preload: './src/main/preload/mattermost.js', modalPreload: './src/main/preload/modalPreload.js', finderPreload: './src/main/preload/finderPreload.js',