feat: bump electron (#14151)
This commit is contained in:
2
.github/workflows/build-test.yml
vendored
2
.github/workflows/build-test.yml
vendored
@@ -1351,7 +1351,7 @@ jobs:
|
|||||||
run: |
|
run: |
|
||||||
sudo add-apt-repository universe
|
sudo add-apt-repository universe
|
||||||
sudo apt install -y libfuse2 elfutils flatpak flatpak-builder
|
sudo apt install -y libfuse2 elfutils flatpak flatpak-builder
|
||||||
flatpak remote-add --user --if-not-exists flathub https://flathub.org/repo/flathub.flatpakrepo
|
flatpak remote-add --user --if-not-exists flathub https://dl.flathub.org/repo/flathub.flatpakrepo
|
||||||
flatpak update
|
flatpak update
|
||||||
# some flatpak deps need git protocol.file.allow
|
# some flatpak deps need git protocol.file.allow
|
||||||
git config --global protocol.file.allow always
|
git config --global protocol.file.allow always
|
||||||
|
|||||||
14
.github/workflows/release-desktop.yml
vendored
14
.github/workflows/release-desktop.yml
vendored
@@ -103,11 +103,13 @@ jobs:
|
|||||||
hard-link-nm: false
|
hard-link-nm: false
|
||||||
nmHoistingLimits: workspaces
|
nmHoistingLimits: workspaces
|
||||||
enableScripts: false
|
enableScripts: false
|
||||||
|
|
||||||
- name: Build AFFiNE native
|
- name: Build AFFiNE native
|
||||||
uses: ./.github/actions/build-rust
|
uses: ./.github/actions/build-rust
|
||||||
with:
|
with:
|
||||||
target: ${{ matrix.spec.target }}
|
target: ${{ matrix.spec.target }}
|
||||||
package: '@affine/native'
|
package: '@affine/native'
|
||||||
|
|
||||||
- uses: actions/download-artifact@v4
|
- uses: actions/download-artifact@v4
|
||||||
with:
|
with:
|
||||||
name: desktop-web
|
name: desktop-web
|
||||||
@@ -128,7 +130,7 @@ jobs:
|
|||||||
run: |
|
run: |
|
||||||
sudo add-apt-repository universe
|
sudo add-apt-repository universe
|
||||||
sudo apt install -y libfuse2 elfutils flatpak flatpak-builder
|
sudo apt install -y libfuse2 elfutils flatpak flatpak-builder
|
||||||
flatpak remote-add --user --if-not-exists flathub https://flathub.org/repo/flathub.flatpakrepo
|
flatpak remote-add --user --if-not-exists flathub https://dl.flathub.org/repo/flathub.flatpakrepo
|
||||||
flatpak update
|
flatpak update
|
||||||
# some flatpak deps need git protocol.file.allow
|
# some flatpak deps need git protocol.file.allow
|
||||||
git config --global protocol.file.allow always
|
git config --global protocol.file.allow always
|
||||||
@@ -165,7 +167,7 @@ jobs:
|
|||||||
mv packages/frontend/apps/electron/out/*/make/zip/linux/${{ matrix.spec.arch }}/*.zip ./builds/affine-${{ env.RELEASE_VERSION }}-${{ env.BUILD_TYPE }}-linux-${{ matrix.spec.arch }}.zip
|
mv packages/frontend/apps/electron/out/*/make/zip/linux/${{ matrix.spec.arch }}/*.zip ./builds/affine-${{ env.RELEASE_VERSION }}-${{ env.BUILD_TYPE }}-linux-${{ matrix.spec.arch }}.zip
|
||||||
mv packages/frontend/apps/electron/out/*/make/*.AppImage ./builds/affine-${{ env.RELEASE_VERSION }}-${{ env.BUILD_TYPE }}-linux-${{ matrix.spec.arch }}.appimage
|
mv packages/frontend/apps/electron/out/*/make/*.AppImage ./builds/affine-${{ env.RELEASE_VERSION }}-${{ env.BUILD_TYPE }}-linux-${{ matrix.spec.arch }}.appimage
|
||||||
mv packages/frontend/apps/electron/out/*/make/deb/${{ matrix.spec.arch }}/*.deb ./builds/affine-${{ env.RELEASE_VERSION }}-${{ env.BUILD_TYPE }}-linux-${{ matrix.spec.arch }}.deb
|
mv packages/frontend/apps/electron/out/*/make/deb/${{ matrix.spec.arch }}/*.deb ./builds/affine-${{ env.RELEASE_VERSION }}-${{ env.BUILD_TYPE }}-linux-${{ matrix.spec.arch }}.deb
|
||||||
# mv packages/frontend/apps/electron/out/*/make/flatpak/*/*.flatpak ./builds/affine-${{ env.RELEASE_VERSION }}-${{ env.BUILD_TYPE }}-linux-${{ matrix.spec.arch }}.flatpak
|
mv packages/frontend/apps/electron/out/*/make/flatpak/*/*.flatpak ./builds/affine-${{ env.RELEASE_VERSION }}-${{ env.BUILD_TYPE }}-linux-${{ matrix.spec.arch }}.flatpak
|
||||||
|
|
||||||
- uses: actions/attest-build-provenance@v2
|
- uses: actions/attest-build-provenance@v2
|
||||||
if: ${{ matrix.spec.platform == 'darwin' }}
|
if: ${{ matrix.spec.platform == 'darwin' }}
|
||||||
@@ -181,6 +183,8 @@ jobs:
|
|||||||
./builds/affine-${{ env.RELEASE_VERSION }}-${{ env.BUILD_TYPE }}-linux-x64.zip
|
./builds/affine-${{ env.RELEASE_VERSION }}-${{ env.BUILD_TYPE }}-linux-x64.zip
|
||||||
./builds/affine-${{ env.RELEASE_VERSION }}-${{ env.BUILD_TYPE }}-linux-x64.appimage
|
./builds/affine-${{ env.RELEASE_VERSION }}-${{ env.BUILD_TYPE }}-linux-x64.appimage
|
||||||
./builds/affine-${{ env.RELEASE_VERSION }}-${{ env.BUILD_TYPE }}-linux-x64.deb
|
./builds/affine-${{ env.RELEASE_VERSION }}-${{ env.BUILD_TYPE }}-linux-x64.deb
|
||||||
|
./builds/affine-${{ env.RELEASE_VERSION }}-${{ env.BUILD_TYPE }}-linux-x64.flatpak
|
||||||
|
|
||||||
- name: Upload Artifact
|
- name: Upload Artifact
|
||||||
uses: actions/upload-artifact@v4
|
uses: actions/upload-artifact@v4
|
||||||
with:
|
with:
|
||||||
@@ -415,12 +419,6 @@ jobs:
|
|||||||
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
- uses: actions/download-artifact@v4
|
|
||||||
with:
|
|
||||||
name: desktop-web
|
|
||||||
path: web-static
|
|
||||||
- name: Zip web-static
|
|
||||||
run: zip -r web-static.zip web-static
|
|
||||||
- name: Download Artifacts (macos-x64)
|
- name: Download Artifacts (macos-x64)
|
||||||
uses: actions/download-artifact@v4
|
uses: actions/download-artifact@v4
|
||||||
with:
|
with:
|
||||||
|
|||||||
@@ -68,7 +68,7 @@
|
|||||||
"@vitest/coverage-istanbul": "^3.2.4",
|
"@vitest/coverage-istanbul": "^3.2.4",
|
||||||
"@vitest/ui": "^3.2.4",
|
"@vitest/ui": "^3.2.4",
|
||||||
"cross-env": "^10.1.0",
|
"cross-env": "^10.1.0",
|
||||||
"electron": "^35.0.0",
|
"electron": "^36.0.0",
|
||||||
"eslint": "^9.16.0",
|
"eslint": "^9.16.0",
|
||||||
"eslint-config-prettier": "^10.0.0",
|
"eslint-config-prettier": "^10.0.0",
|
||||||
"eslint-import-resolver-typescript": "^4.0.0",
|
"eslint-import-resolver-typescript": "^4.0.0",
|
||||||
|
|||||||
@@ -14,11 +14,34 @@ import { getCurrentWorkspace, isAiEnabled } from './utils';
|
|||||||
|
|
||||||
const logger = new DebugLogger('electron-renderer:recording');
|
const logger = new DebugLogger('electron-renderer:recording');
|
||||||
|
|
||||||
|
async function readRecordingFile(filepath: string) {
|
||||||
|
if (apis?.recording?.readRecordingFile) {
|
||||||
|
try {
|
||||||
|
return await apis.recording.readRecordingFile(filepath);
|
||||||
|
} catch (error) {
|
||||||
|
logger.error(
|
||||||
|
'Failed to read recording file via IPC, fallback to fetch',
|
||||||
|
error
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const fileUrl = new URL(
|
||||||
|
filepath,
|
||||||
|
location.origin.replace(/\.$/, 'local-file')
|
||||||
|
);
|
||||||
|
const response = await fetch(fileUrl);
|
||||||
|
if (!response.ok) {
|
||||||
|
throw new Error(
|
||||||
|
`Failed to fetch recording file: ${response.status} ${response.statusText}`
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return response.arrayBuffer();
|
||||||
|
}
|
||||||
|
|
||||||
async function saveRecordingBlob(blobEngine: BlobEngine, filepath: string) {
|
async function saveRecordingBlob(blobEngine: BlobEngine, filepath: string) {
|
||||||
logger.debug('Saving recording', filepath);
|
logger.debug('Saving recording', filepath);
|
||||||
const opusBuffer = await fetch(new URL(filepath, location.origin)).then(res =>
|
const opusBuffer = await readRecordingFile(filepath);
|
||||||
res.arrayBuffer()
|
|
||||||
);
|
|
||||||
const blob = new Blob([opusBuffer], {
|
const blob = new Blob([opusBuffer], {
|
||||||
type: 'audio/mp4',
|
type: 'audio/mp4',
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -111,57 +111,60 @@ const makers = [
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
!process.env.SKIP_BUNDLE &&
|
!process.env.SKIP_BUNDLE && {
|
||||||
false && {
|
name: '@electron-forge/maker-flatpak',
|
||||||
name: '@electron-forge/maker-flatpak',
|
platforms: ['linux'],
|
||||||
platforms: ['linux'],
|
/** @type {import('@electron-forge/maker-flatpak').MakerFlatpakConfig} */
|
||||||
/** @type {import('@electron-forge/maker-flatpak').MakerFlatpakConfig} */
|
config: {
|
||||||
config: {
|
options: {
|
||||||
options: {
|
mimeType: linuxMimeTypes,
|
||||||
mimeType: linuxMimeTypes,
|
productName,
|
||||||
productName,
|
bin: productName,
|
||||||
bin: productName,
|
id: appIdMap[buildType],
|
||||||
id: fromBuildIdentifier(appIdMap),
|
icon: iconPngPath, // not working yet
|
||||||
icon: iconPngPath, // not working yet
|
branch: buildType,
|
||||||
branch: buildType,
|
runtime: 'org.freedesktop.Platform',
|
||||||
files: [
|
runtimeVersion: '25.08',
|
||||||
[
|
sdk: 'org.freedesktop.Sdk',
|
||||||
'./resources/affine.metainfo.xml',
|
base: 'org.electronjs.Electron2.BaseApp',
|
||||||
'/usr/share/metainfo/affine.metainfo.xml',
|
baseVersion: '25.08',
|
||||||
|
files: [
|
||||||
|
[
|
||||||
|
'./resources/affine.metainfo.xml',
|
||||||
|
'/usr/share/metainfo/affine.metainfo.xml',
|
||||||
|
],
|
||||||
|
],
|
||||||
|
modules: [
|
||||||
|
{
|
||||||
|
name: 'zypak',
|
||||||
|
sources: [
|
||||||
|
{
|
||||||
|
type: 'git',
|
||||||
|
url: 'https://github.com/refi64/zypak',
|
||||||
|
tag: 'v2025.09',
|
||||||
|
},
|
||||||
],
|
],
|
||||||
],
|
},
|
||||||
runtimeVersion: '25.08',
|
],
|
||||||
modules: [
|
finishArgs: [
|
||||||
{
|
// Wayland/X11 Rendering
|
||||||
name: 'zypak',
|
'--socket=wayland',
|
||||||
sources: [
|
'--socket=x11',
|
||||||
{
|
'--share=ipc',
|
||||||
type: 'git',
|
// Open GL
|
||||||
url: 'https://github.com/refi64/zypak',
|
'--device=dri',
|
||||||
tag: 'v2025.09',
|
// Audio output
|
||||||
},
|
'--socket=pulseaudio',
|
||||||
],
|
// Read/write home directory access
|
||||||
},
|
'--filesystem=home',
|
||||||
],
|
// Allow communication with network
|
||||||
finishArgs: [
|
'--share=network',
|
||||||
// Wayland/X11 Rendering
|
// System notifications with libnotify
|
||||||
'--socket=wayland',
|
'--talk-name=org.freedesktop.Notifications',
|
||||||
'--socket=x11',
|
],
|
||||||
'--share=ipc',
|
|
||||||
// Open GL
|
|
||||||
'--device=dri',
|
|
||||||
// Audio output
|
|
||||||
'--socket=pulseaudio',
|
|
||||||
// Read/write home directory access
|
|
||||||
'--filesystem=home',
|
|
||||||
// Allow communication with network
|
|
||||||
'--share=network',
|
|
||||||
// System notifications with libnotify
|
|
||||||
'--talk-name=org.freedesktop.Notifications',
|
|
||||||
],
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
},
|
||||||
].filter(Boolean);
|
].filter(Boolean);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -198,6 +201,7 @@ export default {
|
|||||||
},
|
},
|
||||||
],
|
],
|
||||||
executableName: productName,
|
executableName: productName,
|
||||||
|
ignore: [/\.map$/],
|
||||||
asar: true,
|
asar: true,
|
||||||
extendInfo: {
|
extendInfo: {
|
||||||
NSAudioCaptureUsageDescription:
|
NSAudioCaptureUsageDescription:
|
||||||
|
|||||||
@@ -59,7 +59,7 @@
|
|||||||
"builder-util-runtime": "^9.5.0",
|
"builder-util-runtime": "^9.5.0",
|
||||||
"cross-env": "^10.1.0",
|
"cross-env": "^10.1.0",
|
||||||
"debug": "^4.4.0",
|
"debug": "^4.4.0",
|
||||||
"electron": "^35.0.0",
|
"electron": "^36.0.0",
|
||||||
"electron-log": "^5.4.3",
|
"electron-log": "^5.4.3",
|
||||||
"electron-squirrel-startup": "1.0.1",
|
"electron-squirrel-startup": "1.0.1",
|
||||||
"electron-window-state": "^5.0.3",
|
"electron-window-state": "^5.0.3",
|
||||||
|
|||||||
@@ -63,6 +63,8 @@ const {
|
|||||||
default: process.platform,
|
default: process.platform,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
allowPositionals: true,
|
||||||
|
strict: false,
|
||||||
});
|
});
|
||||||
|
|
||||||
log(`parsed args: arch=${arch}, platform=${platform}`);
|
log(`parsed args: arch=${arch}, platform=${platform}`);
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
export const mainHost = '.';
|
export const mainHost = '.';
|
||||||
export const anotherHost = 'another-host';
|
export const anotherHost = 'another-host';
|
||||||
|
|
||||||
export const mainWindowOrigin = `file://${mainHost}`;
|
export const mainWindowOrigin = `assets://${mainHost}`;
|
||||||
export const anotherOrigin = `file://${anotherHost}`;
|
export const anotherOrigin = `assets://${anotherHost}`;
|
||||||
|
|
||||||
export const onboardingViewUrl = `${mainWindowOrigin}/onboarding`;
|
export const onboardingViewUrl = `${mainWindowOrigin}/onboarding`;
|
||||||
export const shellViewUrl = `${mainWindowOrigin}/shell.html`;
|
export const shellViewUrl = `${mainWindowOrigin}/shell.html`;
|
||||||
|
|||||||
@@ -12,16 +12,15 @@ protocol.registerSchemesAsPrivileged([
|
|||||||
{
|
{
|
||||||
scheme: 'assets',
|
scheme: 'assets',
|
||||||
privileges: {
|
privileges: {
|
||||||
secure: false,
|
secure: true,
|
||||||
|
allowServiceWorkers: true,
|
||||||
corsEnabled: true,
|
corsEnabled: true,
|
||||||
supportFetchAPI: true,
|
supportFetchAPI: true,
|
||||||
standard: true,
|
standard: true,
|
||||||
bypassCSP: true,
|
bypassCSP: true,
|
||||||
|
stream: true,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
]);
|
|
||||||
|
|
||||||
protocol.registerSchemesAsPrivileged([
|
|
||||||
{
|
{
|
||||||
scheme: 'file',
|
scheme: 'file',
|
||||||
privileges: {
|
privileges: {
|
||||||
@@ -36,6 +35,17 @@ protocol.registerSchemesAsPrivileged([
|
|||||||
]);
|
]);
|
||||||
|
|
||||||
const webStaticDir = join(resourcesPath, 'web-static');
|
const webStaticDir = join(resourcesPath, 'web-static');
|
||||||
|
const localWhiteListDirs = [
|
||||||
|
path.resolve(app.getPath('sessionData')).toLowerCase(),
|
||||||
|
path.resolve(app.getPath('temp')).toLowerCase(),
|
||||||
|
];
|
||||||
|
|
||||||
|
function isPathInWhiteList(filepath: string) {
|
||||||
|
const lowerFilePath = filepath.toLowerCase();
|
||||||
|
return localWhiteListDirs.some(whitelistDir =>
|
||||||
|
lowerFilePath.startsWith(whitelistDir)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
async function handleFileRequest(request: Request) {
|
async function handleFileRequest(request: Request) {
|
||||||
const urlObject = new URL(request.url);
|
const urlObject = new URL(request.url);
|
||||||
@@ -45,11 +55,14 @@ async function handleFileRequest(request: Request) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const isAbsolutePath = urlObject.host !== '.';
|
const isAbsolutePath = urlObject.host !== '.';
|
||||||
|
const isFontRequest =
|
||||||
|
urlObject.pathname &&
|
||||||
|
/\.(woff2?|ttf|otf)$/i.test(urlObject.pathname.split('?')[0] ?? '');
|
||||||
|
|
||||||
// Redirect to webpack dev server if defined
|
// Redirect to webpack dev server if defined
|
||||||
if (process.env.DEV_SERVER_URL && !isAbsolutePath) {
|
if (process.env.DEV_SERVER_URL && !isAbsolutePath && !isFontRequest) {
|
||||||
const devServerUrl = new URL(
|
const devServerUrl = new URL(
|
||||||
urlObject.pathname,
|
`${urlObject.pathname}${urlObject.search}`,
|
||||||
process.env.DEV_SERVER_URL
|
process.env.DEV_SERVER_URL
|
||||||
);
|
);
|
||||||
return net.fetch(devServerUrl.toString(), request);
|
return net.fetch(devServerUrl.toString(), request);
|
||||||
@@ -83,14 +96,7 @@ async function handleFileRequest(request: Request) {
|
|||||||
filepath = path.resolve(filepath.replace(/^\//, ''));
|
filepath = path.resolve(filepath.replace(/^\//, ''));
|
||||||
}
|
}
|
||||||
// security check if the filepath is within app.getPath('sessionData')
|
// security check if the filepath is within app.getPath('sessionData')
|
||||||
const sessionDataPath = path
|
if (urlObject.host !== 'local-file' || !isPathInWhiteList(filepath)) {
|
||||||
.resolve(app.getPath('sessionData'))
|
|
||||||
.toLowerCase();
|
|
||||||
const tempPath = path.resolve(app.getPath('temp')).toLowerCase();
|
|
||||||
if (
|
|
||||||
!filepath.toLowerCase().startsWith(sessionDataPath) &&
|
|
||||||
!filepath.toLowerCase().startsWith(tempPath)
|
|
||||||
) {
|
|
||||||
throw new Error('Invalid filepath');
|
throw new Error('Invalid filepath');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -102,7 +108,20 @@ async function handleFileRequest(request: Request) {
|
|||||||
const corsWhitelist = [
|
const corsWhitelist = [
|
||||||
/^(?:[a-zA-Z0-9-]+\.)*googlevideo\.com$/,
|
/^(?:[a-zA-Z0-9-]+\.)*googlevideo\.com$/,
|
||||||
/^(?:[a-zA-Z0-9-]+\.)*youtube\.com$/,
|
/^(?:[a-zA-Z0-9-]+\.)*youtube\.com$/,
|
||||||
|
/^(?:[a-zA-Z0-9-]+\.)*youtube-nocookie\.com$/,
|
||||||
|
/^(?:[a-zA-Z0-9-]+\.)*gstatic\.com$/,
|
||||||
|
/^(?:[a-zA-Z0-9-]+\.)*googleapis\.com$/,
|
||||||
|
/^localhost(?::\d+)?$/,
|
||||||
|
/^127\.0\.0\.1(?::\d+)?$/,
|
||||||
|
/^insider\.affine\.pro$/,
|
||||||
|
/^app\.affine\.pro$/,
|
||||||
];
|
];
|
||||||
|
const needRefererDomains = [
|
||||||
|
/^(?:[a-zA-Z0-9-]+\.)*youtube\.com$/,
|
||||||
|
/^(?:[a-zA-Z0-9-]+\.)*youtube-nocookie\.com$/,
|
||||||
|
/^(?:[a-zA-Z0-9-]+\.)*googlevideo\.com$/,
|
||||||
|
];
|
||||||
|
const defaultReferer = 'https://client.affine.local/';
|
||||||
|
|
||||||
export function registerProtocol() {
|
export function registerProtocol() {
|
||||||
protocol.handle('file', request => {
|
protocol.handle('file', request => {
|
||||||
@@ -159,6 +178,31 @@ export function registerProtocol() {
|
|||||||
delete responseHeaders['access-control-allow-headers'];
|
delete responseHeaders['access-control-allow-headers'];
|
||||||
delete responseHeaders['Access-Control-Allow-Origin'];
|
delete responseHeaders['Access-Control-Allow-Origin'];
|
||||||
delete responseHeaders['Access-Control-Allow-Headers'];
|
delete responseHeaders['Access-Control-Allow-Headers'];
|
||||||
|
} else if (
|
||||||
|
!needRefererDomains.some(domainRegex => domainRegex.test(hostname))
|
||||||
|
) {
|
||||||
|
if (
|
||||||
|
!responseHeaders['access-control-allow-origin'] &&
|
||||||
|
!responseHeaders['Access-Control-Allow-Origin']
|
||||||
|
) {
|
||||||
|
responseHeaders['Access-Control-Allow-Origin'] = ['*'];
|
||||||
|
}
|
||||||
|
if (
|
||||||
|
!responseHeaders['access-control-allow-headers'] &&
|
||||||
|
!responseHeaders['Access-Control-Allow-Headers']
|
||||||
|
) {
|
||||||
|
responseHeaders['Access-Control-Allow-Headers'] = [
|
||||||
|
'Origin, X-Requested-With, Content-Type, Accept, Authorization',
|
||||||
|
];
|
||||||
|
}
|
||||||
|
if (
|
||||||
|
!responseHeaders['access-control-allow-methods'] &&
|
||||||
|
!responseHeaders['Access-Control-Allow-Methods']
|
||||||
|
) {
|
||||||
|
responseHeaders['Access-Control-Allow-Methods'] = [
|
||||||
|
'GET,HEAD,PUT,PATCH,POST,DELETE,OPTIONS',
|
||||||
|
];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// to allow url embedding, remove "x-frame-options",
|
// to allow url embedding, remove "x-frame-options",
|
||||||
@@ -217,7 +261,7 @@ export function registerProtocol() {
|
|||||||
const url = new URL(details.url);
|
const url = new URL(details.url);
|
||||||
|
|
||||||
(async () => {
|
(async () => {
|
||||||
// session cookies are set to file:// on production
|
// session cookies are set to assets:// on production
|
||||||
// if sending request to the cloud, attach the session cookie (to affine cloud server)
|
// if sending request to the cloud, attach the session cookie (to affine cloud server)
|
||||||
if (
|
if (
|
||||||
url.protocol === 'http:' ||
|
url.protocol === 'http:' ||
|
||||||
@@ -235,6 +279,14 @@ export function registerProtocol() {
|
|||||||
delete details.requestHeaders['cookie'];
|
delete details.requestHeaders['cookie'];
|
||||||
details.requestHeaders['Cookie'] = cookieString;
|
details.requestHeaders['Cookie'] = cookieString;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const hostname = url.hostname;
|
||||||
|
const needReferer = needRefererDomains.some(regex =>
|
||||||
|
regex.test(hostname)
|
||||||
|
);
|
||||||
|
if (needReferer && !details.requestHeaders['Referer']) {
|
||||||
|
details.requestHeaders['Referer'] = defaultReferer;
|
||||||
|
}
|
||||||
})()
|
})()
|
||||||
.catch(err => {
|
.catch(err => {
|
||||||
logger.error('error handling before send headers', err);
|
logger.error('error handling before send headers', err);
|
||||||
|
|||||||
@@ -686,6 +686,22 @@ export async function getRawAudioBuffers(
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function assertRecordingFilepath(filepath: string) {
|
||||||
|
const normalizedPath = path.normalize(filepath);
|
||||||
|
const normalizedBase = path.normalize(SAVED_RECORDINGS_DIR + path.sep);
|
||||||
|
|
||||||
|
if (!normalizedPath.toLowerCase().startsWith(normalizedBase.toLowerCase())) {
|
||||||
|
throw new Error('Invalid recording filepath');
|
||||||
|
}
|
||||||
|
|
||||||
|
return normalizedPath;
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function readRecordingFile(filepath: string) {
|
||||||
|
const normalizedPath = assertRecordingFilepath(filepath);
|
||||||
|
return fsp.readFile(normalizedPath);
|
||||||
|
}
|
||||||
|
|
||||||
export async function readyRecording(id: number, buffer: Buffer) {
|
export async function readyRecording(id: number, buffer: Buffer) {
|
||||||
logger.info('readyRecording', id);
|
logger.info('readyRecording', id);
|
||||||
|
|
||||||
|
|||||||
@@ -19,6 +19,7 @@ import {
|
|||||||
handleBlockCreationFailed,
|
handleBlockCreationFailed,
|
||||||
handleBlockCreationSuccess,
|
handleBlockCreationSuccess,
|
||||||
pauseRecording,
|
pauseRecording,
|
||||||
|
readRecordingFile,
|
||||||
readyRecording,
|
readyRecording,
|
||||||
recordingStatus$,
|
recordingStatus$,
|
||||||
removeRecording,
|
removeRecording,
|
||||||
@@ -53,6 +54,9 @@ export const recordingHandlers = {
|
|||||||
getRawAudioBuffers: async (_, id: number, cursor?: number) => {
|
getRawAudioBuffers: async (_, id: number, cursor?: number) => {
|
||||||
return getRawAudioBuffers(id, cursor);
|
return getRawAudioBuffers(id, cursor);
|
||||||
},
|
},
|
||||||
|
readRecordingFile: async (_, filepath: string) => {
|
||||||
|
return readRecordingFile(filepath);
|
||||||
|
},
|
||||||
// save the encoded recording buffer to the file system
|
// save the encoded recording buffer to the file system
|
||||||
readyRecording: async (_, id: number, buffer: Uint8Array) => {
|
readyRecording: async (_, id: number, buffer: Uint8Array) => {
|
||||||
return readyRecording(id, Buffer.from(buffer));
|
return readyRecording(id, Buffer.from(buffer));
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import { app } from 'electron';
|
import { app } from 'electron';
|
||||||
|
|
||||||
|
import { anotherHost, mainHost } from './constants';
|
||||||
import { openExternalSafely } from './security/open-external';
|
import { openExternalSafely } from './security/open-external';
|
||||||
|
|
||||||
const extractRedirectTarget = (rawUrl: string) => {
|
const extractRedirectTarget = (rawUrl: string) => {
|
||||||
@@ -33,7 +34,20 @@ const extractRedirectTarget = (rawUrl: string) => {
|
|||||||
|
|
||||||
app.on('web-contents-created', (_, contents) => {
|
app.on('web-contents-created', (_, contents) => {
|
||||||
const isInternalUrl = (url: string) => {
|
const isInternalUrl = (url: string) => {
|
||||||
return url.startsWith('file://.');
|
try {
|
||||||
|
const parsed = new URL(url);
|
||||||
|
if (
|
||||||
|
parsed.protocol === 'assets:' &&
|
||||||
|
(parsed.hostname === mainHost || parsed.hostname === anotherHost)
|
||||||
|
) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (parsed.protocol === 'file:' && parsed.hostname === mainHost) {
|
||||||
|
// legacy allowance for older file:// loads
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
} catch {}
|
||||||
|
return false;
|
||||||
};
|
};
|
||||||
/**
|
/**
|
||||||
* Block navigation to origins not on the allowlist.
|
* Block navigation to origins not on the allowlist.
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import queryString from 'query-string';
|
|||||||
function maybeAffineOrigin(origin: string, baseUrl: string) {
|
function maybeAffineOrigin(origin: string, baseUrl: string) {
|
||||||
return (
|
return (
|
||||||
origin.startsWith('file://') ||
|
origin.startsWith('file://') ||
|
||||||
|
origin.startsWith('assets://') ||
|
||||||
origin.endsWith('affine.pro') || // stable/beta
|
origin.endsWith('affine.pro') || // stable/beta
|
||||||
origin.endsWith('apple.getaffineapp.com') || // stable/beta
|
origin.endsWith('apple.getaffineapp.com') || // stable/beta
|
||||||
origin.endsWith('affine.fail') || // canary
|
origin.endsWith('affine.fail') || // canary
|
||||||
|
|||||||
@@ -115,7 +115,9 @@ const defaultDevServerConfig: DevServerConfiguration = {
|
|||||||
overlay: process.env.DISABLE_DEV_OVERLAY === 'true' ? false : undefined,
|
overlay: process.env.DISABLE_DEV_OVERLAY === 'true' ? false : undefined,
|
||||||
logging: process.env.CI ? 'none' : 'error',
|
logging: process.env.CI ? 'none' : 'error',
|
||||||
// see: https://webpack.js.org/configuration/dev-server/#websocketurl
|
// see: https://webpack.js.org/configuration/dev-server/#websocketurl
|
||||||
webSocketURL: 'auto://0.0.0.0:8080/ws',
|
// must be an explicit ws/wss URL because custom protocols (e.g. assets://)
|
||||||
|
// cannot be used to construct WebSocket endpoints in Electron
|
||||||
|
webSocketURL: 'ws://0.0.0.0:8080/ws',
|
||||||
},
|
},
|
||||||
historyApiFallback: {
|
historyApiFallback: {
|
||||||
rewrites: [
|
rewrites: [
|
||||||
|
|||||||
12
yarn.lock
12
yarn.lock
@@ -583,7 +583,7 @@ __metadata:
|
|||||||
builder-util-runtime: "npm:^9.5.0"
|
builder-util-runtime: "npm:^9.5.0"
|
||||||
cross-env: "npm:^10.1.0"
|
cross-env: "npm:^10.1.0"
|
||||||
debug: "npm:^4.4.0"
|
debug: "npm:^4.4.0"
|
||||||
electron: "npm:^35.0.0"
|
electron: "npm:^36.0.0"
|
||||||
electron-log: "npm:^5.4.3"
|
electron-log: "npm:^5.4.3"
|
||||||
electron-squirrel-startup: "npm:1.0.1"
|
electron-squirrel-startup: "npm:1.0.1"
|
||||||
electron-updater: "npm:^6.6.2"
|
electron-updater: "npm:^6.6.2"
|
||||||
@@ -786,7 +786,7 @@ __metadata:
|
|||||||
"@vitest/coverage-istanbul": "npm:^3.2.4"
|
"@vitest/coverage-istanbul": "npm:^3.2.4"
|
||||||
"@vitest/ui": "npm:^3.2.4"
|
"@vitest/ui": "npm:^3.2.4"
|
||||||
cross-env: "npm:^10.1.0"
|
cross-env: "npm:^10.1.0"
|
||||||
electron: "npm:^35.0.0"
|
electron: "npm:^36.0.0"
|
||||||
eslint: "npm:^9.16.0"
|
eslint: "npm:^9.16.0"
|
||||||
eslint-config-prettier: "npm:^10.0.0"
|
eslint-config-prettier: "npm:^10.0.0"
|
||||||
eslint-import-resolver-typescript: "npm:^4.0.0"
|
eslint-import-resolver-typescript: "npm:^4.0.0"
|
||||||
@@ -22392,16 +22392,16 @@ __metadata:
|
|||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
"electron@npm:^35.0.0":
|
"electron@npm:^36.0.0":
|
||||||
version: 35.7.5
|
version: 36.9.5
|
||||||
resolution: "electron@npm:35.7.5"
|
resolution: "electron@npm:36.9.5"
|
||||||
dependencies:
|
dependencies:
|
||||||
"@electron/get": "npm:^2.0.0"
|
"@electron/get": "npm:^2.0.0"
|
||||||
"@types/node": "npm:^22.7.7"
|
"@types/node": "npm:^22.7.7"
|
||||||
extract-zip: "npm:^2.0.1"
|
extract-zip: "npm:^2.0.1"
|
||||||
bin:
|
bin:
|
||||||
electron: cli.js
|
electron: cli.js
|
||||||
checksum: 10/f3757f0b6f21ddd5ebf8b83becdaa3e47dc13473e5375e6e6aee638d7029e73d08d6a4170b37ad8c594057da139e7cdf4c8b82b70c2c1ad0306abdcc274c5fee
|
checksum: 10/2c78ce37b6cdcf2388dc3f3932f2104f7bd529c51ee8d00e0201ce86089966309c0ba62c2045abc4dad81893ebe7f7070bb047dcb9c05366f31ddd7fb73790ca
|
||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user