Skip to content

Commit 7f67588

Browse files
authored
Merge pull request #9071 from wireapp/security/context-isolation-clean
feat: modernize Electron architecture and update dependencies [WPB-20012] [WPB-20013]
2 parents b7378b5 + 2081748 commit 7f67588

File tree

21 files changed

+2252
-5652
lines changed

21 files changed

+2252
-5652
lines changed

electron/renderer/src/actions/index.ts

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ import {Availability} from '@wireapp/protocol-messaging';
2323

2424
import {AccountAction, accountAction} from './AccountAction';
2525

26+
import {getLogger} from '../../../src/logging/getLogger';
2627
import {AppDispatch, State} from '../index';
2728
import {generateUUID} from '../lib/util';
2829
import {
@@ -41,6 +42,8 @@ import {AccountSelector} from '../selector/AccountSelector';
4142
import {Account, ConversationJoinData} from '../types/account';
4243
import {ContextMenuState} from '../types/contextMenuState';
4344

45+
const logger = getLogger('actions');
46+
4447
export enum ACCOUNT_ACTION {
4548
ADD_ACCOUNT = 'ADD_ACCOUNT',
4649
DELETE_ACCOUNT = 'DELETE_ACCOUNT',
@@ -151,7 +154,7 @@ export const addAccountWithSession = () => {
151154
}
152155

153156
if (hasReachedAccountLimit) {
154-
console.warn('Reached number of maximum accounts');
157+
logger.warn('Reached number of maximum accounts');
155158
} else {
156159
dispatch(addAccount());
157160
}
@@ -177,7 +180,7 @@ export const updateAccountData = (id: string, data: Partial<Account>) => {
177180
if (!validatedAccountData.error) {
178181
dispatch(updateAccount(id, validatedAccountData.value));
179182
} else {
180-
console.warn('Got invalid account data:', validatedAccountData.error);
183+
logger.warn('Got invalid account data:', validatedAccountData.error);
181184
}
182185
};
183186
};
@@ -191,15 +194,15 @@ export const updateAccountBadgeCount = (id: string, count: number) => {
191194
}, 0);
192195
const ignoreFlash = account?.availability === Availability.Type.BUSY;
193196

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

196199
if (account) {
197200
const countHasChanged = account.badgeCount !== count;
198201
if (countHasChanged) {
199202
dispatch(updateAccountBadge(id, count));
200203
}
201204
} else {
202-
console.warn('Missing account when updating badge count');
205+
logger.warn('Missing account when updating badge count');
203206
}
204207
};
205208
};

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

Lines changed: 20 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ import {ContainerSM, COLOR, H1, Logo, Text, TextLink} from '@wireapp/react-ui-ki
2727
import './Webview.css';
2828

