mirror of
https://github.com/toeverything/AFFiNE.git
synced 2026-02-13 12:55:00 +00:00
fix(electron): do not use async callback in onBeforeSendHeaders (#7894)
it seems using async callback for onBeforeSendHeaders may crash the app. the main reason why it is async is to read the cookies from session. fix AF-1172
This commit is contained in:
@@ -1,7 +1,6 @@
|
||||
import path from 'node:path';
|
||||
|
||||
import type { App, BrowserWindow } from 'electron';
|
||||
import { ipcMain } from 'electron';
|
||||
import type { App } from 'electron';
|
||||
|
||||
import { buildType, CLOUD_BASE_URL, isDev } from './config';
|
||||
import { mainWindowOrigin } from './constants';
|
||||
@@ -103,20 +102,8 @@ async function handleOauthJwt(url: string) {
|
||||
),
|
||||
});
|
||||
|
||||
let hiddenWindow: BrowserWindow | null = null;
|
||||
|
||||
ipcMain.once('affine:login', () => {
|
||||
hiddenWindow?.destroy();
|
||||
if (urlObj.searchParams.get('next') === 'onboarding') {
|
||||
// eslint-disable-next-line @typescript-eslint/no-floating-promises
|
||||
mainWindow.loadURL(mainWindowOrigin + '/auth/onboarding');
|
||||
}
|
||||
});
|
||||
|
||||
// hacks to refresh auth state in the main window
|
||||
hiddenWindow = await handleOpenUrlInHiddenWindow(
|
||||
mainWindowOrigin + '/auth/signIn'
|
||||
);
|
||||
await handleOpenUrlInHiddenWindow(mainWindowOrigin + '/auth/signIn');
|
||||
} catch (e) {
|
||||
logger.error('failed to open url in popup', e);
|
||||
}
|
||||
|
||||
@@ -3,8 +3,7 @@ import { join } from 'node:path';
|
||||
import { net, protocol, session } from 'electron';
|
||||
|
||||
import { CLOUD_BASE_URL } from './config';
|
||||
import { logger } from './logger';
|
||||
import { getCookie } from './windows-manager';
|
||||
import { getCookies } from './windows-manager';
|
||||
|
||||
protocol.registerSchemesAsPrivileged([
|
||||
{
|
||||
@@ -104,33 +103,23 @@ export function registerProtocol() {
|
||||
);
|
||||
|
||||
session.defaultSession.webRequest.onBeforeSendHeaders((details, callback) => {
|
||||
(async () => {
|
||||
const url = new URL(details.url);
|
||||
const pathname = url.pathname;
|
||||
// if sending request to the cloud, attach the session cookie
|
||||
if (isNetworkResource(pathname)) {
|
||||
const cookie = await getCookie(CLOUD_BASE_URL);
|
||||
if (cookie) {
|
||||
const cookieString = cookie
|
||||
.map(c => `${c.name}=${c.value}`)
|
||||
.join('; ');
|
||||
details.requestHeaders['cookie'] = cookieString;
|
||||
}
|
||||
|
||||
// add the referer and origin headers
|
||||
details.requestHeaders['referer'] ??= CLOUD_BASE_URL;
|
||||
details.requestHeaders['origin'] ??= CLOUD_BASE_URL;
|
||||
const url = new URL(details.url);
|
||||
const pathname = url.pathname;
|
||||
// if sending request to the cloud, attach the session cookie
|
||||
if (isNetworkResource(pathname)) {
|
||||
const cookie = getCookies();
|
||||
if (cookie) {
|
||||
const cookieString = cookie.map(c => `${c.name}=${c.value}`).join('; ');
|
||||
details.requestHeaders['cookie'] = cookieString;
|
||||
}
|
||||
callback({
|
||||
cancel: false,
|
||||
requestHeaders: details.requestHeaders,
|
||||
});
|
||||
})().catch(e => {
|
||||
logger.error('failed to attach cookie', e);
|
||||
callback({
|
||||
cancel: false,
|
||||
requestHeaders: details.requestHeaders,
|
||||
});
|
||||
|
||||
// add the referer and origin headers
|
||||
details.requestHeaders['referer'] ??= CLOUD_BASE_URL;
|
||||
details.requestHeaders['origin'] ??= CLOUD_BASE_URL;
|
||||
}
|
||||
callback({
|
||||
cancel: false,
|
||||
requestHeaders: details.requestHeaders,
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@ import { join } from 'node:path';
|
||||
import {
|
||||
app,
|
||||
type CookiesSetDetails,
|
||||
session,
|
||||
type View,
|
||||
type WebContents,
|
||||
WebContentsView,
|
||||
@@ -22,7 +23,7 @@ import {
|
||||
} from 'rxjs';
|
||||
|
||||
import { isMacOS } from '../../shared/utils';
|
||||
import { isDev } from '../config';
|
||||
import { CLOUD_BASE_URL, isDev } from '../config';
|
||||
import { mainWindowOrigin, shellViewUrl } from '../constants';
|
||||
import { ensureHelperProcess } from '../helper-process';
|
||||
import { logger } from '../logger';
|
||||
@@ -185,6 +186,8 @@ export class WebContentViewsManager {
|
||||
*/
|
||||
readonly tabAction$ = new Subject<TabAction>();
|
||||
|
||||
cookies: Electron.Cookie[] = [];
|
||||
|
||||
readonly activeWorkbenchId$ = this.tabViewsMeta$.pipe(
|
||||
map(m => m?.activeWorkbenchId ?? m?.workbenches[0].id)
|
||||
);
|
||||
@@ -672,7 +675,6 @@ export class WebContentViewsManager {
|
||||
disposables.push(
|
||||
windowReadyToShow$.subscribe(w => {
|
||||
handleWebContentsResize().catch(logger.error);
|
||||
|
||||
const screenSizeChangeEvents = ['resize', 'maximize', 'unmaximize'];
|
||||
const onResize = () => {
|
||||
if (this.activeWorkbenchView) {
|
||||
@@ -689,6 +691,23 @@ export class WebContentViewsManager {
|
||||
// add shell view
|
||||
this.createAndAddView('shell').catch(logger.error);
|
||||
(async () => {
|
||||
const updateCookies = () => {
|
||||
session.defaultSession.cookies
|
||||
.get({
|
||||
url: CLOUD_BASE_URL,
|
||||
})
|
||||
.then(cookies => {
|
||||
this.cookies = cookies;
|
||||
})
|
||||
.catch(err => {
|
||||
logger.error('failed to get cookies', err);
|
||||
});
|
||||
};
|
||||
updateCookies();
|
||||
session.defaultSession.cookies.on('changed', () => {
|
||||
updateCookies();
|
||||
});
|
||||
|
||||
if (this.tabViewsMeta.workbenches.length === 0) {
|
||||
// create a default view (e.g., on first launch)
|
||||
await this.addTab();
|
||||
@@ -705,40 +724,17 @@ export class WebContentViewsManager {
|
||||
});
|
||||
};
|
||||
|
||||
setCookie = async (cookie: CookiesSetDetails) => {
|
||||
setCookie = async (cookiesSetDetails: CookiesSetDetails) => {
|
||||
const views = this.allViews;
|
||||
if (!views) {
|
||||
return;
|
||||
}
|
||||
logger.info('setting cookie to main window view(s)', cookie);
|
||||
logger.info('setting cookie to main window view(s)', cookiesSetDetails);
|
||||
for (const view of views) {
|
||||
await view.webContents.session.cookies.set(cookie);
|
||||
await view.webContents.session.cookies.set(cookiesSetDetails);
|
||||
}
|
||||
};
|
||||
|
||||
removeCookie = async (url: string, name: string) => {
|
||||
const views = this.allViews;
|
||||
if (!views) {
|
||||
return;
|
||||
}
|
||||
logger.info('removing cookie from main window view(s)', { url, name });
|
||||
for (const view of views) {
|
||||
await view.webContents.session.cookies.remove(url, name);
|
||||
}
|
||||
};
|
||||
|
||||
getCookie = (url?: string, name?: string) => {
|
||||
// all webviews share the same session
|
||||
const view = this.allViews?.at(0);
|
||||
if (!view) {
|
||||
return;
|
||||
}
|
||||
return view.webContents.session.cookies.get({
|
||||
url,
|
||||
name,
|
||||
});
|
||||
};
|
||||
|
||||
getViewById = (id: string) => {
|
||||
if (id === 'shell') {
|
||||
return this.shellView;
|
||||
@@ -865,12 +861,8 @@ export async function setCookie(
|
||||
return WebContentViewsManager.instance.setCookie(details);
|
||||
}
|
||||
|
||||
export async function removeCookie(url: string, name: string): Promise<void> {
|
||||
return WebContentViewsManager.instance.removeCookie(url, name);
|
||||
}
|
||||
|
||||
export async function getCookie(url?: string, name?: string) {
|
||||
return WebContentViewsManager.instance.getCookie(url, name);
|
||||
export function getCookies() {
|
||||
return WebContentViewsManager.instance.cookies;
|
||||
}
|
||||
|
||||
// there is no proper way to listen to webContents resize event
|
||||
|
||||
Reference in New Issue
Block a user