// Licensed to the Software Freedom Conservancy (SFC) under one1// or more contributor license agreements. See the NOTICE file2// distributed with this work for additional information3// regarding copyright ownership. The SFC licenses this file4// to you under the Apache License, Version 2.0 (the5// "License"); you may not use this file except in compliance6// with the License. You may obtain a copy of the License at7//8// http://www.apache.org/licenses/LICENSE-2.09//10// Unless required by applicable law or agreed to in writing,11// software distributed under the License is distributed on an12// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY13// KIND, either express or implied. See the License for the14// specific language governing permissions and limitations15// under the License.1617/**18* @fileoverview Atoms for accessing HTML5 web storage maps (localStorage,19* sessionStorage). These storage objects store each item as a key-value20* mapping pair.21*22*/2324goog.provide('bot.storage');25goog.provide('bot.storage.Storage');2627goog.require('bot');28goog.require('bot.Error');29goog.require('bot.ErrorCode');30goog.require('bot.html5');313233/**34* A factory method to create a wrapper to access the HTML5 localStorage35* object.36* Note: We are not using Closure from goog.storage,37* Closure uses "window" object directly, which may not always be38* defined (for example in firefox extensions).39* We use bot.window() from bot.js instead to keep track of the window or frame40* is currently being used for command execution. The implementation is41* otherwise similar to the implementation in the Closure library42* (goog.storage.mechanism.HTML5LocalStorage).43*44* @param {Window=} opt_window The window whose storage to access;45* defaults to the main window.46* @return {!bot.storage.Storage} The wrapper Storage object.47*/48bot.storage.getLocalStorage = function(opt_window) {49var win = opt_window || bot.getWindow();5051if (!bot.html5.isSupported(bot.html5.API.LOCAL_STORAGE, win)) {52throw new bot.Error(bot.ErrorCode.UNKNOWN_ERROR, 'Local storage undefined');53}54var storageMap = win.localStorage;55return new bot.storage.Storage(storageMap);56};575859/**60* A factory method to create a wrapper to access the HTML5 sessionStorage61* object.62*63* @param {Window=} opt_window The window whose storage to access;64* defaults to the main window.65* @return {!bot.storage.Storage} The wrapper Storage object.66*/67bot.storage.getSessionStorage = function(opt_window) {68var win = opt_window || bot.getWindow();6970if (bot.html5.isSupported(bot.html5.API.SESSION_STORAGE, win)) {71var storageMap = win.sessionStorage;72return new bot.storage.Storage(storageMap);73}74throw new bot.Error(bot.ErrorCode.UNKNOWN_ERROR,75'Session storage undefined');76};77787980/**81* Provides a wrapper object to the HTML5 web storage object.82* @constructor83*84* @param {Storage} storageMap HTML5 storage object e.g. localStorage,85* sessionStorage.86*/87bot.storage.Storage = function(storageMap) {88/**89* Member variable to access the assigned HTML5 storage object.90* @private {Storage}91* @const92*/93this.storageMap_ = storageMap;94};959697/**98* Sets the value item of a key/value pair in the Storage object.99* If the value given is null, the string 'null' will be inserted100* instead.101*102* @param {string} key The key of the item.103* @param {*} value The value of the item.104*/105bot.storage.Storage.prototype.setItem = function(key, value) {106try {107// Note: Ideally, browsers should set a null value. But the browsers108// report arbitrarily. Firefox returns <null>, while Chrome reports109// the string "null". We are setting the value to the string "null".110this.storageMap_.setItem(key, value + '');111} catch (e) {112throw new bot.Error(bot.ErrorCode.UNKNOWN_ERROR, e.message);113}114};115116117/**118* Returns the value item of a key in the Storage object.119*120* @param {string} key The key of the returned value.121* @return {?string} The mapped value if present in the storage object,122* otherwise null. If a null value was inserted for a given123* key, then the string 'null' is returned.124*/125bot.storage.Storage.prototype.getItem = function(key) {126var value = this.storageMap_.getItem(key);127return /** @type {?string} */ (value);128};129130131/**132* Returns an array of keys of all keys of the Storage object.133*134* @return {!Array.<string>} The array of stored keys..135*/136bot.storage.Storage.prototype.keySet = function() {137var keys = [];138var length = this.size();139for (var i = 0; i < length; i++) {140keys[i] = this.storageMap_.key(i);141}142return keys;143};144145146/**147* Removes an item with a given key.148*149* @param {string} key The key item of the key/value pair.150* @return {?string} The removed value if present, otherwise null.151*/152bot.storage.Storage.prototype.removeItem = function(key) {153var value = this.getItem(key);154this.storageMap_.removeItem(key);155return value;156};157158159/**160* Removes all items.161*/162bot.storage.Storage.prototype.clear = function() {163this.storageMap_.clear();164};165166167/**168* Returns the number of items in the Storage object.169*170* @return {number} The number of the key/value pairs.171*/172bot.storage.Storage.prototype.size = function() {173return this.storageMap_.length;174};175176177/**178* Returns the key item of the key/value pairs in the Storage object179* of a given index.180*181* @param {number} index The index of the key/value pair list.182* @return {?string} The key item of a given index.183*/184bot.storage.Storage.prototype.key = function(index) {185return this.storageMap_.key(index);186};187188189/**190* Returns HTML5 storage object of the wrapper Storage object191*192* @return {Storage} The storageMap attribute.193*/194bot.storage.Storage.prototype.getStorageMap = function() {195return this.storageMap_;196};197198199