Having two isolated (in terms of history/cookies/localstorage) BrowserViews in the same BrowserWindow with ElectronHow to switch website for a BrowserView without waiting for page reload?How browser delete session or delete history works?Persistent unique ID for Chrome tabs that lasts between browser sessionsLosing media query matching after switching portrait-landscape-portraitHow to disable overriding of cookies?Electron and CSS - Two divs with the same FIXED height are displayed differently?electron browserwindow useContentSize doesn't workPutting div content out of browser window in electron appElectron app and Web based angular appAngular / Electron using the renderer.js with angular componentsTwo browsers in the same Electron window
Lay out the Carpet
Is there a good way to store credentials outside of a password manager?
Anatomically Correct Strange Women In Ponds Distributing Swords
Are student evaluations of teaching assistants read by others in the faculty?
when is out of tune ok?
How to be diplomatic in refusing to write code that breaches the privacy of our users
Why, precisely, is argon used in neutrino experiments?
How can I get through very long and very dry, but also very useful technical documents when learning a new tool?
How does Loki do this?
How to write papers efficiently when English isn't my first language?
Gears on left are inverse to gears on right?
How long to clear the 'suck zone' of a turbofan after start is initiated?
Is a stroke of luck acceptable after a series of unfavorable events?
Two monoidal structures and copowering
CREATE opcode: what does it really do?
What can we do to stop prior company from asking us questions?
Crossing the line between justified force and brutality
System.debug(JSON.Serialize(o)) Not longer shows full string
Term for the "extreme-extension" version of a straw man fallacy?
Pole-zeros of a real-valued causal FIR system
Escape a backup date in a file name
Customer Requests (Sometimes) Drive Me Bonkers!
Would this custom Sorcerer variant that can only learn any verbal-component-only spell be unbalanced?
What is the intuitive meaning of having a linear relationship between the logs of two variables?
Having two isolated (in terms of history/cookies/localstorage) BrowserViews in the same BrowserWindow with Electron
How to switch website for a BrowserView without waiting for page reload?How browser delete session or delete history works?Persistent unique ID for Chrome tabs that lasts between browser sessionsLosing media query matching after switching portrait-landscape-portraitHow to disable overriding of cookies?Electron and CSS - Two divs with the same FIXED height are displayed differently?electron browserwindow useContentSize doesn't workPutting div content out of browser window in electron appElectron app and Web based angular appAngular / Electron using the renderer.js with angular componentsTwo browsers in the same Electron window
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)?
javascript
|
show 6 more comments
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)?
javascript
Not sure whether this will work, but did you try withwebPreferences.contextIsolation? From the official docs, it looks like it provides an isolated javascript context, not sure whether this will impact the browser view though, but you may give it a shot: electronjs.org/docs/api/browser-window (the docs are under browser-window, but the BrowserView constructor accepts the browser-window config as argument). Otherwise, you may inject a session instead: electronjs.org/docs/api/session (check webPreferences.session)
– briosheje
Mar 8 at 11:27
Thank you @briosheje, I tried withcontextIsolationbut with no success. Would you have a code sample with session injection? i.e. how to isolate both BrowserViews with different sessions?
– Basj
Mar 9 at 9:27
Why not 2 BrowserWindows?
– Leonardo Buscemi
Mar 10 at 16:20
1
@Basj Making the two windowViews resize won't be too much of an issue, you can just listen to the resize event on the window and set the width/height of both window views to that. Was my answer below any help at all in solving your issues?
– JokerDan
Mar 10 at 21:31
1
@JokerDan It's on my todo list for tomorrow to run it / test it / give feedback (haven't had the time to run the code today), thanks already very much for having posted it!
– Basj
Mar 10 at 21:36
|
show 6 more comments
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)?
javascript
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)?
javascript
javascript
asked Mar 8 at 11:06
BasjBasj
6,13833108241
6,13833108241
Not sure whether this will work, but did you try withwebPreferences.contextIsolation? From the official docs, it looks like it provides an isolated javascript context, not sure whether this will impact the browser view though, but you may give it a shot: electronjs.org/docs/api/browser-window (the docs are under browser-window, but the BrowserView constructor accepts the browser-window config as argument). Otherwise, you may inject a session instead: electronjs.org/docs/api/session (check webPreferences.session)
– briosheje
Mar 8 at 11:27
Thank you @briosheje, I tried withcontextIsolationbut with no success. Would you have a code sample with session injection? i.e. how to isolate both BrowserViews with different sessions?
– Basj
Mar 9 at 9:27
Why not 2 BrowserWindows?
– Leonardo Buscemi
Mar 10 at 16:20
1
@Basj Making the two windowViews resize won't be too much of an issue, you can just listen to the resize event on the window and set the width/height of both window views to that. Was my answer below any help at all in solving your issues?
– JokerDan
Mar 10 at 21:31
1
@JokerDan It's on my todo list for tomorrow to run it / test it / give feedback (haven't had the time to run the code today), thanks already very much for having posted it!
– Basj
Mar 10 at 21:36
|
show 6 more comments
Not sure whether this will work, but did you try withwebPreferences.contextIsolation? From the official docs, it looks like it provides an isolated javascript context, not sure whether this will impact the browser view though, but you may give it a shot: electronjs.org/docs/api/browser-window (the docs are under browser-window, but the BrowserView constructor accepts the browser-window config as argument). Otherwise, you may inject a session instead: electronjs.org/docs/api/session (check webPreferences.session)
– briosheje
Mar 8 at 11:27
Thank you @briosheje, I tried withcontextIsolationbut with no success. Would you have a code sample with session injection? i.e. how to isolate both BrowserViews with different sessions?
– Basj
Mar 9 at 9:27
Why not 2 BrowserWindows?
– Leonardo Buscemi
Mar 10 at 16:20
1
@Basj Making the two windowViews resize won't be too much of an issue, you can just listen to the resize event on the window and set the width/height of both window views to that. Was my answer below any help at all in solving your issues?
– JokerDan
Mar 10 at 21:31
1
@JokerDan It's on my todo list for tomorrow to run it / test it / give feedback (haven't had the time to run the code today), thanks already very much for having posted it!
– Basj
Mar 10 at 21:36
Not sure whether this will work, but did you try with
webPreferences.contextIsolation? From the official docs, it looks like it provides an isolated javascript context, not sure whether this will impact the browser view though, but you may give it a shot: electronjs.org/docs/api/browser-window (the docs are under browser-window, but the BrowserView constructor accepts the browser-window config as argument). Otherwise, you may inject a session instead: electronjs.org/docs/api/session (check webPreferences.session)– briosheje
Mar 8 at 11:27
Not sure whether this will work, but did you try with
webPreferences.contextIsolation? From the official docs, it looks like it provides an isolated javascript context, not sure whether this will impact the browser view though, but you may give it a shot: electronjs.org/docs/api/browser-window (the docs are under browser-window, but the BrowserView constructor accepts the browser-window config as argument). Otherwise, you may inject a session instead: electronjs.org/docs/api/session (check webPreferences.session)– briosheje
Mar 8 at 11:27
Thank you @briosheje, I tried with
contextIsolation but with no success. Would you have a code sample with session injection? i.e. how to isolate both BrowserViews with different sessions?– Basj
Mar 9 at 9:27
Thank you @briosheje, I tried with
contextIsolation but with no success. Would you have a code sample with session injection? i.e. how to isolate both BrowserViews with different sessions?– Basj
Mar 9 at 9:27
Why not 2 BrowserWindows?
– Leonardo Buscemi
Mar 10 at 16:20
Why not 2 BrowserWindows?
– Leonardo Buscemi
Mar 10 at 16:20
1
1
@Basj Making the two windowViews resize won't be too much of an issue, you can just listen to the resize event on the window and set the width/height of both window views to that. Was my answer below any help at all in solving your issues?
– JokerDan
Mar 10 at 21:31
@Basj Making the two windowViews resize won't be too much of an issue, you can just listen to the resize event on the window and set the width/height of both window views to that. Was my answer below any help at all in solving your issues?
– JokerDan
Mar 10 at 21:31
1
1
@JokerDan It's on my todo list for tomorrow to run it / test it / give feedback (haven't had the time to run the code today), thanks already very much for having posted it!
– Basj
Mar 10 at 21:36
@JokerDan It's on my todo list for tomorrow to run it / test it / give feedback (haven't had the time to run the code today), thanks already very much for having posted it!
– Basj
Mar 10 at 21:36
|
show 6 more comments
1 Answer
1
active
oldest
votes
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
Electron-Json-Storage Package - We use this to store/retrieve cookies. The default location for storage isC:Users%user%AppDataRoaming%appname%storage.
Electron Cookies documentation
Electron Session documentation - Notably thesession.fromPartitiondocs.
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);
));
);
1
Thanks @JokenDan, it seems to totally work! Even theThe only thing I have not tackled in this answer is: keep history after restart: it seems to work! Does it for you too? I'll continue my tests, and will post if anything seems to break this, but so far, it seems to work. PS: what do you want to do withconst cDomain = !cookie.domain.startsWith('.') ? '.$cookie.domain' : cookie.domain; cookie.url = 'https://www$cDomain'?
– Basj
Mar 11 at 15:58
So, theurlproperty is not populated on the cookie when we get them, but it is a required property when we set them. So here, we are taking the domain for the cookie (Some cases it is.twitter.comand othersauth.twitter.comfor instance). When saving, it has to be a fully qualified URL (https://www.twitter.com) - So we are just doing a check for the.and constructing the URL properly from the domain, to be a full URL. Like I said in the comment, if you want to use websites that mix http and https, then you will need to account for and do a check for that.
– JokerDan
Mar 11 at 16:12
add a comment |
Your Answer
StackExchange.ifUsing("editor", function ()
StackExchange.using("externalEditor", function ()
StackExchange.using("snippets", function ()
StackExchange.snippets.init();
);
);
, "code-snippets");
StackExchange.ready(function()
var channelOptions =
tags: "".split(" "),
id: "1"
;
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function()
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled)
StackExchange.using("snippets", function()
createEditor();
);
else
createEditor();
);
function createEditor()
StackExchange.prepareEditor(
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader:
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
,
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
);
);
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f55061908%2fhaving-two-isolated-in-terms-of-history-cookies-localstorage-browserviews-in-t%23new-answer', 'question_page');
);
Post as a guest
Required, but never shown
1 Answer
1
active
oldest
votes
1 Answer
1
active
oldest
votes
active
oldest
votes
active
oldest
votes
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
Electron-Json-Storage Package - We use this to store/retrieve cookies. The default location for storage isC:Users%user%AppDataRoaming%appname%storage.
Electron Cookies documentation
Electron Session documentation - Notably thesession.fromPartitiondocs.
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);
));
);
1
Thanks @JokenDan, it seems to totally work! Even theThe only thing I have not tackled in this answer is: keep history after restart: it seems to work! Does it for you too? I'll continue my tests, and will post if anything seems to break this, but so far, it seems to work. PS: what do you want to do withconst cDomain = !cookie.domain.startsWith('.') ? '.$cookie.domain' : cookie.domain; cookie.url = 'https://www$cDomain'?
– Basj
Mar 11 at 15:58
So, theurlproperty is not populated on the cookie when we get them, but it is a required property when we set them. So here, we are taking the domain for the cookie (Some cases it is.twitter.comand othersauth.twitter.comfor instance). When saving, it has to be a fully qualified URL (https://www.twitter.com) - So we are just doing a check for the.and constructing the URL properly from the domain, to be a full URL. Like I said in the comment, if you want to use websites that mix http and https, then you will need to account for and do a check for that.
– JokerDan
Mar 11 at 16:12
add a comment |
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
Electron-Json-Storage Package - We use this to store/retrieve cookies. The default location for storage isC:Users%user%AppDataRoaming%appname%storage.
Electron Cookies documentation
Electron Session documentation - Notably thesession.fromPartitiondocs.
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);
));
);
1
Thanks @JokenDan, it seems to totally work! Even theThe only thing I have not tackled in this answer is: keep history after restart: it seems to work! Does it for you too? I'll continue my tests, and will post if anything seems to break this, but so far, it seems to work. PS: what do you want to do withconst cDomain = !cookie.domain.startsWith('.') ? '.$cookie.domain' : cookie.domain; cookie.url = 'https://www$cDomain'?
– Basj
Mar 11 at 15:58
So, theurlproperty is not populated on the cookie when we get them, but it is a required property when we set them. So here, we are taking the domain for the cookie (Some cases it is.twitter.comand othersauth.twitter.comfor instance). When saving, it has to be a fully qualified URL (https://www.twitter.com) - So we are just doing a check for the.and constructing the URL properly from the domain, to be a full URL. Like I said in the comment, if you want to use websites that mix http and https, then you will need to account for and do a check for that.
– JokerDan
Mar 11 at 16:12
add a comment |
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
Electron-Json-Storage Package - We use this to store/retrieve cookies. The default location for storage isC:Users%user%AppDataRoaming%appname%storage.
Electron Cookies documentation
Electron Session documentation - Notably thesession.fromPartitiondocs.
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);
));
);
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
Electron-Json-Storage Package - We use this to store/retrieve cookies. The default location for storage isC:Users%user%AppDataRoaming%appname%storage.
Electron Cookies documentation
Electron Session documentation - Notably thesession.fromPartitiondocs.
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);
));
);
edited Mar 10 at 18:00
answered Mar 10 at 16:53
JokerDanJokerDan
1,052716
1,052716
1
Thanks @JokenDan, it seems to totally work! Even theThe only thing I have not tackled in this answer is: keep history after restart: it seems to work! Does it for you too? I'll continue my tests, and will post if anything seems to break this, but so far, it seems to work. PS: what do you want to do withconst cDomain = !cookie.domain.startsWith('.') ? '.$cookie.domain' : cookie.domain; cookie.url = 'https://www$cDomain'?
– Basj
Mar 11 at 15:58
So, theurlproperty is not populated on the cookie when we get them, but it is a required property when we set them. So here, we are taking the domain for the cookie (Some cases it is.twitter.comand othersauth.twitter.comfor instance). When saving, it has to be a fully qualified URL (https://www.twitter.com) - So we are just doing a check for the.and constructing the URL properly from the domain, to be a full URL. Like I said in the comment, if you want to use websites that mix http and https, then you will need to account for and do a check for that.
– JokerDan
Mar 11 at 16:12
add a comment |
1
Thanks @JokenDan, it seems to totally work! Even theThe only thing I have not tackled in this answer is: keep history after restart: it seems to work! Does it for you too? I'll continue my tests, and will post if anything seems to break this, but so far, it seems to work. PS: what do you want to do withconst cDomain = !cookie.domain.startsWith('.') ? '.$cookie.domain' : cookie.domain; cookie.url = 'https://www$cDomain'?
– Basj
Mar 11 at 15:58
So, theurlproperty is not populated on the cookie when we get them, but it is a required property when we set them. So here, we are taking the domain for the cookie (Some cases it is.twitter.comand othersauth.twitter.comfor instance). When saving, it has to be a fully qualified URL (https://www.twitter.com) - So we are just doing a check for the.and constructing the URL properly from the domain, to be a full URL. Like I said in the comment, if you want to use websites that mix http and https, then you will need to account for and do a check for that.
– JokerDan
Mar 11 at 16:12
1
1
Thanks @JokenDan, it seems to totally work! Even the
The only thing I have not tackled in this answer is: keep history after restart : it seems to work! Does it for you too? I'll continue my tests, and will post if anything seems to break this, but so far, it seems to work. PS: what do you want to do with const cDomain = !cookie.domain.startsWith('.') ? '.$cookie.domain' : cookie.domain; cookie.url = 'https://www$cDomain'?– Basj
Mar 11 at 15:58
Thanks @JokenDan, it seems to totally work! Even the
The only thing I have not tackled in this answer is: keep history after restart : it seems to work! Does it for you too? I'll continue my tests, and will post if anything seems to break this, but so far, it seems to work. PS: what do you want to do with const cDomain = !cookie.domain.startsWith('.') ? '.$cookie.domain' : cookie.domain; cookie.url = 'https://www$cDomain'?– Basj
Mar 11 at 15:58
So, the
url property is not populated on the cookie when we get them, but it is a required property when we set them. So here, we are taking the domain for the cookie (Some cases it is .twitter.com and others auth.twitter.com for instance). When saving, it has to be a fully qualified URL (https://www.twitter.com) - So we are just doing a check for the . and constructing the URL properly from the domain, to be a full URL. Like I said in the comment, if you want to use websites that mix http and https, then you will need to account for and do a check for that.– JokerDan
Mar 11 at 16:12
So, the
url property is not populated on the cookie when we get them, but it is a required property when we set them. So here, we are taking the domain for the cookie (Some cases it is .twitter.com and others auth.twitter.com for instance). When saving, it has to be a fully qualified URL (https://www.twitter.com) - So we are just doing a check for the . and constructing the URL properly from the domain, to be a full URL. Like I said in the comment, if you want to use websites that mix http and https, then you will need to account for and do a check for that.– JokerDan
Mar 11 at 16:12
add a comment |
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f55061908%2fhaving-two-isolated-in-terms-of-history-cookies-localstorage-browserviews-in-t%23new-answer', 'question_page');
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Not sure whether this will work, but did you try with
webPreferences.contextIsolation? From the official docs, it looks like it provides an isolated javascript context, not sure whether this will impact the browser view though, but you may give it a shot: electronjs.org/docs/api/browser-window (the docs are under browser-window, but the BrowserView constructor accepts the browser-window config as argument). Otherwise, you may inject a session instead: electronjs.org/docs/api/session (check webPreferences.session)– briosheje
Mar 8 at 11:27
Thank you @briosheje, I tried with
contextIsolationbut with no success. Would you have a code sample with session injection? i.e. how to isolate both BrowserViews with different sessions?– Basj
Mar 9 at 9:27
Why not 2 BrowserWindows?
– Leonardo Buscemi
Mar 10 at 16:20
1
@Basj Making the two windowViews resize won't be too much of an issue, you can just listen to the resize event on the window and set the width/height of both window views to that. Was my answer below any help at all in solving your issues?
– JokerDan
Mar 10 at 21:31
1
@JokerDan It's on my todo list for tomorrow to run it / test it / give feedback (haven't had the time to run the code today), thanks already very much for having posted it!
– Basj
Mar 10 at 21:36