1 // This file is part of Moodle - http://moodle.org/
3 // Moodle is free software: you can redistribute it and/or modify
4 // it under the terms of the GNU General Public License as published by
5 // the Free Software Foundation, either version 3 of the License, or
6 // (at your option) any later version.
8 // Moodle is distributed in the hope that it will be useful,
9 // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 // GNU General Public License for more details.
13 // You should have received a copy of the GNU General Public License
14 // along with Moodle. If not, see <http://www.gnu.org/licenses/>.
17 * Simple API for set/get to localstorage, with cacherev expiration.
19 * @module core/localstorage
22 * @copyright 2015 Damyon Wiese <damyon@moodle.com>
23 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
26 define(['core/config'], function(config) {
28 // Private functions and variables.
29 /** @var {boolean} supported - Is localstorage supported in this browser? */
30 var supported = false;
31 /** @var {string} prefix - Prefix to use on all cache keys */
33 /** @var {jsrevPrefix} jsrevPrefix - Key to store the current jsrev version for the cache */
35 /** @var {Object} localStorage - Browsers localStorage object */
36 var localStorage = null;
39 * Check if the browser supports local storage.
41 * @method detectSupport
42 * @return {boolean} True if the browser supports local storage.
44 var detectSupport = function() {
45 if (config.jsrev == -1) {
46 // Disable cache if debugging.
49 if (typeof(window.localStorage) === "undefined") {
54 localStorage = window.localStorage;
55 if (localStorage === null) {
58 // MDL-51461 - Some browsers misreport availability of local storage
59 // so check it is actually usable.
60 localStorage.setItem(testKey, '1');
61 localStorage.removeItem(testKey);
69 * Add a unique prefix to all keys so multiple moodle sites do not share caches.
72 * @param {string} key The cache key to prefix.
73 * @return {string} The new key
75 var prefixKey = function(key) {
80 * Check the current jsrev version and clear the cache if it has been bumped.
82 * @method validateCache
84 var validateCache = function() {
85 var cacheVersion = localStorage.getItem(jsrevPrefix);
86 if (cacheVersion === null) {
87 localStorage.setItem(jsrevPrefix, config.jsrev);
90 var moodleVersion = config.jsrev;
92 if (moodleVersion != cacheVersion) {
94 localStorage.setItem(jsrevPrefix, config.jsrev);
99 * Hash a string, used to make shorter key prefixes.
102 * @param string source The string to hash
103 * @return int The int hash
105 var hashString = function(source) {
106 // From http://stackoverflow.com/questions/7616461/generate-a-hash-from-string-in-javascript-jquery.
107 /* jshint bitwise: false */
108 var hash = 0, i, chr, len;
109 if (source.length === 0) {
112 for (i = 0, len = source.length; i < len; i++) {
113 chr = source.charCodeAt(i);
114 hash = ((hash << 5) - hash) + chr;
115 hash |= 0; // Convert to 32bit integer
123 * This computes the hash prefixes from jsrev and friends.
125 var init = function() {
126 supported = detectSupport();
127 var hashSource = config.wwwroot + '/' + config.jsrev;
129 var hash = hashString(hashSource);
131 hashSource = config.wwwroot + '/';
132 hash = hashString(hashSource);
133 jsrevPrefix = hash + '/jsrev';
136 // Run the module init.
139 return /** @alias module:core/localstorage */ {
141 * Get a value from local storage. Remember - all values must be strings.
144 * @param {string} key The cache key to check.
145 * @return {boolean|string} False if the value is not in the cache, or some other error - a string otherwise.
152 key = prefixKey(key);
154 return localStorage.getItem(key);
158 * Set a value to local storage. Remember - all values must be strings.
161 * @param {string} key The cache key to set.
162 * @param {string} value The value to set.
163 * @return {boolean} False if the value can't be saved in the cache, or some other error - true otherwise.
165 set: function(key, value) {
170 key = prefixKey(key);
171 // This can throw exceptions when the storage limit is reached.
173 localStorage.setItem(key, value);