javascript - 在与 Electron 相同的 BrowserWindow 中有两个独立的(在历史/cookies/localstorage 方面)BrowserViews

标签 javascript google-chrome browser electron

假设我在同一个 BrowserWindow 中有两个 BrowserView 和一个允许用户在显示 bv1 之间切换的 UI 按钮bv2(类似于 Firefox、Chrome 等浏览器中的“选项卡”系统,允许您在不同页面之间切换):

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);

当按下按钮(如浏览器中的“选项卡”)时:

browserWindow.setBrowserView(bv2);

我注意到这两个 BrowserView:

  • 共享相同的 cookies/localStorage(我不想要!),即如果第一个连接到一个帐户,第二个也将连接到同一个帐户

  • 在 Electron 应用程序重启后保留历史记录和 cookie(这很好,确实需要!)

问题:如何让两个 BrowserView 在 cookies/localStorage/history 方面完全隔离(因此 bv1 可以连接到一个 Twitter 帐户并 bv2 连接到另一个)?

最佳答案

因此,我设法以一种非常、非常、迂回的方式实现了它。有效 session 劫持您自己的 session ,在应用程序关闭/打开时保存和加载它。下面的代码带有一些注释,并以一些有用的链接开头。这在以开发人员身份运行时以及使用构建应用程序运行时有效。

您可能需要在此处查看像这样在本地存储 cookie 时可能存在的安全问题。

我在这个答案中唯一没有解决的是:

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);
    }));
  });
}

关于javascript - 在与 Electron 相同的 BrowserWindow 中有两个独立的(在历史/cookies/localstorage 方面)BrowserViews,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55061908/

相关文章:

php - 语法错误 : Unexpected EOF

css - 隐藏移动内容

javascript - 在 google maps api v3 服务中使用查询字符串参数

javascript - 使用 Codeigniter 表单验证和 Jquery 序列化

javascript - d3js 步进线图 - 鼠标悬停时突出显示两点之间的线

python-2.7 - 如何在 Chrome 中使用 Selenium + Python 绑定(bind)控制文件的下载

javascript - 单击通知时打开弹出窗口

firefox - 浏览器添加 www.和 .com 自动到服务器地址

java - 如何在浏览器中显示DynamicReports而不下载到客户端驱动器?

php - 带有\x26 值的 JSON 破坏了 PHPs json_decode