Last active
October 22, 2022 18:17
-
-
Save george-thomas-hill/c3179e6eddeb1a2715201a20dbf95015 to your computer and use it in GitHub Desktop.
Demonstrates that embedding PDFs using webviews and custom protocols crashes Electron.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!DOCTYPE html> | |
<html> | |
<head> | |
<meta charset="UTF-8"> | |
<!-- https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP --> | |
<meta http-equiv="Content-Security-Policy" | |
content="default-src 'self'; script-src 'self' 'unsafe-inline'; style-src 'self' 'unsafe-inline'; frame-src 'self' customprotocolname: ;"> | |
<link href="./styles.css" rel="stylesheet"> | |
<title>Hello World!</title> | |
</head> | |
<body> | |
<h1>Hello World!</h1> | |
We are using Node.js <span id="node-version"></span>, | |
Chromium <span id="chrome-version"></span>, | |
and Electron <span id="electron-version"></span>. | |
<h1>See what happens if you load a local .png or a local .pdf into the iframe.</h1> | |
<button onclick="loadFileIntoIframe()">Load file into iFrame</button> | |
<br> | |
<br> | |
<iframe id="theIframe" src=""></iframe> | |
<p>For me, embedding these files works correctly. However …</p> | |
<h1>See what happens if you load a local .png or local .pdf using a custom protocol.</h1> | |
<button onclick="loadFileIntoIframeUsingCustomProtocol()">Load file into iFrame using a custom protocol</button> | |
<br> | |
<br> | |
<iframe id="theIframeForCustomProtocol" src=""></iframe> | |
<p>For me, .png files display correctly, but .pdf files only display as a gray box.</p> | |
<h1>See what happens if you load a local .png or local .pdf using a custom protocol into a webview.</h1> | |
<button onclick="loadFileIntoWebviewUsingCustomProtocol()">Load file into webview using a custom protocol</button> | |
<br> | |
<br> | |
<webview id="theWebview" src="" | |
webpreferences="sandbox=yes, javascript=no, autoplayPolicy=document-user-activation-required"> | |
</webview> | |
<p>For me, .png files display correctly, but .pdf files crash Electron ("Electron exited with signal SIGTRAP.").</p> | |
<script src="./renderer.js"></script> | |
</body> | |
</html> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const { app, BrowserWindow, dialog, ipcMain, protocol } = require('electron'); | |
const path = require('path'); | |
function createWindow() { | |
const mainWindow = new BrowserWindow({ | |
width: 1200, | |
height: 700, | |
webPreferences: { | |
preload: path.join(__dirname, 'preload.js'), | |
webviewTag: true, | |
}, | |
}); | |
mainWindow.loadFile('index.html'); | |
mainWindow.webContents.openDevTools() | |
} | |
app.whenReady().then( | |
() => { | |
createWindow(); | |
app.on('activate', function () { | |
if (BrowserWindow.getAllWindows().length === 0) createWindow(); | |
}); | |
} | |
); | |
app.on( | |
'window-all-closed', | |
function () { | |
if (process.platform !== 'darwin') app.quit(); | |
} | |
); | |
ipcMain.handle("getFilePathFromDialog", handleGetFilePathFromDialog); | |
async function handleGetFilePathFromDialog(event, desiredOptions) { | |
const mainWindow = BrowserWindow.fromWebContents(event.sender); | |
const result = dialog.showOpenDialog(mainWindow, desiredOptions); | |
return result; | |
} | |
// https://github.com/electron/electron/issues/23393 | |
const files = {}; | |
app.whenReady().then(() => { | |
const protocolName = "customprotocolname"; | |
protocol.registerFileProtocol( | |
protocolName, | |
(request, callback) => { | |
// console.log(`request: ${"v".repeat(60)}`); | |
// console.log(request); | |
// console.log(`request: ${"^".repeat(60)}`); | |
const theUrl = request.url; | |
const theUrlParts = theUrl.split("/"); | |
const fileIdString = theUrlParts[theUrlParts.length - 1]; | |
const fileId = parseInt(fileIdString, 10); | |
// console.log("fileId:", fileId); | |
if (files[fileId]) { | |
const resolvedPath = files[fileId]; | |
// console.log(`\n\nServing:\n\n` + resolvedPath); | |
callback(resolvedPath); | |
} else { | |
callback(404); | |
} | |
}); | |
}); | |
ipcMain.handle( | |
"serveFile", | |
(event, filePath) => { | |
// console.log(event, args); | |
const id = Math.floor(Math.random() * 1000 * 1000 * 1000); | |
// console.log(`\n\nSetting id ${id} --> ${filePath}\n\n`); | |
files[id] = filePath; | |
return id; | |
} | |
); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{ | |
"name": "electron-embed-pdfs", | |
"productName": "electron-embed-pdfs", | |
"description": "My Electron application description", | |
"keywords": [], | |
"main": "./main.js", | |
"version": "1.0.0", | |
"author": "george-thomas-hill", | |
"scripts": { | |
"start": "electron ." | |
}, | |
"dependencies": {}, | |
"devDependencies": { | |
"electron": "21.2.0" | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
window.addEventListener( | |
'DOMContentLoaded', | |
() => { | |
const replaceText = (selector, text) => { | |
const element = document.getElementById(selector); | |
if (element) element.innerText = text; | |
} | |
for (const type of ['chrome', 'node', 'electron']) { | |
replaceText(`${type}-version`, process.versions[type]); | |
} | |
} | |
); | |
// import { ipcRenderer, contextBridge } from "electron"; | |
const { ipcRenderer, contextBridge } = require("electron"); | |
contextBridge.exposeInMainWorld( | |
"electron", | |
{ | |
ipcApi: { | |
getFilePathFromDialog(parametersObject) { | |
const resultObject = | |
ipcRenderer.invoke("getFilePathFromDialog", parametersObject); | |
return resultObject; | |
}, | |
askForFileToBeServed(desiredPath) { | |
const theId = ipcRenderer.invoke("serveFile", desiredPath); | |
return theId; | |
}, | |
}, | |
} | |
); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
async function loadFileIntoIframe() { | |
const theResult = | |
await window.electron.ipcApi.getFilePathFromDialog({ | |
title: "Choose a File to Embed", | |
buttonLabel: "Embed This File", | |
message: "Please select the file that you want to embed.", | |
properties: [ | |
"showHiddenFiles", | |
], | |
}); | |
console.log(theResult); | |
if (theResult.canceled === false) { | |
const theIframe = document.getElementById("theIframe"); | |
theIframe.src = `file://${theResult.filePaths[0]}`; | |
} | |
} | |
async function loadFileIntoIframeUsingCustomProtocol() { | |
const theResult = | |
await window.electron.ipcApi.getFilePathFromDialog({ | |
title: "Choose a File to Embed Using a Custom Protocol", | |
buttonLabel: "Embed This File", | |
message: "Please select the file that you want to embed using a custom protocol.", | |
properties: [ | |
"showHiddenFiles", | |
], | |
}); | |
console.log(theResult); | |
if (theResult.canceled === false) { | |
const thePromise = window.electron.ipcApi.askForFileToBeServed(theResult.filePaths[0]); | |
thePromise.then(processTheResult); | |
function processTheResult(result) { | |
console.log(result); | |
const theIframe = document.getElementById("theIframeForCustomProtocol"); | |
theIframe.src = `customprotocolname://secretString/${result}`; | |
} | |
}; | |
} | |
async function loadFileIntoWebviewUsingCustomProtocol() { | |
const theResult = | |
await window.electron.ipcApi.getFilePathFromDialog({ | |
title: "Choose a File to Embed Using a Custom Protocol", | |
buttonLabel: "Embed This File", | |
message: "Please select the file that you want to embed using a custom protocol.", | |
properties: [ | |
"showHiddenFiles", | |
], | |
}); | |
console.log(theResult); | |
if (theResult.canceled === false) { | |
const thePromise = window.electron.ipcApi.askForFileToBeServed(theResult.filePaths[0]); | |
thePromise.then(processTheResult); | |
function processTheResult(result) { | |
console.log(result); | |
const theWebview = document.getElementById("theWebview"); | |
theWebview.src = `customprotocolname://secretString/${result}`; | |
} | |
}; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* No styles! */ |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment