packages/fxa-content-server/app/scripts/lib/session.js (108 lines of code) (raw):
/* eslint-disable no-prototype-builtins */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
// Session saves session information about the user. Data is automatically
// saved to sessionStorage and automatically loaded from sessionStorage on startup.
import _ from 'underscore';
var NAMESPACE = '__fxa_session';
// these keys will be persisted to localStorage so that they live between browser sessions
var PERSIST_TO_LOCAL_STORAGE = ['oauth'];
function Session() {
this.load();
}
Session.prototype = {
/**
* Load info from sessionStorage
* @method load
* @returns {Object}
*/
load() {
var values = {};
// Try parsing sessionStorage values
try {
values = _.extend(values, JSON.parse(sessionStorage.getItem(NAMESPACE)));
} catch (e) {
// ignore the parse error.
}
// Try parsing localStorage values
try {
values = _.extend(values, JSON.parse(localStorage.getItem(NAMESPACE)));
} catch (e) {
// ignore the parse error.
}
// Update new values, without overwriting items on the prototype.
_.each(
values,
function (value, key) {
// eslint-disable-next-line no-prototype-builtins
if (!Session.prototype.hasOwnProperty(key)) {
this[key] = value;
}
},
this
);
return values;
},
/**
* Reload in-memory values based on what's currently in storage.
* This method can be used to pull in any changes to localStorage
* made by other tabs. Note that it will remove items from the session
* if they no longer appear in sessionStorage or localStorage.
* @method reload
*/
reload() {
var values = this.load();
// Clear values that no longer exist in storage.
_.each(
this,
function (value, key) {
if (!Session.prototype.hasOwnProperty(key)) {
if (!values.hasOwnProperty(key)) {
this[key] = null;
delete this[key];
}
}
},
this
);
},
/**
* Set data.
* Note: items with keys in Session.prototype cannot be overwritten.
*
* @method set
* @param {Object|String} key - can take either a key/value pair or a dictionary of key/value pairs.
* @param {String} [value]
* @returns {undefined}
*/
set(key, value) {
if (typeof value === 'undefined' && typeof key === 'object') {
return _.each(
key,
function (value, key) {
this.set(key, value);
},
this
);
}
// don't overwrite any items on the prototype.
if (!Session.prototype.hasOwnProperty(key)) {
this[key] = value;
this.persist();
}
},
/**
* Persist data to sessionStorage or localStorage
* @method persist
*/
persist() {
// items on the blacklist do not get saved to sessionStorage.
var toSaveToSessionStorage = {};
var toSaveToLocalStorage = {};
_.each(this, function (value, key) {
if (_.indexOf(PERSIST_TO_LOCAL_STORAGE, key) >= 0) {
toSaveToLocalStorage[key] = value;
} else {
toSaveToSessionStorage[key] = value;
}
});
// Wrap browser storage access in a try/catch block because some browsers
// (Firefox, Chrome) except when trying to access browser storage and
// cookies are disabled.
try {
localStorage.setItem(NAMESPACE, JSON.stringify(toSaveToLocalStorage));
sessionStorage.setItem(NAMESPACE, JSON.stringify(toSaveToSessionStorage));
} catch (e) {
// some browsers disable access to browser storage
// if cookies are disabled.
}
},
/**
* Get an item
* @method get
* @param {String} key
* @returns {Object}
*/
get(key) {
return this[key];
},
/**
* Remove an item or all items
*
* If no key specified, all items are cleared.
* Note: items in Session.prototype cannot be cleared
*
* @method clear
* @param {String} [key]
*/
clear(key) {
// no key specified, clear everything.
if (typeof key === 'undefined') {
for (key in this) {
this.clear(key);
}
return;
}
if (this.hasOwnProperty(key)) {
this[key] = null;
delete this[key];
this.persist();
}
},
// BEGIN TEST API
/**
* Remove an item from memory but not sessionStorage. Used to test .load
* @method testRemove
* @param {String} key
* @private
*/
testRemove(key) {
if (this.hasOwnProperty(key)) {
this[key] = null;
delete this[key];
}
},
/**
* Clear everything, for testing.
* @method testClear
* @private
*/
testClear() {
for (var key in this) {
if (this.hasOwnProperty(key)) {
this[key] = null;
delete this[key];
}
}
sessionStorage.clear();
localStorage.clear();
},
// END TEST API
};
// session is a singleton
export default new Session();