Skip to content

Commit db9fa19

Browse files
emil-wireclaude
andcommitted
Merge security/context-isolation-fix into dev
Brings the original PR#9055 changes to dev branch where they should have been merged originally. 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <[email protected]>
2 parents 4173d94 + 793aef9 commit db9fa19

File tree

17 files changed

+2020
-5563
lines changed

17 files changed

+2020
-5563
lines changed

electron/renderer/src/actions/index.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -191,7 +191,7 @@ export const updateAccountBadgeCount = (id: string, count: number) => {
191191
}, 0);
192192
const ignoreFlash = account?.availability === Availability.Type.BUSY;
193193

194-
window.sendBadgeCount(accumulatedCount, ignoreFlash);
194+
window.wireDesktop?.sendBadgeCount(accumulatedCount, ignoreFlash);
195195

196196
if (account) {
197197
const countHasChanged = account.badgeCount !== count;

electron/renderer/src/components/WebView/Webview.tsx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -211,7 +211,7 @@ const Webview = ({
211211
case EVENT_TYPE.LIFECYCLE.SIGNED_IN: {
212212
if (conversationJoinData) {
213213
const {code, key, domain} = conversationJoinData;
214-
window.sendConversationJoinToHost(accountId, code, key, domain);
214+
window.wireDesktop?.sendConversationJoinToHost(accountId, code, key, domain);
215215
setConversationJoinData(accountId, undefined);
216216
}
217217
updateAccountLifecycle(accountId, channel);
@@ -241,7 +241,7 @@ const Webview = ({
241241

242242
if (isConversationJoinData(data)) {
243243
if (accountLifecycle === EVENT_TYPE.LIFECYCLE.SIGNED_IN) {
244-
window.sendConversationJoinToHost(accountId, data.code, data.key, data.domain);
244+
window.wireDesktop?.sendConversationJoinToHost(accountId, data.code, data.key, data.domain);
245245
setConversationJoinData(accountId, undefined);
246246
} else {
247247
setConversationJoinData(accountId, data);
@@ -283,7 +283,7 @@ const Webview = ({
283283
}, [account, accountLifecycle, conversationJoinData]);
284284

285285
const deleteWebview = (account: Account) => {
286-
window.sendDeleteAccount(account.id, account.sessionID).then(() => {
286+
window.wireDesktop?.sendDeleteAccount(account.id, account.sessionID)?.then(() => {
287287
abortAccountCreation(account.id);
288288
});
289289
};

electron/renderer/src/components/context/EditAccountMenu.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ const EditAccountMenu = ({
6464
<ContextMenuItem
6565
onClick={() => {
6666
connected.switchWebview(accountIndex);
67-
window.sendLogoutAccount(accountId);
67+
window.wireDesktop?.sendLogoutAccount(accountId);
6868
}}
6969
>
7070
{getText('wrapperLogOut')}
@@ -73,7 +73,7 @@ const EditAccountMenu = ({
7373

7474
<ContextMenuItem
7575
onClick={() => {
76-
window.sendDeleteAccount(accountId, sessionID).then(() => {
76+
window.wireDesktop?.sendDeleteAccount(accountId, sessionID)?.then(() => {
7777
connected.abortAccountCreation(accountId);
7878
});
7979
}}

electron/renderer/src/lib/locale.ts

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -19,12 +19,12 @@
1919

2020
import {i18nLanguageIdentifier} from '../../../src/locale';
2121

22-
window.locStrings = window.locStrings || {};
23-
window.locStringsDefault = window.locStringsDefault || {};
24-
window.locale = window.locale || 'en';
22+
const locStrings = window.wireDesktop?.locStrings || {};
23+
const locStringsDefault = window.wireDesktop?.locStringsDefault || {};
24+
const locale = window.wireDesktop?.locale || 'en';
2525

2626
export const getText = (stringIdentifier: i18nLanguageIdentifier, paramReplacements?: Record<string, string>) => {
27-
let str = window.locStrings[stringIdentifier] || window.locStringsDefault[stringIdentifier] || stringIdentifier;
27+
let str = locStrings[stringIdentifier] || locStringsDefault[stringIdentifier] || stringIdentifier;
2828

2929
const replacements = {...paramReplacements};
3030
for (const replacement of Object.keys(replacements)) {
@@ -37,4 +37,4 @@ export const getText = (stringIdentifier: i18nLanguageIdentifier, paramReplaceme
3737
return str;
3838
};
3939

40-
export const wrapperLocale = window.locale;
40+
export const wrapperLocale = locale;

electron/src/lib/eventType.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ export const EVENT_TYPE = {
3333
ACTION: {
3434
CHANGE_ENVIRONMENT: 'EVENT_TYPE.ACTION.CHANGE_ENVIRONMENT',
3535
CHANGE_DOWNLOAD_LOCATION: 'EVENT_TYPE.ACTION.CHANGE_DOWNLOAD_LOCATION',
36+
COPY_TO_CLIPBOARD: 'EVENT_TYPE.ACTION.COPY_TO_CLIPBOARD',
3637
CREATE_SSO_ACCOUNT: 'EVENT_TYPE.ACTION.CREATE_SSO_ACCOUNT',
3738
CREATE_SSO_ACCOUNT_RESPONSE: 'EVENT_TYPE.ACTION.CREATE_SSO_ACCOUNT_RESPONSE',
3839
DECRYPT: 'EVENT_TYPE.ACTION.DECRYPT',
@@ -85,8 +86,16 @@ export const EVENT_TYPE = {
8586
LOCALE_VALUES: 'EVENT_TYPE.PROXY_PROMPT.LOCALE_VALUES',
8687
SUBMITTED: 'EVENT_TYPE.PROXY_PROMPT.AUTHENTICATION_DATA',
8788
},
89+
CONTEXT_MENU: {
90+
SHOW: 'EVENT_TYPE.CONTEXT_MENU.SHOW',
91+
COPY_TEXT: 'EVENT_TYPE.CONTEXT_MENU.COPY_TEXT',
92+
COPY_IMAGE: 'EVENT_TYPE.CONTEXT_MENU.COPY_IMAGE',
93+
SAVE_IMAGE: 'EVENT_TYPE.CONTEXT_MENU.SAVE_IMAGE',
94+
REPLACE_MISSPELLING: 'EVENT_TYPE.CONTEXT_MENU.REPLACE_MISSPELLING',
95+
},
8896
UI: {
8997
BADGE_COUNT: 'EVENT_TYPE.UI.BADGE_COUNT',
98+
SHOULD_USE_DARK_COLORS: 'EVENT_TYPE.UI.SHOULD_USE_DARK_COLORS',
9099
SYSTEM_MENU: 'EVENT_TYPE.UI.SYSTEM_MENU',
91100
THEME_UPDATE: 'EVENT_TYPE.UI.THEME_UPDATE',
92101
WEBAPP_VERSION: 'EVENT_TYPE.UI.WEBAPP_VERSION',

electron/src/locale/index.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ export type i18nStrings = Record<i18nLanguageIdentifier, string>;
5353
export type SupportedI18nLanguage = keyof typeof SUPPORTED_LANGUAGES;
5454
export type SupportedI18nLanguageObject = Record<SupportedI18nLanguage, i18nStrings>;
5555

56-
const app = Electron.app || require('@electron/remote').app;
56+
const app = Electron.app;
5757

5858
export const LANGUAGES: SupportedI18nLanguageObject = {
5959
cs,

electron/src/logging/getLogger.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,8 +26,8 @@ import {LogFactory, LoggerOptions} from '@wireapp/commons';
2626

2727
import {config} from '../settings/config';
2828

29-
const mainProcess = process || require('@electron/remote').process;
30-
const app = Electron.app || require('@electron/remote').app;
29+
const mainProcess = process;
30+
const app = Electron.app;
3131

3232
const logDir = path.join(app.getPath('userData'), 'logs');
3333
const logFile = path.join(logDir, 'electron.log');

electron/src/main.ts

Lines changed: 46 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -17,15 +17,17 @@
1717
*
1818
*/
1919

20-
import * as remoteMain from '@electron/remote/main';
2120
import {
2221
app,
22+
clipboard,
2323
dialog,
2424
BrowserWindow,
2525
BrowserWindowConstructorOptions,
2626
Event as ElectronEvent,
2727
ipcMain,
2828
Menu,
29+
nativeImage,
30+
nativeTheme,
2931
WebContents,
3032
desktopCapturer,
3133
safeStorage,
@@ -74,8 +76,6 @@ import {ProxyPromptWindow} from './window/ProxyPromptWindow';
7476
import {WindowManager} from './window/WindowManager';
7577
import * as WindowUtil from './window/WindowUtil';
7678

77-
remoteMain.initialize();
78-
7979
const APP_PATH = path.join(app.getAppPath(), config.electronDirectory);
8080
const INDEX_HTML = path.join(APP_PATH, 'renderer/index.html');
8181
const LOG_DIR = path.join(app.getPath('userData'), 'logs');
@@ -278,7 +278,7 @@ const showMainWindow = async (mainWindowState: windowStateKeeper.State): Promise
278278
title: config.name,
279279
webPreferences: {
280280
backgroundThrottling: false,
281-
contextIsolation: false,
281+
contextIsolation: true,
282282
nodeIntegration: false,
283283
preload: PRELOAD_JS,
284284
sandbox: false,
@@ -296,10 +296,49 @@ const showMainWindow = async (mainWindowState: windowStateKeeper.State): Promise
296296
ipcMain.handle(EVENT_TYPE.ACTION.DECRYPT, (event, encrypted: Uint8Array) =>
297297
safeStorage.decryptString(Buffer.from(encrypted)),
298298
);
299+
ipcMain.handle(EVENT_TYPE.UI.SHOULD_USE_DARK_COLORS, () => {
300+
return nativeTheme.shouldUseDarkColors;
301+
});
299302

300-
main = new BrowserWindow(options);
303+
ipcMain.handle(EVENT_TYPE.CONTEXT_MENU.COPY_TEXT, (event, text: string) => {
304+
clipboard.writeText(text);
305+
});
306+
307+
ipcMain.handle(EVENT_TYPE.CONTEXT_MENU.COPY_IMAGE, async (event, imageUrl: string) => {
308+
try {
309+
const response = await fetch(imageUrl, {
310+
headers: {
311+
'User-Agent': config.userAgent,
312+
},
313+
});
314+
const bytes = await response.arrayBuffer();
315+
const image = nativeImage.createFromBuffer(Buffer.from(bytes));
316+
clipboard.writeImage(image);
317+
} catch (error) {
318+
console.error('Failed to copy image:', error);
319+
}
320+
});
301321

302-
remoteMain.enable(main.webContents);
322+
ipcMain.handle(EVENT_TYPE.CONTEXT_MENU.SAVE_IMAGE, async (event, imageUrl: string, timestamp?: string) => {
323+
try {
324+
const response = await fetch(imageUrl, {
325+
headers: {
326+
'User-Agent': config.userAgent,
327+
},
328+
});
329+
const bytes = await response.arrayBuffer();
330+
ipcMain.emit(EVENT_TYPE.ACTION.SAVE_PICTURE, event, new Uint8Array(bytes), timestamp);
331+
} catch (error) {
332+
console.error('Failed to save image:', error);
333+
}
334+
});
335+
336+
ipcMain.handle(EVENT_TYPE.CONTEXT_MENU.REPLACE_MISSPELLING, (event, suggestion: string) => {
337+
const webContents = event.sender;
338+
webContents.replaceMisspelling(suggestion);
339+
});
340+
341+
main = new BrowserWindow(options);
303342

304343
main.setMenuBarVisibility(showMenuBar);
305344

@@ -632,7 +671,6 @@ class ElectronWrapperInit {
632671
const enableSpellChecking = settings.restore(SettingsType.ENABLE_SPELL_CHECKING, true);
633672

634673
app.on('web-contents-created', async (webviewEvent: ElectronEvent, contents: WebContents) => {
635-
remoteMain.enable(contents);
636674
// disable new Windows by default on everything
637675
contents.setWindowOpenHandler(() => {
638676
return {action: 'deny'};
@@ -645,7 +683,7 @@ class ElectronWrapperInit {
645683
params.contextIsolation = 'true';
646684
params.plugins = 'false';
647685
webPreferences.allowRunningInsecureContent = false;
648-
webPreferences.contextIsolation = false;
686+
webPreferences.contextIsolation = true;
649687
webPreferences.experimentalFeatures = false;
650688
webPreferences.nodeIntegration = false;
651689
webPreferences.preload = PRELOAD_RENDERER_JS;

0 commit comments

Comments
 (0)