( function ( mw ) {
'use strict';
- var storage;
+
+ // Catch exceptions to avoid fatal in Chrome's "Block data storage" mode
+ // which throws when accessing the localStorage property itself, as opposed
+ // to the standard behaviour of throwing on getItem/setItem. (T148998)
+ var
+ localStorage = ( function () {
+ try {
+ return window.localStorage;
+ } catch ( e ) {}
+ }() ),
+ sessionStorage = ( function () {
+ try {
+ return window.sessionStorage;
+ } catch ( e ) {}
+ }() );
/**
- * Library for storing device specific information. It should be used for storing simple
- * strings and is not suitable for storing large chunks of data.
- * @class mw.storage
- * @singleton
+ * A wrapper for an HTML5 Storage interface (`localStorage` or `sessionStorage`)
+ * that is safe to call on all browsers.
+ *
+ * @class mw.SafeStorage
+ * @private
*/
- storage = {
- isLocalStorageSupported: false,
- /**
- * Retrieve value from device storage.
- *
- * @param {String} key of item to retrieve
- * @returns {String|Boolean} false when localStorage not available, otherwise string
- */
- get: function ( key ) {
- if ( this.isLocalStorageSupported ) {
- return localStorage.getItem( key );
- } else {
- return false;
- }
- },
- /**
- * Set a value in device storage.
- *
- * @param {String} key key name to store under.
- * @param {String} value to be stored.
- * @returns {Boolean} whether the save succeeded or not.
- */
- set: function ( key, value ) {
- try {
- localStorage.setItem( key, value );
- return true;
- } catch ( e ) {
- return false;
- }
- },
+ /**
+ * @ignore
+ * @param {Object|undefined} store The Storage instance to wrap around
+ */
+ function SafeStorage( store ) {
+ this.store = store;
+ }
- /**
- * Remove a value from device storage.
- *
- * @param {String} key of item to remove.
- * @returns {Boolean} whether the save succeeded or not.
- */
- remove: function ( key ) {
- if ( this.isLocalStorageSupported ) {
- localStorage.removeItem( key );
- return true;
- } else {
- return false;
- }
- }
+ /**
+ * Retrieve value from device storage.
+ *
+ * @param {string} key Key of item to retrieve
+ * @return {string|boolean} False when localStorage not available, otherwise string
+ */
+ SafeStorage.prototype.get = function ( key ) {
+ try {
+ return this.store.getItem( key );
+ } catch ( e ) {}
+ return false;
};
- mw.storage = storage;
- // See if local storage is supported
- try {
- localStorage.setItem( 'localStorageTest', 'localStorageTest' );
- localStorage.removeItem( 'localStorageTest' );
- storage.isLocalStorageSupported = true;
- } catch ( e ) {
- // Already set. No body needed.
- }
+ /**
+ * Set a value in device storage.
+ *
+ * @param {string} key Key name to store under
+ * @param {string} value Value to be stored
+ * @return {boolean} Whether the save succeeded or not
+ */
+ SafeStorage.prototype.set = function ( key, value ) {
+ try {
+ this.store.setItem( key, value );
+ return true;
+ } catch ( e ) {}
+ return false;
+ };
+
+ /**
+ * Remove a value from device storage.
+ *
+ * @param {string} key Key of item to remove
+ * @return {boolean} Whether the save succeeded or not
+ */
+ SafeStorage.prototype.remove = function ( key ) {
+ try {
+ this.store.removeItem( key );
+ return true;
+ } catch ( e ) {}
+ return false;
+ };
+
+ /**
+ * @class
+ * @singleton
+ * @extends mw.SafeStorage
+ */
+ mw.storage = new SafeStorage( localStorage );
+
+ /**
+ * @class
+ * @singleton
+ * @extends mw.SafeStorage
+ */
+ mw.storage.session = new SafeStorage( sessionStorage );
}( mediaWiki ) );