Merge pull request #2372 from matrix-org/dbkr/electron_sandbox

React-sdk changes to support sandboxed electron
This commit is contained in:
David Baker 2018-12-19 09:48:05 +00:00 committed by GitHub
commit 1ca91370f3
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 25 additions and 61 deletions

View file

@ -3,6 +3,7 @@
/* /*
Copyright 2016 Aviral Dasgupta Copyright 2016 Aviral Dasgupta
Copyright 2016 OpenMarket Ltd Copyright 2016 OpenMarket Ltd
Copyright 2018 New Vector Ltd
Licensed under the Apache License, Version 2.0 (the "License"); Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License. you may not use this file except in compliance with the License.
@ -105,11 +106,6 @@ export default class BasePlatform {
return "Not implemented"; return "Not implemented";
} }
isElectron(): boolean { return false; }
setupScreenSharingForIframe() {
}
/** /**
* Restarts the application, without neccessarily reloading * Restarts the application, without neccessarily reloading
* any application code * any application code

View file

@ -188,9 +188,11 @@ module.exports = React.createClass({
phase: "UserSettings.LOADING", // LOADING, DISPLAY phase: "UserSettings.LOADING", // LOADING, DISPLAY
email_add_pending: false, email_add_pending: false,
vectorVersion: undefined, vectorVersion: undefined,
canSelfUpdate: null,
rejectingInvites: false, rejectingInvites: false,
mediaDevices: null, mediaDevices: null,
ignoredUsers: [], ignoredUsers: [],
autoLaunchEnabled: null,
}; };
}, },
@ -209,6 +211,13 @@ module.exports = React.createClass({
}, (e) => { }, (e) => {
console.log("Failed to fetch app version", e); console.log("Failed to fetch app version", e);
}); });
PlatformPeg.get().canSelfUpdate().then((canUpdate) => {
if (this._unmounted) return;
this.setState({
canSelfUpdate: canUpdate,
});
});
} }
this._refreshMediaDevices(); this._refreshMediaDevices();
@ -227,11 +236,12 @@ module.exports = React.createClass({
}); });
this._refreshFromServer(); this._refreshFromServer();
if (PlatformPeg.get().isElectron()) { if (PlatformPeg.get().supportsAutoLaunch()) {
const {ipcRenderer} = require('electron'); PlatformPeg.get().getAutoLaunchEnabled().then(enabled => {
this.setState({
ipcRenderer.on('settings', this._electronSettings); autoLaunchEnabled: enabled,
ipcRenderer.send('settings_get'); });
});
} }
this.setState({ this.setState({
@ -262,11 +272,6 @@ module.exports = React.createClass({
if (cli) { if (cli) {
cli.removeListener("RoomMember.membership", this._onInviteStateChange); cli.removeListener("RoomMember.membership", this._onInviteStateChange);
} }
if (PlatformPeg.get().isElectron()) {
const {ipcRenderer} = require('electron');
ipcRenderer.removeListener('settings', this._electronSettings);
}
}, },
// `UserSettings` assumes that the client peg will not be null, so give it some // `UserSettings` assumes that the client peg will not be null, so give it some
@ -285,10 +290,6 @@ module.exports = React.createClass({
}); });
}, },
_electronSettings: function(ev, settings) {
this.setState({ electron_settings: settings });
},
_refreshMediaDevices: function(stream) { _refreshMediaDevices: function(stream) {
if (stream) { if (stream) {
// kill stream so that we don't leave it lingering around with webcam enabled etc // kill stream so that we don't leave it lingering around with webcam enabled etc
@ -967,7 +968,7 @@ module.exports = React.createClass({
_renderCheckUpdate: function() { _renderCheckUpdate: function() {
const platform = PlatformPeg.get(); const platform = PlatformPeg.get();
if ('canSelfUpdate' in platform && platform.canSelfUpdate() && 'startUpdateCheck' in platform) { if (this.state.canSelfUpdate) {
return <div> return <div>
<h3>{ _t('Updates') }</h3> <h3>{ _t('Updates') }</h3>
<div className="mx_UserSettings_section"> <div className="mx_UserSettings_section">
@ -1012,8 +1013,7 @@ module.exports = React.createClass({
}, },
_renderElectronSettings: function() { _renderElectronSettings: function() {
const settings = this.state.electron_settings; if (!PlatformPeg.get().supportsAutoLaunch()) return;
if (!settings) return;
// TODO: This should probably be a granular setting, but it only applies to electron // TODO: This should probably be a granular setting, but it only applies to electron
// and ends up being get/set outside of matrix anyways (local system setting). // and ends up being get/set outside of matrix anyways (local system setting).
@ -1023,7 +1023,7 @@ module.exports = React.createClass({
<div className="mx_UserSettings_toggle"> <div className="mx_UserSettings_toggle">
<input type="checkbox" <input type="checkbox"
name="auto-launch" name="auto-launch"
defaultChecked={settings['auto-launch']} defaultChecked={this.state.autoLaunchEnabled}
onChange={this._onAutoLaunchChanged} onChange={this._onAutoLaunchChanged}
/> />
<label htmlFor="auto-launch">{ _t('Start automatically after system login') }</label> <label htmlFor="auto-launch">{ _t('Start automatically after system login') }</label>
@ -1033,8 +1033,11 @@ module.exports = React.createClass({
}, },
_onAutoLaunchChanged: function(e) { _onAutoLaunchChanged: function(e) {
const {ipcRenderer} = require('electron'); PlatformPeg.get().setAutoLaunchEnabled(e.target.checked).then(() => {
ipcRenderer.send('settings_set', 'auto-launch', e.target.checked); this.setState({
autoLaunchEnabled: e.target.checked,
});
});
}, },
_mapWebRtcDevicesToSpans: function(devices) { _mapWebRtcDevicesToSpans: function(devices) {
@ -1393,7 +1396,7 @@ module.exports = React.createClass({
{ this._renderBulkOptions() } { this._renderBulkOptions() }
{ this._renderBugReport() } { this._renderBugReport() }
{ PlatformPeg.get().isElectron() && this._renderElectronSettings() } { this._renderElectronSettings() }
{ this._renderAnalyticsControl() } { this._renderAnalyticsControl() }

View file

@ -22,7 +22,6 @@ import qs from 'querystring';
import React from 'react'; import React from 'react';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import MatrixClientPeg from '../../../MatrixClientPeg'; import MatrixClientPeg from '../../../MatrixClientPeg';
import PlatformPeg from '../../../PlatformPeg';
import ScalarAuthClient from '../../../ScalarAuthClient'; import ScalarAuthClient from '../../../ScalarAuthClient';
import WidgetMessaging from '../../../WidgetMessaging'; import WidgetMessaging from '../../../WidgetMessaging';
import TintableSvgButton from './TintableSvgButton'; import TintableSvgButton from './TintableSvgButton';
@ -49,7 +48,6 @@ export default class AppTile extends React.Component {
this.state = this._getNewState(props); this.state = this._getNewState(props);
this._onAction = this._onAction.bind(this); this._onAction = this._onAction.bind(this);
this._onMessage = this._onMessage.bind(this);
this._onLoaded = this._onLoaded.bind(this); this._onLoaded = this._onLoaded.bind(this);
this._onEditClick = this._onEditClick.bind(this); this._onEditClick = this._onEditClick.bind(this);
this._onDeleteClick = this._onDeleteClick.bind(this); this._onDeleteClick = this._onDeleteClick.bind(this);
@ -143,10 +141,6 @@ export default class AppTile extends React.Component {
} }
componentDidMount() { componentDidMount() {
// Legacy Jitsi widget messaging -- TODO replace this with standard widget
// postMessaging API
window.addEventListener('message', this._onMessage, false);
// Widget action listeners // Widget action listeners
this.dispatcherRef = dis.register(this._onAction); this.dispatcherRef = dis.register(this._onAction);
} }
@ -155,9 +149,6 @@ export default class AppTile extends React.Component {
// Widget action listeners // Widget action listeners
dis.unregister(this.dispatcherRef); dis.unregister(this.dispatcherRef);
// Jitsi listener
window.removeEventListener('message', this._onMessage);
// if it's not remaining on screen, get rid of the PersistedElement container // if it's not remaining on screen, get rid of the PersistedElement container
if (!ActiveWidgetStore.getWidgetPersistence(this.props.id)) { if (!ActiveWidgetStore.getWidgetPersistence(this.props.id)) {
ActiveWidgetStore.destroyPersistentWidget(); ActiveWidgetStore.destroyPersistentWidget();
@ -233,32 +224,6 @@ export default class AppTile extends React.Component {
} }
} }
// Legacy Jitsi widget messaging
// TODO -- This should be replaced with the new widget postMessaging API
_onMessage(event) {
if (this.props.type !== 'jitsi') {
return;
}
if (!event.origin) {
event.origin = event.originalEvent.origin;
}
const widgetUrlObj = url.parse(this.state.widgetUrl);
const eventOrigin = url.parse(event.origin);
if (
eventOrigin.protocol !== widgetUrlObj.protocol ||
eventOrigin.host !== widgetUrlObj.host
) {
return;
}
if (event.data.widgetAction === 'jitsi_iframe_loaded') {
const iframe = this.refs.appFrame.contentWindow
.document.querySelector('iframe[id^="jitsiConferenceFrame"]');
PlatformPeg.get().setupScreenSharingForIframe(iframe);
}
}
_canUserModify() { _canUserModify() {
// User widgets should always be modifiable by their creator // User widgets should always be modifiable by their creator
if (this.props.userWidget && MatrixClientPeg.get().credentials.userId === this.props.creatorUserId) { if (this.props.userWidget && MatrixClientPeg.get().credentials.userId === this.props.creatorUserId) {