2929
import {EVENT_TYPE} from '../../../../src/lib/eventType';
30+
import {getLogger} from '../../../../src/logging/getLogger';
3031
import {
3132
abortAccountCreation,
3233
resetIdentity,
@@ -58,7 +59,7 @@ const getEnvironmentUrl = (account: Account) => {
5859
url.searchParams.set('id', account.id);
5960

6061
// set the current language
61-
url.searchParams.set('hl', wrapperLocale);
62+
url.searchParams.set('hl', wrapperLocale());
6263

6364
if (account.ssoCode && account.isAdding) {
6465
url.pathname = '/auth';
@@ -104,18 +105,17 @@ const Webview = ({
104105
const [canDelete, setCanDelete] = useState(false);
105106
const [url, setUrl] = useState(getEnvironmentUrl(account));
106107
const [webviewError, setWebviewError] = useState<DidFailLoadEvent | null>(null);
108+
const logger = getLogger('Webview');
107109

108110
useEffect(() => {
109111
const newUrl = getEnvironmentUrl(account);
110-
console.info(`Loading WebApp URL "${newUrl}" ...`);
112+
logger.info(`Loading WebApp URL "${newUrl}" ...`);
111113
if (url !== newUrl && webviewRef.current) {
112114
setUrl(newUrl);
113115
try {
114-
webviewRef.current
115-
.loadURL(newUrl)
116-
.catch((error: any) => console.error(`Navigating to ${newUrl} failed`, error));
116+
webviewRef.current.loadURL(newUrl).catch((error: any) => logger.error(`Navigating to ${newUrl} failed`, error));
117117
} catch (error) {
118-
console.warn('Can not #loadURL before attaching webview to DOM', error);
118+
logger.warn('Can not #loadURL before attaching webview to DOM', error);
119119
}
120120
}
121121
// eslint-disable-next-line react-hooks/exhaustive-deps
@@ -164,19 +164,21 @@ const Webview = ({
164164
useEffect(() => {
165165
const listener = (error: DidFailLoadEvent) => {
166166
const urlOrigin = new URL(getEnvironmentUrl(account)).origin;
167-
console.warn(`Webview fired "did-fail-load" for URL "${error.validatedURL}" and account ID "${account.id}"`);
167+
logger.warn(`Webview fired "did-fail-load" for URL "${error.validatedURL}" and account ID "${account.id}"`);
168168
if (error.validatedURL.startsWith(urlOrigin)) {
169169
setWebviewError(error);
170170
}
171171
};
172-
webviewRef.current?.addEventListener(ON_WEBVIEW_ERROR, listener);
172+
173+
const currentWebview = webviewRef.current;
174+
currentWebview?.addEventListener(ON_WEBVIEW_ERROR, listener);
173175

174176
return () => {
175-
if (webviewRef.current) {
176-
webviewRef.current.removeEventListener(ON_WEBVIEW_ERROR, listener);
177+
if (currentWebview) {
178+
currentWebview.removeEventListener(ON_WEBVIEW_ERROR, listener);
177179
}
178180
};
179-
}, [webviewRef, account]);
181+
}, [account, logger]);
180182

181183
useEffect(() => {
182184
const onIpcMessage = ({channel, args}: {args: unknown[]; channel: string}) => {
@@ -211,7 +213,7 @@ const Webview = ({
211213
case EVENT_TYPE.LIFECYCLE.SIGNED_IN: {
212214
if (conversationJoinData) {
213215
const {code, key, domain} = conversationJoinData;
214-
window.sendConversationJoinToHost(accountId, code, key, domain);
216+
window.wireDesktop?.sendConversationJoinToHost(accountId, code, key, domain);
215217
setConversationJoinData(accountId, undefined);
216218
}
217219
updateAccountLifecycle(accountId, channel);
@@ -241,7 +243,7 @@ const Webview = ({
241243

242244
if (isConversationJoinData(data)) {
243245
if (accountLifecycle === EVENT_TYPE.LIFECYCLE.SIGNED_IN) {
244-
window.sendConversationJoinToHost(accountId, data.code, data.key, data.domain);
246+
window.wireDesktop?.sendConversationJoinToHost(accountId, data.code, data.key, data.domain);
245247
setConversationJoinData(accountId, undefined);
246248
} else {
247249
setConversationJoinData(accountId, data);
@@ -272,18 +274,19 @@ const Webview = ({
272274
}
273275
};
274276

275-
webviewRef.current?.addEventListener(ON_IPC_MESSAGE, onIpcMessage);
277+
const currentWebview = webviewRef.current;
278+
currentWebview?.addEventListener(ON_IPC_MESSAGE, onIpcMessage);
276279

277280
return () => {
278-
if (webviewRef.current) {
279-
webviewRef.current.removeEventListener(ON_IPC_MESSAGE, onIpcMessage);
281+
if (currentWebview) {
282+
currentWebview.removeEventListener(ON_IPC_MESSAGE, onIpcMessage);
280283
}
281284
};
282285
// eslint-disable-next-line react-hooks/exhaustive-deps
283286
}, [account, accountLifecycle, conversationJoinData]);
284287

285288
const deleteWebview = (account: Account) => {
286-
window.sendDeleteAccount(account.id, account.sessionID).then(() => {
289+
window.wireDesktop?.sendDeleteAccount(account.id, account.sessionID)?.then(() => {
287290
abortAccountCreation(account.id);
288291
});
289292
};

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/configureStore.ts

Lines changed: 31 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -18,15 +18,18 @@
1818
*/
1919

2020
import throttle from 'lodash/throttle';
21-
import {applyMiddleware, createStore} from 'redux';
21+
import {applyMiddleware, createStore, Middleware} from 'redux';
2222
import {createLogger} from 'redux-logger';
2323
import thunk from 'redux-thunk';
2424

2525
import {loadState, saveState} from './lib/localStorage';
2626
import reducers from './reducers';
2727

28+
import {getLogger} from '../../src/logging/getLogger';
29+
2830
const HALF_SECOND = 500;
2931
const persistedState = loadState();
32+
const fileLogger = getLogger('configureStore');
3033

3134
export const configureStore = (thunkArguments: Object) => {
3235
const store = createStore(reducers, persistedState, createMiddleware(thunkArguments));
@@ -49,22 +52,35 @@ export const configureStore = (thunkArguments: Object) => {
4952
return store;
5053
};
5154

55+
const isValidMiddleware = (middleware: unknown): middleware is Middleware => {
56+
return typeof middleware === 'function';
57+
};
58+
5259
const createMiddleware = (thunkArguments: Object = {}) => {
53-
const middlewares = [];
54-
middlewares.push(thunk.withExtraArgument(thunkArguments));
60+
const thunkWithExtraArgument = thunk.withExtraArgument(thunkArguments);
61+
62+
const middlewares: Middleware[] = [];
63+
64+
middlewares.push(thunkWithExtraArgument);
65+
5566
if (process.env.NODE_ENV !== 'production') {
56-
middlewares.push(
57-
createLogger({
58-
collapsed: true,
59-
diff: true,
60-
duration: true,
61-
level: {
62-
action: 'info',
63-
nextState: 'info',
64-
prevState: false,
65-
},
66-
}),
67-
);
67+
const logger = createLogger({
68+
collapsed: true,
69+
diff: true,
70+
duration: true,
71+
level: {
72+
action: 'info',
73+
nextState: 'info',
74+
prevState: false,
75+
},
76+
});
77+
78+
if (isValidMiddleware(logger)) {
79+
middlewares.push(logger);
80+
} else {
81+
fileLogger.warn('Logger middleware failed type validation');
82+
}
6883
}
84+
6985
return applyMiddleware(...middlewares);
7086
};

electron/renderer/src/lib/WindowUrl.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ export class WindowUrl {
3232
});
3333

3434
// set the current language
35-
envUrlParams.set('hl', wrapperLocale);
35+
envUrlParams.set('hl', wrapperLocale());
3636

3737
return customBackendUrlParsed.href;
3838
}

electron/renderer/src/lib/localStorage.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,17 +17,19 @@
1717
*
1818
*/
1919

20+
import {getLogger} from '../../../src/logging/getLogger';
2021
import {State} from '../index';
2122

2223
const STATE_NAME = 'state';
24+
const logger = getLogger('localStorage');
2325

2426
export const loadState = (): State | undefined => {
2527
try {
2628
const serializedState = localStorage.getItem(STATE_NAME);
2729
return !!serializedState ? (JSON.parse(serializedState) as State) : undefined;
2830
} catch (error) {
2931
if (error instanceof Error) {
30-
console.error('ERROR: Failed to load state ', error.message);
32+
logger.error('ERROR: Failed to load state ', error.message);
3133
}
3234
return undefined;
3335
}
@@ -39,7 +41,7 @@ export const saveState = (state: State) => {
3941
localStorage.setItem(STATE_NAME, serializedState);
4042
} catch (error) {
4143
if (error instanceof Error) {
42-
console.error('ERROR: Failed to save state ', error.message);
44+
logger.error('ERROR: Failed to save state ', error.message);
4345
}
4446
}
4547
};

electron/renderer/src/lib/locale.ts

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

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

22-
window.locStrings = window.locStrings || {};
23-
window.locStringsDefault = window.locStringsDefault || {};
24-
window.locale = window.locale || 'en';
25-
2622
export const getText = (stringIdentifier: i18nLanguageIdentifier, paramReplacements?: Record<string, string>) => {
27-
let str = window.locStrings[stringIdentifier] || window.locStringsDefault[stringIdentifier] || stringIdentifier;
23+
const locStrings = window.wireDesktop?.locStrings || {};
24+
const locStringsDefault = window.wireDesktop?.locStringsDefault || {};
25+
26+
let str = locStrings[stringIdentifier] || locStringsDefault[stringIdentifier] || stringIdentifier;
2827

2928
const replacements = {...paramReplacements};
3029
for (const replacement of Object.keys(replacements)) {
@@ -37,4 +36,4 @@ export const getText = (stringIdentifier: i18nLanguageIdentifier, paramReplaceme
3736
return str;
3837
};
3938

40-
export const wrapperLocale = window.locale;
39+
export const wrapperLocale = () => window.wireDesktop?.locale || 'en';

electron/src/lib/eventType.ts

Lines changed: 10 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,9 +86,18 @@ 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',
100+
SYSTEM_THEME_CHANGED: 'EVENT_TYPE.UI.SYSTEM_THEME_CHANGED',
91101
THEME_UPDATE: 'EVENT_TYPE.UI.THEME_UPDATE',
92102
WEBAPP_VERSION: 'EVENT_TYPE.UI.WEBAPP_VERSION',
93103
WEBAPP_AVS_VERSION: 'EVENT_TYPE.UI.WEBAPP_AVS_VERSION',

electron/src/locale/index.ts

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@
1919

2020
import * as Electron from 'electron';
2121

22+
import * as path from 'path';
23+
2224
import cs from './cs-CZ.json';
2325
import da from './da-DK.json';
2426
import de from './de-DE.json';
@@ -44,6 +46,7 @@ import tr from './tr-TR.json';
4446
import uk from './uk-UA.json';
4547
import zh from './zh-CN.json';
4648

49+
import {getLogger} from '../logging/getLogger';
4750
import {config} from '../settings/config';
4851
import {settings} from '../settings/ConfigurationPersistence';
4952
import {SettingsType} from '../settings/SettingsType';
@@ -53,7 +56,8 @@ export type i18nStrings = Record<i18nLanguageIdentifier, string>;
5356
export type SupportedI18nLanguage = keyof typeof SUPPORTED_LANGUAGES;
5457
export type SupportedI18nLanguageObject = Record<SupportedI18nLanguage, i18nStrings>;
5558

56-
const app = Electron.app || require('@electron/remote').app;
59+
const app = Electron.app;
60+
const logger = getLogger(path.basename(__filename));
5761

5862
export const LANGUAGES: SupportedI18nLanguageObject = {
5963
cs,
@@ -141,7 +145,20 @@ let current: SupportedI18nLanguage | undefined;
141145
export const getCurrent = (): SupportedI18nLanguage => {
142146
if (!current) {
143147
// We care only about the language part and not the country (en_US, de_DE)
144-
const defaultLocale = parseLocale(app.getLocale().substring(0, 2));
148+
let systemLocale = 'en';
149+
150+
try {
151+
if (app?.getLocale) {
152+
systemLocale = app.getLocale().substring(0, 2);
153+
}
154+
} catch (error) {
155+
logger.warn('Failed to get system locale from app:', error);
156+
if (typeof navigator !== 'undefined' && navigator.language) {
157+
systemLocale = navigator.language.substring(0, 2);
158+
}
159+
}
160+
161+
const defaultLocale = parseLocale(systemLocale);
145162
current = settings.restore(SettingsType.LOCALE, defaultLocale);
146163
}
147164
return current;

0 commit comments

Comments
 (0)