电子中给定上下文隔离的预加载与客户端之间的通信

时间:2019-04-06 00:56:02

标签: electron

我有一个电子应用程序。我的客户端脚本(渲染器)需要访问电子API,但这给了我一个安全警告,因此我将其移至预加载脚本中并禁用了nodeIntegration。然后,我收到有关contextIsolation的警告,因此启用了它。我的预加载脚本以前在窗口上附加了一个功能,客户端可以读取以下内容:

window.readClipboard = function(){
    return clipboard.readText()
}

不幸的是,上下文隔离意味着客户端无法再访问此功能。有没有办法使它与上下文隔离一起使用,还是应该禁用它?

其他详细信息

促使我尝试打开上下文隔离的警告消息如下:

  

电子弃用警告(contextIsolation默认更改)   默认情况下,窗口禁用了上下文隔离。在电子5.0.0中,   默认情况下将启用上下文隔离。为此做准备   更改,为此在webPreferences中设置{contextIsolation:false}   窗口,或确保此窗口不依赖上下文隔离   被禁用,并设置{contextIsolation:true}。

在client.js中,我尝试访问:

console.log("window.readClipboard", window.readClipboard)

输出:

  

window.readClipboard未定义

1 个答案:

答案 0 :(得分:2)

据我所知,上下文隔离旨在防止出现您所描述的情况。因此,如果您想向window添加数据,最好的办法就是禁用隔离。

但是,我在contextIsolation定义中查找了Content Scripts文档中引用的BrowserWindow文档,并找到了一种使用postMessage来获取剪贴板文本的方法。

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>