From fd1f8ce27b6e6051356dc7ef4c13561c701a38ed Mon Sep 17 00:00:00 2001 From: SimonLaux Date: Wed, 6 Sep 2023 19:14:48 +0200 Subject: [PATCH] migrate now deprecated apis --- src/main/deltachat/webxdc.ts | 198 +++++++++++++++------------------ src/main/open_url.ts | 2 +- src/main/windows/html_email.ts | 40 +++---- 3 files changed, 111 insertions(+), 129 deletions(-) diff --git a/src/main/deltachat/webxdc.ts b/src/main/deltachat/webxdc.ts index dd264d9251..9d4a15e4c5 100644 --- a/src/main/deltachat/webxdc.ts +++ b/src/main/deltachat/webxdc.ts @@ -6,12 +6,11 @@ const log = getLogger('main/deltachat/webxdc') import Mime from 'mime-types' import { Menu, - ProtocolResponse, nativeImage, shell, MenuItemConstructorOptions, - clipboard, dialog, + clipboard, } from 'electron' import { join } from 'path' import { readdir, stat, rmdir, writeFile, readFile } from 'fs/promises' @@ -60,27 +59,23 @@ export default class DCWebxdc extends SplitOut { // icon protocol app.whenReady().then(() => { - protocol.registerBufferProtocol( - 'webxdc-icon', - async (request, callback) => { - const [a, m] = request.url.substr(12).split('.') - const [accountId, messageId] = [Number(a), Number(m)] - try { - const { icon } = await this.rpc.getWebxdcInfo(accountId, messageId) - const blob = Buffer.from( - await this.rpc.getWebxdcBlob(accountId, messageId, icon), - 'base64' - ) - callback({ - mimeType: Mime.lookup(icon) || '', - data: blob, - }) - } catch (error) { - log.error('failed to load webxdc icon for:', error) - callback({ statusCode: 404 }) - } + protocol.handle('webxdc-icon', async request => { + const [a, m] = request.url.substr(12).split('.') + const [accountId, messageId] = [Number(a), Number(m)] + try { + const { icon } = await this.rpc.getWebxdcInfo(accountId, messageId) + const blob = Buffer.from( + await this.rpc.getWebxdcBlob(accountId, messageId, icon), + 'base64' + ) + return new Response(blob, { + headers: { 'content-type': Mime.lookup(icon) || '' }, + }) + } catch (error) { + log.error('failed to load webxdc icon for:', error) + return new Response('', { status: 404 }) } - ) + }) }) // actual webxdc instances @@ -116,101 +111,92 @@ export default class DCWebxdc extends SplitOut { if (!accounts_sessions.includes(accountId)) { accounts_sessions.push(accountId) - ses.protocol.registerBufferProtocol( - 'webxdc', - async (request, callback) => { - const respond = (response: Omit) => { - const headers: ProtocolResponse['headers'] = { - 'Content-Security-Policy': CSP, - // Ensure that the client doesn't try to interpret a file as - // one with 'application/pdf' mime type and therefore open it - // in the PDF viewer. - 'X-Content-Type-Options': 'nosniff', - } - ;(response as ProtocolResponse).headers = headers - - if (open_apps[id].internet_access) { - delete headers['Content-Security-Policy'] - } - - callback(response) + ses.protocol.handle('webxdc', async request => { + const get_headers = (mime_type: string | undefined) => { + const headers = new Headers() + if (!open_apps[id].internet_access) { + headers.append('Content-Security-Policy', CSP) } - const url = UrlParser(request.url) - const [account, msg] = url.hostname.split('.') - const id = `${account}.${msg}` - - if (!open_apps[id]) { - return + headers.append('X-Content-Type-Options', 'nosniff') + if (mime_type) { + headers.append('content-type', mime_type) } + return headers + } - let filename = url.pathname - // remove leading / trailing "/" - if (filename.endsWith('/')) { - filename = filename.substr(0, filename.length - 1) - } - if (filename.startsWith('/')) { - filename = filename.substr(1) - } + const url = UrlParser(request.url) + const [account, msg] = url.hostname.split('.') + const id = `${account}.${msg}` - let mimeType: string | undefined = Mime.lookup(filename) || '' - // Make sure that the browser doesn't open files in the PDF viewer. - // TODO is this the only mime type that opens the PDF viewer? - // TODO consider a mime type whitelist instead. - if (mimeType === 'application/pdf') { - // TODO make sure that `callback` won't internally set mime type back - // to 'application/pdf' (at the time of writing it's not the case). - // Otherwise consider explicitly setting it as a header. - mimeType = undefined - } + if (!open_apps[id]) { + return new Response('', { status: 500 }) + } - if (filename === WRAPPER_PATH) { - respond({ - mimeType, - data: await readFile( - join(htmlDistDir(), '/webxdc_wrapper.html') - ), - }) - } else if (filename === 'webxdc.js') { - const displayName = Buffer.from( - displayname || addr || 'unknown' - ).toString('base64') - const selfAddr = Buffer.from( - addr || 'unknown@unknown' - ).toString('base64') - - // initializes the preload script, the actual implementation of `window.webxdc` is found there: static/webxdc-preload.js - respond({ - mimeType, - data: Buffer.from( - `window.parent.webxdc_internal.setup("${selfAddr}","${displayName}") + let filename = url.pathname + // remove leading / trailing "/" + if (filename.endsWith('/')) { + filename = filename.substr(0, filename.length - 1) + } + if (filename.startsWith('/')) { + filename = filename.substr(1) + } + + let mimeType: string | undefined = Mime.lookup(filename) || '' + // Make sure that the browser doesn't open files in the PDF viewer. + // TODO is this the only mime type that opens the PDF viewer? + // TODO consider a mime type whitelist instead. + if (mimeType === 'application/pdf') { + // TODO make sure that `callback` won't internally set mime type back + // to 'application/pdf' (at the time of writing it's not the case). + // Otherwise consider explicitly setting it as a header. + mimeType = undefined + } + + if (filename === WRAPPER_PATH) { + return new Response( + await readFile(join(htmlDistDir(), '/webxdc_wrapper.html')), + { + headers: get_headers(mimeType), + } + ) + } else if (filename === 'webxdc.js') { + const displayName = Buffer.from( + displayname || addr || 'unknown' + ).toString('base64') + const selfAddr = Buffer.from(addr || 'unknown@unknown').toString( + 'base64' + ) + + // initializes the preload script, the actual implementation of `window.webxdc` is found there: static/webxdc-preload.js + return new Response( + Buffer.from( + `window.parent.webxdc_internal.setup("${selfAddr}","${displayName}") window.webxdc = window.parent.webxdc window.webxdc_custom = window.parent.webxdc_custom` + ), + { + headers: get_headers(mimeType), + } + ) + } else { + try { + const blob = Buffer.from( + await this.rpc.getWebxdcBlob( + open_apps[id].accountId, + open_apps[id].msgId, + filename ), + 'base64' + ) + return new Response(blob, { + headers: get_headers(mimeType), }) - } else { - try { - const blob = Buffer.from( - await this.rpc.getWebxdcBlob( - open_apps[id].accountId, - open_apps[id].msgId, - filename - ), - 'base64' - ) - - respond({ - mimeType, - data: blob, - }) - } catch (error) { - log.error('webxdc: load blob:', error) - respond({ - statusCode: 404, - }) - } + } catch (error) { + log.error('webxdc: load blob:', error) + return new Response('', { status: 404 }) } } - ) + }) } const app_icon = icon_blob && nativeImage?.createFromBuffer(icon_blob) diff --git a/src/main/open_url.ts b/src/main/open_url.ts index 7fc5f6891a..0249f144b7 100644 --- a/src/main/open_url.ts +++ b/src/main/open_url.ts @@ -91,7 +91,7 @@ export function openUrlFromArgv(argv: string[]) { } } -app.on('second-instance', (_event, argv)=>{ +app.on('second-instance', (_event, argv) => { log.debug('Someone tried to run a second instance') openUrlFromArgv(argv) if (window) { diff --git a/src/main/windows/html_email.ts b/src/main/windows/html_email.ts index 1d13743a51..82d55b77a7 100644 --- a/src/main/windows/html_email.ts +++ b/src/main/windows/html_email.ts @@ -315,39 +315,34 @@ function makeBrowserView( ses.setProxy({ mode: 'fixed_servers', proxyRules: 'not-existing-proxy:80' }) if (!allow_remote_content) { // block network access - ses.protocol.interceptHttpProtocol('http', (_req, callback) => { - callback({ statusCode: 404, data: '' }) + ses.protocol.handle('http', () => { + return new Response('', { status: 404 }) }) - ses.protocol.interceptHttpProtocol('https', (_req, callback) => { - callback({ statusCode: 404, data: '' }) + ses.protocol.handle('https', () => { + return new Response('', { status: 404 }) }) } - ses.protocol.registerBufferProtocol('email', (_req, callback) => { - callback({ - statusCode: 200, - data: Buffer.from(html_content), - mimeType: 'text/html', + ses.protocol.handle('email', () => { + return new Response(Buffer.from(html_content), { + status: 200, headers: { + 'content-type': 'text/html', 'Content-Security-Policy': allow_remote_content ? CSP_ALLOW : CSP_DENY, }, }) }) if (allow_remote_content) { - const callback = async ( - req: Electron.ProtocolRequest, - callback: (response: Electron.ProtocolResponse) => void - ) => { + const callback = async (req: Request) => { try { const response = await getDCJsonrpcClient().getHttpResponse( account_id, req.url ) const blob = Buffer.from(response.blob, 'base64') - callback({ - statusCode: 200, - data: blob, + return new Response(blob, { + status: 200, headers: { 'Content-Security-Policy': CSP_ALLOW, 'Content-Type': `${response.mimetype}; ${response.encoding}`, @@ -355,16 +350,17 @@ function makeBrowserView( }) } catch (error) { log.info('remote content failed to load', req.url, error) - callback({ - statusCode: 400, - data: Buffer.from((error as any)?.message), - mimeType: 'text/plain', + return new Response(Buffer.from((error as any)?.message), { + status: 400, + headers: { + mimeType: 'text/plain', + }, }) } } - ses.protocol.interceptBufferProtocol('http', callback) - ses.protocol.interceptBufferProtocol('https', callback) + ses.protocol.handle('http', callback) + ses.protocol.handle('https', callback) } const sandboxedView = new BrowserView({