[MM-33828] Define CSP for all BrowserWindows, enable contextIsolation for main/settings window, other fixes (#1517)

* [MM-33828] Added CSP to renderer process pages and turned off remote module when not needed

* Turn on contextIsolation and turn off nodeIntegration for main and settings windows

* Check for details.reason instead of object
This commit is contained in:
Devin Binnie
2021-03-23 06:26:48 -04:00
committed by GitHub
parent 5ed84270c8
commit b5c59fa8ce
13 changed files with 134 additions and 125 deletions

View File

@@ -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,
});

View File

@@ -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,

View File

@@ -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();
});

View File

@@ -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',
},

View File

@@ -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',
}});

View File

@@ -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 = (
<span className='overlay-gradient'/>
);
}
let titleBarButtons;
if (os.platform() === 'win32' && os.release().startsWith('10')) {
if (window.os.isWindows10) {
titleBarButtons = (
<span className='title-bar-btns'>
<div
@@ -421,7 +417,7 @@ export default class MainPage extends React.PureComponent {
darkMode={this.state.darkMode}
show={this.state.showExtraBar}
goBack={() => {
ipcRenderer.send(HISTORY, -1);
window.ipcRenderer.send(HISTORY, -1);
}}
/>
<Row>

View File

@@ -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(
<Checkbox
key='inputAutoStart'
@@ -462,8 +461,8 @@ export default class SettingsPage extends React.PureComponent {
</HelpBlock>
</Checkbox>);
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(
<Checkbox
key='inputShowUnreadBadge'
@@ -479,7 +478,7 @@ export default class SettingsPage extends React.PureComponent {
</Checkbox>);
}
if (process.platform === 'win32' || process.platform === 'linux') {
if (window.process.platform === 'win32' || window.process.platform === 'linux') {
options.push(
<Checkbox
key='flashWindow'
@@ -495,7 +494,7 @@ export default class SettingsPage extends React.PureComponent {
</Checkbox>);
}
if (process.platform === 'darwin') {
if (window.process.platform === 'darwin') {
options.push(
<FormGroup
key='OptionsForm'
@@ -545,7 +544,7 @@ export default class SettingsPage extends React.PureComponent {
);
}
if (process.platform === 'darwin' || process.platform === 'linux') {
if (window.process.platform === 'darwin' || window.process.platform === 'linux') {
options.push(
<Checkbox
key='inputShowTrayIcon'
@@ -554,14 +553,14 @@ export default class SettingsPage extends React.PureComponent {
checked={this.state.showTrayIcon}
onChange={this.handleChangeShowTrayIcon}
>
{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'}
<HelpBlock>
{'Setting takes effect after restarting the app.'}
</HelpBlock>
</Checkbox>);
}
if (process.platform === 'linux') {
if (window.process.platform === 'linux') {
options.push(
<FormGroup
key='trayIconTheme'
@@ -590,7 +589,7 @@ export default class SettingsPage extends React.PureComponent {
);
}
if (process.platform === 'linux') {
if (window.process.platform === 'linux') {
options.push(
<Checkbox
key='inputMinimizeToTray'

View File

@@ -3,7 +3,6 @@
// Copyright (c) 2015-2016 Yuya Ochiai
import React from 'react';
import {ipcRenderer} from 'electron';
import PropTypes from 'prop-types';
import {Nav, NavItem} from 'react-bootstrap';
import {Container, Draggable} from 'react-smooth-dnd';
@@ -20,7 +19,7 @@ export default class TabBar extends React.PureComponent { // need "this"
}
componentDidMount() {
ipcRenderer.invoke(GET_CONFIGURATION).then((config) => {
window.ipcRenderer.invoke(GET_CONFIGURATION).then((config) => {
this.setState({hasGPOTeams: config.registryTeams && config.registryTeams.length > 0});
});
}

View File

@@ -2,6 +2,7 @@
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="Content-Security-Policy" content="default-src 'self'; style-src 'self' 'unsafe-inline'">
<title><%= htmlWebpackPlugin.options.title %></title>
</head>
<body>

View File

@@ -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__}`);
});

View File

@@ -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');
}
}

View File

@@ -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');
}}
/>
);

View File

@@ -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',