I have an electron app. My client script (renderer) needs to access electron APIs, but this gave me a security warning, so I moved it into a preload script and disabled nodeIntegration. I was then receiving a warning about contextIsolation, so I enabled it. My preload script was previously attaching a function to window that the client could read as follows:
window.readClipboard = function(){
return clipboard.readText()
}
Unfortunately, context isolation meant that the client could no longer access this function. Is there a way to make this work with context isolation or should I disable it?
Extra Details
The warning message that made me try to turn on context isolation was the following:
Electron Deprecation Warning (contextIsolation default change) This window has context isolation disabled by default. In Electron 5.0.0, context isolation will be enabled by default. To prepare for this change, set {contextIsolation: false} in the webPreferences for this window, or ensure that this window does not rely on context isolation being disabled, and set {contextIsolation: true}.
In client.js I try accessing:
console.log("window.readClipboard", window.readClipboard)
With output:
window.readClipboard undefined
Context Isolation is a feature that ensures that both your preload scripts and Electron's internal logic run in a separate context to the website you load in a webContents .
Electron node integration refers to the ability of accessing Node. js resources from within the “renderer” thread (the UI). It is enabled by default in Quasar CLI, although Electron is encouraging developers to turn it off as a security precaution.
As far as I see context isolation is designed to prevent the very case you described. So if you want to add data to window
the best you can do is disable isolation.
However, I looked up the Content Scripts docs referred in BrowserWindow docs at the contextIsolation
definition and find a way to use postMessage
to get the clipboard text.
main.js
const { app, BrowserWindow } = require('electron')
const path = require('path')
app.once('ready', () => {
let win = new BrowserWindow({
webPreferences: {
nodeIntegration: false,
contextIsolation: true,
preload: path.join(__dirname, 'preload.js')
}
})
win.loadURL(path.join(__dirname, 'index.html'))
})
preload.js
const { clipboard } = require('electron')
window.addEventListener("message", (event) => {
if (event.source != window) return
if (event.data.type && (event.data.type == "READCLIP_REQ")) {
window.postMessage({ type: "READCLIP_ANS", text: window.readClipboard() }, "*")
}
}, false)
window.readClipboard = function(){
return clipboard.readText()
}
index.html
<html>
<body>
<p></p>
<p></p>
<script>
// Try window.readClipboard directly (works with no isolation)
document.getElementsByTagName("p")[0].innerText =
window.readClipboard && window.readClipboard()
// Try the same with postMessage
const readClipboardMessage = () => {
window.postMessage({ type: "READCLIP_REQ" }, "*")
}
window.addEventListener("message", (event) => {
if (event.source != window) return
if (event.data.type && (event.data.type == "READCLIP_ANS")) {
document.getElementsByTagName("p")[1].innerText = event.data.text
}
}, false)
readClipboardMessage()
</script>
</body>
</html>
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With