Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Communication between preload and client given context isolation in electron

Tags:

electron

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

like image 526
Casebash Avatar asked Apr 06 '19 00:04

Casebash


People also ask

What is context isolation in electron?

​ 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 .

What is Nodeintegration electron?

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.


1 Answers

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>
like image 159
pergy Avatar answered Sep 28 '22 07:09

pergy