mirror of
https://github.com/tiddly-gittly/TidGi-Desktop.git
synced 2025-12-30 22:02:53 -08:00
Allow access to Node.js & Electron APIs in JS code injection (#245)
Co-authored-by: linonetwo <linonetwo012@gmail.com>
This commit is contained in:
parent
0de23b6c25
commit
fbd50b3f3f
6 changed files with 89 additions and 31 deletions
|
|
@ -25,6 +25,7 @@ const getDefaultPauseNotificationsByScheduleTo = () => {
|
|||
};
|
||||
|
||||
const defaultPreferences = {
|
||||
allowNodeInJsCodeInjection: false,
|
||||
allowPrerelease: Boolean(semver.prerelease(app.getVersion())),
|
||||
askForDownloadPath: true,
|
||||
attachToMenubar: false,
|
||||
|
|
|
|||
|
|
@ -48,15 +48,32 @@ const handleLoaded = (event) => {
|
|||
});
|
||||
|
||||
const jsCodeInjection = ipcRenderer.sendSync('get-preference', 'jsCodeInjection');
|
||||
const allowNodeInJsCodeInjection = ipcRenderer.sendSync('get-preference', 'allowNodeInJsCodeInjection');
|
||||
const cssCodeInjection = ipcRenderer.sendSync('get-preference', 'cssCodeInjection');
|
||||
|
||||
if (jsCodeInjection && jsCodeInjection.trim().length > 0) {
|
||||
try {
|
||||
const node = document.createElement('script');
|
||||
node.innerHTML = jsCodeInjection;
|
||||
document.body.appendChild(node);
|
||||
} catch (err) {
|
||||
console.log(err); // eslint-disable-line no-console
|
||||
if (allowNodeInJsCodeInjection) {
|
||||
try {
|
||||
// eslint-disable-next-line no-new-func
|
||||
Function(
|
||||
'require',
|
||||
`"use strict";${jsCodeInjection}`,
|
||||
)(require);
|
||||
} catch (err) {
|
||||
/* eslint-disable no-console */
|
||||
console.log(err);
|
||||
/* eslint-enable no-console */
|
||||
}
|
||||
} else {
|
||||
try {
|
||||
const node = document.createElement('script');
|
||||
node.innerHTML = jsCodeInjection;
|
||||
document.body.appendChild(node);
|
||||
} catch (err) {
|
||||
/* eslint-disable no-console */
|
||||
console.log(err);
|
||||
/* eslint-enable no-console */
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -2,6 +2,8 @@ import React from 'react';
|
|||
import PropTypes from 'prop-types';
|
||||
|
||||
import Button from '@material-ui/core/Button';
|
||||
import FormControlLabel from '@material-ui/core/FormControlLabel';
|
||||
import Switch from '@material-ui/core/Switch';
|
||||
|
||||
import AceEditor from 'react-ace';
|
||||
|
||||
|
|
@ -29,6 +31,10 @@ const styles = (theme) => ({
|
|||
actions: {
|
||||
borderTop: `1px solid ${theme.palette.divider}`,
|
||||
padding: theme.spacing(2),
|
||||
display: 'flex',
|
||||
},
|
||||
actionsLeft: {
|
||||
flex: 1,
|
||||
},
|
||||
button: {
|
||||
float: 'right',
|
||||
|
|
@ -36,44 +42,68 @@ const styles = (theme) => ({
|
|||
},
|
||||
});
|
||||
|
||||
const getMode = () => {
|
||||
const codeInjectionType = window.require('electron').remote.getGlobal('codeInjectionType');
|
||||
const getMode = (codeInjectionType) => {
|
||||
if (codeInjectionType === 'css') return 'css';
|
||||
if (codeInjectionType === 'js') return 'javascript';
|
||||
return '';
|
||||
};
|
||||
|
||||
const CodeInjection = ({
|
||||
allowNodeInJsCodeInjection,
|
||||
classes,
|
||||
code,
|
||||
onSave,
|
||||
onUpdateForm,
|
||||
shouldUseDarkColors,
|
||||
}) => (
|
||||
<div className={classes.root}>
|
||||
<div className={classes.flexGrow}>
|
||||
<AceEditor
|
||||
mode={getMode()}
|
||||
theme={shouldUseDarkColors ? 'monokai' : 'github'}
|
||||
height="100%"
|
||||
width="100%"
|
||||
name="codeEditor"
|
||||
value={code}
|
||||
onChange={(value) => onUpdateForm({ code: value })}
|
||||
/>
|
||||
}) => {
|
||||
const codeInjectionType = window.require('electron').remote.getGlobal('codeInjectionType');
|
||||
return (
|
||||
<div className={classes.root}>
|
||||
<div className={classes.flexGrow}>
|
||||
<AceEditor
|
||||
mode={getMode(codeInjectionType)}
|
||||
theme={shouldUseDarkColors ? 'monokai' : 'github'}
|
||||
height="100%"
|
||||
width="100%"
|
||||
name="codeEditor"
|
||||
value={code}
|
||||
onChange={(value) => onUpdateForm({ code: value })}
|
||||
/>
|
||||
</div>
|
||||
<div className={classes.actions}>
|
||||
<div className={classes.actionsLeft}>
|
||||
{codeInjectionType === 'js' && (
|
||||
<FormControlLabel
|
||||
control={(
|
||||
<Switch
|
||||
checked={allowNodeInJsCodeInjection}
|
||||
onChange={(e) => onUpdateForm({ allowNodeInJsCodeInjection: e.target.checked })}
|
||||
color="primary"
|
||||
/>
|
||||
)}
|
||||
label="Allow access to Node.JS & Electron APIs"
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
<div className={classes.actionsRight}>
|
||||
<Button color="primary" variant="contained" disableElevation className={classes.button} onClick={onSave}>
|
||||
Save
|
||||
</Button>
|
||||
<Button variant="contained" disableElevation className={classes.button} onClick={() => window.require('electron').remote.getCurrentWindow().close()}>
|
||||
Cancel
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className={classes.actions}>
|
||||
<Button color="primary" variant="contained" disableElevation className={classes.button} onClick={onSave}>
|
||||
Save
|
||||
</Button>
|
||||
<Button variant="contained" disableElevation className={classes.button} onClick={() => window.require('electron').remote.getCurrentWindow().close()}>
|
||||
Cancel
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
);
|
||||
};
|
||||
|
||||
CodeInjection.defaultProps = {
|
||||
allowNodeInJsCodeInjection: false,
|
||||
};
|
||||
|
||||
CodeInjection.propTypes = {
|
||||
allowNodeInJsCodeInjection: PropTypes.bool,
|
||||
classes: PropTypes.object.isRequired,
|
||||
code: PropTypes.string.isRequired,
|
||||
onSave: PropTypes.func.isRequired,
|
||||
|
|
@ -83,6 +113,7 @@ CodeInjection.propTypes = {
|
|||
|
||||
const mapStateToProps = (state) => ({
|
||||
code: state.dialogCodeInjection.form.code || '',
|
||||
allowNodeInJsCodeInjection: state.dialogCodeInjection.form.allowNodeInJsCodeInjection,
|
||||
shouldUseDarkColors: state.general.shouldUseDarkColors,
|
||||
});
|
||||
|
||||
|
|
|
|||
|
|
@ -170,6 +170,7 @@ const getUpdaterDesc = (status, info) => {
|
|||
};
|
||||
|
||||
const Preferences = ({
|
||||
allowNodeInJsCodeInjection,
|
||||
allowPrerelease,
|
||||
askForDownloadPath,
|
||||
attachToMenubar,
|
||||
|
|
@ -1018,7 +1019,7 @@ const Preferences = ({
|
|||
</ListItem>
|
||||
<Divider />
|
||||
<ListItem button onClick={() => requestShowCodeInjectionWindow('js')}>
|
||||
<ListItemText primary="JS Code Injection" secondary={jsCodeInjection ? 'Set' : 'Not set'} />
|
||||
<ListItemText primary="JS Code Injection" secondary={jsCodeInjection ? `Set ${allowNodeInJsCodeInjection ? ' (with access to Node.JS & Electron APIs)' : ''}` : 'Not set'} />
|
||||
<ChevronRightIcon color="action" />
|
||||
</ListItem>
|
||||
<Divider />
|
||||
|
|
@ -1233,6 +1234,7 @@ Preferences.defaultProps = {
|
|||
};
|
||||
|
||||
Preferences.propTypes = {
|
||||
allowNodeInJsCodeInjection: PropTypes.bool.isRequired,
|
||||
allowPrerelease: PropTypes.bool.isRequired,
|
||||
askForDownloadPath: PropTypes.bool.isRequired,
|
||||
attachToMenubar: PropTypes.bool.isRequired,
|
||||
|
|
@ -1275,6 +1277,7 @@ Preferences.propTypes = {
|
|||
};
|
||||
|
||||
const mapStateToProps = (state) => ({
|
||||
allowNodeInJsCodeInjection: state.preferences.allowNodeInJsCodeInjection,
|
||||
allowPrerelease: state.preferences.allowPrerelease,
|
||||
askForDownloadPath: state.preferences.askForDownloadPath,
|
||||
attachToMenubar: state.preferences.attachToMenubar,
|
||||
|
|
|
|||
|
|
@ -16,7 +16,11 @@ export const save = () => (dispatch, getState) => {
|
|||
const { remote } = window.require('electron');
|
||||
|
||||
const codeInjectionType = remote.getGlobal('codeInjectionType');
|
||||
|
||||
requestSetPreference(`${codeInjectionType}CodeInjection`, form.code);
|
||||
if (codeInjectionType === 'js' && typeof form.allowNodeInJsCodeInjection === 'boolean') {
|
||||
requestSetPreference('allowNodeInJsCodeInjection', form.allowNodeInJsCodeInjection);
|
||||
}
|
||||
|
||||
requestShowRequireRestartDialog();
|
||||
|
||||
|
|
|
|||
|
|
@ -10,6 +10,8 @@ const form = (state = {}, action) => {
|
|||
const codeInjectionType = window.require('electron').remote.getGlobal('codeInjectionType');
|
||||
return {
|
||||
code: getPreference(`${codeInjectionType}CodeInjection`),
|
||||
// allowNodeInJsCodeInjection is only used for js injection
|
||||
allowNodeInJsCodeInjection: codeInjectionType === 'js' ? getPreference('allowNodeInJsCodeInjection') : false,
|
||||
};
|
||||
}
|
||||
case UPDATE_CODE_INJECTION_FORM: return { ...state, ...action.changes };
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue