上下文隔离
上下文隔离(contextIsolation)让预加载脚本和 Electron 内部逻辑跑在独立的 JavaScript 上下文里,和页面加载的网站分开。自 Electron 12 起,这个选项默认开启。
官方文档中的直接后果是:预加载脚本里执行 window.hello = 'wave',页面里读取 window.hello 得到的是 undefined。两边各有自己的全局对象和内置对象原型,因此页面改写 Array.prototype.push 影响不到预加载脚本。
DOM 仍然是同一份。预加载脚本可以查询页面上的节点,只是不能把变量直接挂到页面的 window 上。
把能力交到页面
使用 contextBridge.exposeInMainWorld。函数会被代理到另一侧,其余值会被复制并冻结。页面改这份复制,预加载脚本里的原对象不变。
contextBridge.exposeInMainWorld('api', {
save: (content) => ipcRenderer.invoke('file:save', content),
});
只暴露完整的 ipcRenderer 时,页面就能向主进程发送任意频道。官方建议为一个频道写一个函数,并在主进程检查参数。
和沙箱的关系
官方安全清单写明:关掉上下文隔离会同时关掉该渲染进程的进程沙箱,即使单独把 sandbox 设为 true 也一样。两个开关要一起保持开启。
开发者工具的 Console 顶部可以把上下文切到 “Electron Isolated Context”,用来查看预加载脚本所在的世界。