111 lines
3.3 KiB
TypeScript
111 lines
3.3 KiB
TypeScript
/**
|
|
* Playwright Browser IPC Handlers
|
|
* Handles browser download requests from renderer process
|
|
*/
|
|
|
|
import { app, ipcMain, IpcMainInvokeEvent } from 'electron'
|
|
import { join } from 'path'
|
|
import { IPC_CHANNELS } from '../../shared/ipc-channels'
|
|
import { withErrorHandling, type IpcResult } from './index'
|
|
import { DownloadService } from '../services/playwright-browser'
|
|
import { ConfigManager } from '../services/config/config-manager'
|
|
import { S3Client } from '@aws-sdk/client-s3'
|
|
import type { DownloadProgress } from '../services/playwright-browser'
|
|
|
|
/**
|
|
* Create S3 client from config
|
|
*/
|
|
function createS3Client(): S3Client {
|
|
const config = ConfigManager.getInstance().getConfig().update
|
|
if (!config) {
|
|
throw new Error('Update config is not available')
|
|
}
|
|
|
|
return new S3Client({
|
|
region: config.region,
|
|
endpoint: config.endpoint,
|
|
credentials: {
|
|
accessKeyId: config.accessKey,
|
|
secretAccessKey: config.secretKey
|
|
},
|
|
forcePathStyle: true
|
|
})
|
|
}
|
|
|
|
/**
|
|
* Check if Playwright browsers are installed
|
|
*/
|
|
async function checkBrowsersExist(): Promise<boolean> {
|
|
const fs = await import('fs')
|
|
const browsersPath = join(app.getPath('userData'), 'ms-playwright')
|
|
const newChromiumPath = join(browsersPath, 'chromium-1208', 'chrome-win64', 'chrome.exe')
|
|
const oldChromiumPath = join(browsersPath, 'chromium-win32', 'chrome.exe')
|
|
const chromiumPath = fs.default.existsSync(newChromiumPath) ? newChromiumPath : oldChromiumPath
|
|
|
|
if (fs.default.existsSync(chromiumPath)) {
|
|
return true
|
|
}
|
|
|
|
let foundRevision = false
|
|
try {
|
|
const entries = fs.default.readdirSync(browsersPath)
|
|
for (const entry of entries) {
|
|
if (entry.startsWith('chromium-') && !entry.includes('headless')) {
|
|
const revisionPath = join(browsersPath, entry, 'chrome-win64', 'chrome.exe')
|
|
if (fs.default.existsSync(revisionPath)) {
|
|
foundRevision = true
|
|
break
|
|
}
|
|
}
|
|
}
|
|
} catch {
|
|
// Ignore browser directory probing failures
|
|
}
|
|
|
|
return foundRevision
|
|
}
|
|
|
|
/**
|
|
* Track active download for cancellation
|
|
*/
|
|
let activeDownload: { service: DownloadService; cancelled: boolean } | null = null
|
|
|
|
export function registerPlaywrightBrowserHandlers(): void {
|
|
ipcMain.handle(IPC_CHANNELS.PLAYWRIGHT_BROWSER_CHECK, async (): Promise<IpcResult<boolean>> => {
|
|
return withErrorHandling(async () => {
|
|
return checkBrowsersExist()
|
|
}, 'playwright-browser:check')
|
|
})
|
|
|
|
ipcMain.handle(
|
|
IPC_CHANNELS.PLAYWRIGHT_BROWSER_DOWNLOAD,
|
|
async (event: IpcMainInvokeEvent): Promise<IpcResult<void>> => {
|
|
return withErrorHandling(async () => {
|
|
const s3Client = createS3Client()
|
|
const service = new DownloadService({ s3Client })
|
|
|
|
activeDownload = { service, cancelled: false }
|
|
|
|
await service.downloadAll((progress: DownloadProgress) => {
|
|
if (activeDownload?.cancelled) {
|
|
throw new Error('Download cancelled by user')
|
|
}
|
|
|
|
event.sender.send(IPC_CHANNELS.PLAYWRIGHT_BROWSER_PROGRESS, progress)
|
|
})
|
|
|
|
activeDownload = null
|
|
}, 'playwright-browser:download')
|
|
}
|
|
)
|
|
|
|
ipcMain.handle(IPC_CHANNELS.PLAYWRIGHT_BROWSER_CANCEL, async (): Promise<IpcResult<void>> => {
|
|
return withErrorHandling(async () => {
|
|
if (activeDownload) {
|
|
activeDownload.cancelled = true
|
|
activeDownload = null
|
|
}
|
|
}, 'playwright-browser:cancel')
|
|
})
|
|
}
|