Skip to content
Advertisement

Electron, contextIsolation and contextBridge

I recently had to revamp an old Electron app. I found out that it had contextIsolation set to false, so I went ahead and set it to true (and btw set nodeIntegration to false).

As expected, it broke the ipc communications

So I used, as advised in many places, a preload script that enables some communications channels

Here is my preload.js:

const {
    contextBridge,
    ipcRenderer
} = require("electron");

contextBridge.exposeInMainWorld(
    "api", {
        send: (channel, data) => {
            console.log("Send on channel " + channel)
            // whitelist channels
            let validChannels = [];
            if (validChannels.includes(channel)) {
                ipcRenderer.send(channel, data);
            }
        },
        receive: (channel, func) => {
            console.log("Receive on channel " + channel)
            let validChannels = [
                "set-auth-token",
                "set-window-name",
                "get-window-name",
                "send-message-to-one-drive",
                "update-badge",
                "is-hidden",
                "open-google-sign-in"
            ];
            if (validChannels.includes(channel)) {
                // Deliberately strip event as it includes `sender`
                ipcRenderer.on(channel, (event, ...args) => func(...args));
            }
        }
    }
);

My issue is the “api” parameter, I don’t know what to put in there.

Knowing that the website that’s loaded by that app sends messages this way:

let electron = false;
if ('require' in window) {
  electron = window.require('electron');
}

const isAppDesktop = !!electron;

const DesktopHelper = {
  isAppDesktop() {
    return isAppDesktop;
  },

  updateBadge(badgeCount) {
    return isAppDesktop ? electron.ipcRenderer.send('update-badge', badgeCount) : undefined;
  },

  setAuthToken(token) {
    return electron.ipcRenderer.send('set-auth-token', token);
  },

  isHidden() {
    return isAppDesktop ? electron.ipcRenderer.sendSync('is-hidden') : undefined;
  },
};

export default DesktopHelper;

Can someone help?

Advertisement

Answer

contextBridge.exposeInMainWorld(apiKey, api) – the apiKey argument is the name of the object that will be exposed as window[apiKey].

In your example, the apiKey is set to the string "api", so the exposed methods are available in the window.api object. You can access them as window.api.send and window.api.receive.

The methods in DesktopHelper should look like this:

  updateBadge(badgeCount) {
    return isAppDesktop ? window.api.send('update-badge', badgeCount) : 
      undefined;
  },

Or simply api.send('update-badge', badgeCount), since window is the global. You may obviously want to pick a more descriptive name for the API.

User contributions licensed under: CC BY-SA
10 People found this is helpful
Advertisement