Having two isolated (in terms of history/cookies/l

2019-05-03 17:52发布

Let's say I have two BrowserView in the same BrowserWindow and an UI button allowing the user to switch between showing bv1 or bv2 (like the "tab" system in browsers like Firefox, Chrome, that allows you to switch between the different pages):

browserWindow = new BrowserWindow({ width: 1200, height: 600 });

let bv1 = new BrowserView({ webPreferences: { nodeIntegration: false }});
bv1.setBounds({ x: 0, y: 0, width: 1200, height: 600 });
bv1.webContents.loadURL('https://www.twitter.com');

let bv2 = new BrowserView({ webPreferences: { nodeIntegration: false }});
bv2.setBounds({ x: 0, y: 0, width: 1200, height: 600 });
bv2.webContents.loadURL('https://www.twitter.com');

browserWindow.setBrowserView(bv1);

and when a button (like a "tab" in a browser) is pressed:

browserWindow.setBrowserView(bv2);

I noticed that these two BrowserView:

  • share the same cookies/localStorage (which I don't want!), i.e. if the first is connected to an account, the second will be connected as well to the same account

  • keep history and cookies after restart of the Electron app (this is good and wanted indeed!)

Question: how to have the two BrowserView totally isolated in terms of cookies/localStorage/history (and thus bv1 could be connected to one Twitter account and bv2 to another one)?

1条回答
beautiful°
2楼-- · 2019-05-03 18:17

So, I managed to get this working but in a very, very, roundabout way. Effectively session hijacking your own session, saving and loading it on app close/open. Code below with some comments, prefaced with some useful links. This worked when running as dev, and when running with a build application.

You may need to look into possible security issues here with storing cookies locally like this.

The only thing I have not tackled in this answer is:

keep history ... after restart of the Electron app



const { app, BrowserWindow, BrowserView, globalShortcut, session } = require('electron');
const eJSONStorage = require('electron-json-storage');

// Our two different sesions, views, and base URL for our 'tabs'.
let bv1Session, bv2Session = session;
let bv1, bv2 = BrowserView;
const appTabUrl = 'https://www.twitter.com';

app.on('ready', () => {
  const width = 1200; const height = 600;
  let b1Active = true;

  // Our browser window
  browserWindow = new BrowserWindow({
    width: width,
    height: height,
  });

  // Our first browser window with it's own session instance.
  bv1Session = session.fromPartition('persist:bv1Session', { cache: true });
  bv1 = createBrowserView(appTabUrl, bv1Session, width, height);
  loadCookieState('view1Cookies', bv1Session);

  // Our second browser window with it's own session instance.
  bv2Session = session.fromPartition('persist:bv2Session', { cache: true });
  bv2 = createBrowserView(appTabUrl, bv2Session, width, height);
  loadCookieState('view2Cookies', bv2Session);

  // Our initial setting of the browserview
  browserWindow.setBrowserView(bv1);

  // Our shortcut listener and basic switch mechanic
  // Set to [CTRL + /] for windows or [CMD + /] for OSX
  globalShortcut.register('CommandOrControl+/', () => {
    b1Active ? browserWindow.setBrowserView(bv2) : browserWindow.setBrowserView(bv1);
    b1Active = !b1Active
  });
});

// When the app closes, exit gracefully.
// Unregister keypress listener, save cookie states, exit the app.
app.on('window-all-closed', () => {
  globalShortcut.unregisterAll();
  saveCookieState('view1Cookies', bv1Session);
  saveCookieState('view2Cookies', bv2Session);
  app.quit();
})

// Helper method to generate a browser view.
function createBrowserView(url, session, width, height) {
  let browserView = new BrowserView({
    webPreferences: {
      nodeIntegration: false,
      nodeIntegrationInWorker: false,
      session: session
    }
  });
  browserView.setBounds({ x: 0, y: 0, width: width, height: height });
  browserView.webContents.loadURL(url);
  return browserView;
}

// Method that takes a session name, and our current session to save its state.
function saveCookieState(sessionName, currentSession) {
  currentSession.cookies.get({}, (_, cookies) => {
    cookies.forEach(cookie => {
      // URL is a required paramater, take it from the domain with a little parsing.
      // Twitter always uses HTTPS otherwise, we would need to check for http vs https too.
      const cDomain = !cookie.domain.startsWith('.') ? `.${cookie.domain}` : cookie.domain;
      cookie.url = `https://www${cDomain}`
    });
    // Save the set of cookies against the session name.
    eJSONStorage.set(sessionName, cookies, err => {
      if (err) {
        throw err;
      }
    });
  });
}

// Method that loads a session based on its name, into a session created by us.
function loadCookieState(sessionName, currentSession) {
  eJSONStorage.get(sessionName, (error, cookieData) => {
    // Check for empty object returned, this means no saved sessions.
    if (Object.entries(cookieData).length === 0) {
      return;
    }
    if (error) {
      throw error;
    }
    // If we have saved sessions and no errors, load the sessions.
    cookieData.forEach(cookie => currentSession.cookies.set(cookie, error => {
      if (error) console.error(error);
    }));
  });
}
查看更多
登录 后发表回答