Skip to content

Commit 42ea62b

Browse files
committed
refactor: context isolation via preload script
Signed-off-by: Adam Setch <[email protected]>
1 parent 863fcac commit 42ea62b

13 files changed

+191
-42
lines changed

config/webpack.config.main.base.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import path from 'node:path';
22
import type webpack from 'webpack';
33
import { merge } from 'webpack-merge';
4+
45
import baseConfig from './webpack.config.common';
56
import webpackPaths from './webpack.paths';
67

config/webpack.config.main.prod.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import TerserPlugin from 'terser-webpack-plugin';
22
import type webpack from 'webpack';
33
import { merge } from 'webpack-merge';
4+
45
import baseConfig from './webpack.config.main.base';
56

67
const configuration: webpack.Configuration = {
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
import path from 'node:path';
2+
import type webpack from 'webpack';
3+
import { merge } from 'webpack-merge';
4+
5+
import baseConfig from './webpack.config.common';
6+
import webpackPaths from './webpack.paths';
7+
8+
const configuration: webpack.Configuration = {
9+
devtool: 'inline-source-map',
10+
11+
mode: 'development',
12+
13+
target: 'electron-main',
14+
15+
entry: [path.join(webpackPaths.srcMainPath, 'preload.ts')],
16+
17+
output: {
18+
path: webpackPaths.buildPath,
19+
filename: 'preload.js',
20+
library: {
21+
type: 'umd',
22+
},
23+
},
24+
};
25+
26+
export default merge(baseConfig, configuration);
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
import TerserPlugin from 'terser-webpack-plugin';
2+
import type webpack from 'webpack';
3+
import { merge } from 'webpack-merge';
4+
5+
import baseConfig from './webpack.config.preload.base';
6+
7+
const configuration: webpack.Configuration = {
8+
devtool: 'source-map',
9+
10+
mode: 'production',
11+
12+
optimization: {
13+
minimize: true,
14+
minimizer: [new TerserPlugin()],
15+
},
16+
};
17+
18+
export default merge(baseConfig, configuration);

config/webpack.config.renderer.base.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import HtmlWebpackPlugin from 'html-webpack-plugin';
44
import MiniCssExtractPlugin from 'mini-css-extract-plugin';
55
import webpack from 'webpack';
66
import { merge } from 'webpack-merge';
7+
78
import baseConfig from './webpack.config.common';
89
import webpackPaths from './webpack.paths';
910

config/webpack.config.renderer.prod.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import CssMinimizerPlugin from 'css-minimizer-webpack-plugin';
22
import TerserPlugin from 'terser-webpack-plugin';
33
import type webpack from 'webpack';
44
import { merge } from 'webpack-merge';
5+
56
import baseConfig from './webpack.config.renderer.base';
67

78
const configuration: webpack.Configuration = {

package.json

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,13 @@
55
"main": "build/main.js",
66
"scripts": {
77
"clean": "rimraf build coverage dist node_modules",
8-
"build": "concurrently --names \"main,renderer\" --prefix-colors \"blue,green\" \"pnpm build:main\" \"pnpm build:renderer\"",
8+
"build": "concurrently --names \"main,preload,renderer\" --prefix-colors \"blue,magenta,green\" \"pnpm build:main\" \"pnpm build:preload\" \"pnpm build:renderer\"",
99
"build:main": "webpack --config ./config/webpack.config.main.prod.ts",
10+
"build:preload": "webpack --config ./config/webpack.config.preload.prod.ts",
1011
"build:renderer": "webpack --config ./config/webpack.config.renderer.prod.ts",
11-
"watch": "concurrently --names \"main,renderer\" --prefix-colors \"blue,green\" \"pnpm watch:main\" \"pnpm watch:renderer\"",
12+
"watch": "concurrently --names \"main,preload,renderer\" --prefix-colors \"blue,magenta,green\" \"pnpm watch:main\" \"pnpm watch:preload\" \"pnpm watch:renderer\"",
1213
"watch:main": "webpack --watch --config ./config/webpack.config.main.base.ts",
14+
"watch:preload": "webpack --watch --config ./config/webpack.config.preload.base.ts",
1315
"watch:renderer": "webpack --watch --config ./config/webpack.config.renderer.base.ts",
1416
"prepare:remove-source-maps": "ts-node ./scripts/delete-source-maps.ts",
1517
"package:linux": "electron-builder --linux",

src/main/main.ts

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import path from 'path';
12
import { app, globalShortcut, ipcMain as ipc, safeStorage } from 'electron';
23
import log from 'electron-log';
34
import { menubar } from 'menubar';
@@ -22,8 +23,10 @@ const browserWindowOpts = {
2223
skipTaskbar: true, // Hide the app from the Windows taskbar
2324
// TODO #700 refactor to use preload script with a context bridge
2425
webPreferences: {
25-
nodeIntegration: true,
26-
contextIsolation: false,
26+
preload: path.join(__dirname, 'preload.js'),
27+
contextIsolation: true, // TODO change this
28+
enableRemoteModule: false,
29+
nodeIntegration: false, // TODO change this
2730
},
2831
};
2932

@@ -125,7 +128,7 @@ app.whenReady().then(async () => {
125128

126129
ipc.on(namespacedEvent('window-hide'), () => mb.hideWindow());
127130

128-
ipc.on(namespacedEvent('quit'), () => mb.app.quit());
131+
// ipc.on(namespacedEvent('quit'), () => mb.app.quit());
129132

130133
ipc.on(
131134
namespacedEvent('use-alternate-idle-icon'),

src/main/preload.ts

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
import { contextBridge, ipcRenderer } from 'electron';
2+
import { namespacedEvent } from '../shared/events';
3+
4+
import { Constants } from '../renderer/utils/constants';
5+
import type { GitifyAPI } from './types';
6+
7+
const api: GitifyAPI = {
8+
// Define the global variable
9+
global: globalThis,
10+
11+
openExternalLink: (url) =>
12+
ipcRenderer.send(namespacedEvent('open-external-link'), url),
13+
14+
getAppVersion: () => ipcRenderer.invoke(namespacedEvent('version')),
15+
16+
encryptValue: (value) =>
17+
ipcRenderer.invoke(namespacedEvent('safe-storage-encrypt'), value),
18+
19+
decryptValue: (value) =>
20+
ipcRenderer.invoke(namespacedEvent('safe-storage-decrypt'), value),
21+
22+
quitApp: () => ipcRenderer.send(namespacedEvent('quit')),
23+
24+
showWindow: () => ipcRenderer.send(namespacedEvent('window-show')),
25+
26+
hideWindow: () => ipcRenderer.send(namespacedEvent('window-hide')),
27+
28+
setAutoLaunch: (value) =>
29+
ipcRenderer.send(namespacedEvent('update-auto-launch'), {
30+
openAtLogin: value,
31+
openAsHidden: value,
32+
}),
33+
34+
setAlternateIdleIcon: (value) =>
35+
ipcRenderer.send(namespacedEvent('use-alternate-idle-icon'), value),
36+
37+
setKeyboardShortcut: (keyboardShortcut) =>
38+
ipcRenderer.send(namespacedEvent('update-keyboard-shortcut'), {
39+
enabled: keyboardShortcut,
40+
keyboardShortcut: Constants.DEFAULT_KEYBOARD_SHORTCUT,
41+
}),
42+
43+
updateTrayIcon: (notificationsLength = 0) => {
44+
if (notificationsLength < 0) {
45+
ipcRenderer.send(namespacedEvent('icon-error'));
46+
return;
47+
}
48+
49+
if (notificationsLength > 0) {
50+
ipcRenderer.send(namespacedEvent('icon-active'));
51+
return;
52+
}
53+
54+
ipcRenderer.send(namespacedEvent('icon-idle'));
55+
// ipcRenderer.send(namespacedEvent('update-tray-icon'), notificationsLength),
56+
},
57+
58+
updateTrayTitle: (title = '') =>
59+
ipcRenderer.send(namespacedEvent('update-title'), title),
60+
};
61+
62+
contextBridge.exposeInMainWorld('gitify', api);

src/main/types.ts

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
export interface GitifyAPI {
2+
global: typeof globalThis;
3+
openExternalLink: (url: string) => void;
4+
getAppVersion: () => Promise<string>;
5+
encryptValue: (value: string) => Promise<string>;
6+
decryptValue: (value: string) => Promise<string>;
7+
quitApp: () => void;
8+
showWindow: () => void;
9+
hideWindow: () => void;
10+
setAutoLaunch: (value: boolean) => void;
11+
setAlternateIdleIcon: (value: boolean) => void;
12+
setKeyboardShortcut: (keyboardShortcut: boolean) => void;
13+
updateTrayIcon: (notificationsLength?: number) => void;
14+
updateTrayTitle: (title?: string) => void;
15+
}

0 commit comments

Comments
 (0)