Skip to content

Commit

Permalink
migrate now deprecated apis
Browse files Browse the repository at this point in the history
  • Loading branch information
Simon-Laux committed Nov 1, 2023
1 parent 906f0c5 commit fd1f8ce
Show file tree
Hide file tree
Showing 3 changed files with 111 additions and 129 deletions.
198 changes: 92 additions & 106 deletions src/main/deltachat/webxdc.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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'
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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<ProtocolResponse, 'headers'>) => {
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)
Expand Down
2 changes: 1 addition & 1 deletion src/main/open_url.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down
40 changes: 18 additions & 22 deletions src/main/windows/html_email.ts
Original file line number Diff line number Diff line change
Expand Up @@ -315,56 +315,52 @@ 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}`,
},
})
} 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({
Expand Down

0 comments on commit fd1f8ce

Please sign in to comment.