Electron: Disable navigation to external URLs (#3965)
This commit is contained in:
parent
066cd6960b
commit
b901ce82a7
@ -1,17 +1,39 @@
|
|||||||
import { getLastWindow } from './utils';
|
import { checkIsWebContentsUrlAllowed, getLastWindow } from './utils';
|
||||||
|
|
||||||
let localStorage: Record<string, any> | undefined;
|
let localStorage: Record<string, any> | undefined;
|
||||||
|
|
||||||
export async function captureLocalStorage(): Promise<void> {
|
export async function captureLocalStorage(): Promise<void> {
|
||||||
localStorage = await (getLastWindow())?.webContents.executeJavaScript('({ ...localStorage });');
|
const lastWindow = getLastWindow();
|
||||||
}
|
|
||||||
|
|
||||||
export async function restoreLocalStorage(): Promise<void> {
|
if (!lastWindow) {
|
||||||
if (!localStorage) {
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
await getLastWindow()?.webContents.executeJavaScript(
|
const contents = lastWindow.webContents;
|
||||||
|
const contentsUrl = contents.getURL();
|
||||||
|
|
||||||
|
if (!checkIsWebContentsUrlAllowed(contentsUrl)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
localStorage = await contents.executeJavaScript('({ ...localStorage });');
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function restoreLocalStorage(): Promise<void> {
|
||||||
|
const lastWindow = getLastWindow();
|
||||||
|
|
||||||
|
if (!lastWindow || !localStorage) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const contents = lastWindow.webContents;
|
||||||
|
const contentsUrl = contents.getURL();
|
||||||
|
|
||||||
|
if (!checkIsWebContentsUrlAllowed(contentsUrl)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
await contents.executeJavaScript(
|
||||||
Object.keys(localStorage).map(
|
Object.keys(localStorage).map(
|
||||||
(key: string) => `localStorage.setItem('${key}', JSON.stringify(${localStorage![key]}))`,
|
(key: string) => `localStorage.setItem('${key}', JSON.stringify(${localStorage![key]}))`,
|
||||||
).join(';'),
|
).join(';'),
|
||||||
|
|||||||
@ -5,6 +5,10 @@ import fs from 'fs';
|
|||||||
|
|
||||||
import type { TrafficLightPosition } from '../types/electron';
|
import type { TrafficLightPosition } from '../types/electron';
|
||||||
|
|
||||||
|
import { BASE_URL, PRODUCTION_URL } from '../config';
|
||||||
|
|
||||||
|
const ALLOWED_URL_ORIGINS = [BASE_URL!, PRODUCTION_URL].map((url) => (new URL(url).origin));
|
||||||
|
|
||||||
export const IS_MAC_OS = process.platform === 'darwin';
|
export const IS_MAC_OS = process.platform === 'darwin';
|
||||||
export const IS_WINDOWS = process.platform === 'win32';
|
export const IS_WINDOWS = process.platform === 'win32';
|
||||||
export const IS_LINUX = process.platform === 'linux';
|
export const IS_LINUX = process.platform === 'linux';
|
||||||
@ -56,6 +60,20 @@ export function getAppTitle(chatTitle?: string): string {
|
|||||||
return `${chatTitle} · ${appName}`;
|
return `${chatTitle} · ${appName}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function checkIsWebContentsUrlAllowed(url: string): boolean {
|
||||||
|
if (!app.isPackaged) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
const parsedUrl = new URL(url);
|
||||||
|
|
||||||
|
if (parsedUrl.pathname === encodeURI(`${__dirname}/index.html`)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ALLOWED_URL_ORIGINS.includes(parsedUrl.origin);
|
||||||
|
}
|
||||||
|
|
||||||
export const TRAFFIC_LIGHT_POSITION: Record<TrafficLightPosition, Point> = {
|
export const TRAFFIC_LIGHT_POSITION: Record<TrafficLightPosition, Point> = {
|
||||||
standard: { x: 10, y: 20 },
|
standard: { x: 10, y: 20 },
|
||||||
lowered: { x: 10, y: 52 },
|
lowered: { x: 10, y: 52 },
|
||||||
|
|||||||
@ -12,8 +12,8 @@ import { processDeeplink } from './deeplink';
|
|||||||
import { captureLocalStorage, restoreLocalStorage } from './localStorage';
|
import { captureLocalStorage, restoreLocalStorage } from './localStorage';
|
||||||
import tray from './tray';
|
import tray from './tray';
|
||||||
import {
|
import {
|
||||||
forceQuit, getAppTitle, getCurrentWindow, getLastWindow, hasExtraWindows, IS_FIRST_RUN, IS_MAC_OS,
|
checkIsWebContentsUrlAllowed, forceQuit, getAppTitle, getCurrentWindow, getLastWindow, hasExtraWindows,
|
||||||
IS_PREVIEW, IS_WINDOWS, reloadWindows, store, TRAFFIC_LIGHT_POSITION, windows,
|
IS_FIRST_RUN, IS_MAC_OS, IS_PREVIEW, IS_WINDOWS, reloadWindows, store, TRAFFIC_LIGHT_POSITION, windows,
|
||||||
} from './utils';
|
} from './utils';
|
||||||
import windowStateKeeper from './windowState';
|
import windowStateKeeper from './windowState';
|
||||||
|
|
||||||
@ -80,6 +80,12 @@ export function createWindow(url?: string) {
|
|||||||
return deviceType === 'hid' && ALLOWED_DEVICE_ORIGINS.includes(origin);
|
return deviceType === 'hid' && ALLOWED_DEVICE_ORIGINS.includes(origin);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
window.webContents.on('will-navigate', (event, newUrl) => {
|
||||||
|
if (!checkIsWebContentsUrlAllowed(newUrl)) {
|
||||||
|
event.preventDefault();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
window.on('page-title-updated', (event: Event) => {
|
window.on('page-title-updated', (event: Event) => {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
});
|
});
|
||||||
@ -139,7 +145,7 @@ export function createWindow(url?: string) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function loadWindowUrl(window: BrowserWindow, url?: string, hash?: string): void {
|
function loadWindowUrl(window: BrowserWindow, url?: string, hash?: string): void {
|
||||||
if (url) {
|
if (url && checkIsWebContentsUrlAllowed(url)) {
|
||||||
window.loadURL(url);
|
window.loadURL(url);
|
||||||
} else if (!app.isPackaged) {
|
} else if (!app.isPackaged) {
|
||||||
window.loadURL(`http://localhost:1234${hash}`);
|
window.loadURL(`http://localhost:1234${hash}`);
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user