MDL-52127 js: check amd files with eslint grunt task
[moodle.git] / lib / amd / src / localstorage.js
1 // This file is part of Moodle - http://moodle.org/
2 //
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.
7 //
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.
12 //
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/>.
16 /**
17  * Simple API for set/get to localstorage, with cacherev expiration.
18  *
19  * @module     core/localstorage
20  * @package    core
21  * @class      localstorage
22  * @copyright  2015 Damyon Wiese <damyon@moodle.com>
23  * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
24  * @since      2.9
25  */
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 */
32     var prefix = '';
33     /** @var {jsrevPrefix} jsrevPrefix - Key to store the current jsrev version for the cache */
34     var jsrevPrefix = '';
35     /** @var {Object} localStorage - Browsers localStorage object */
36     var localStorage = null;
38     /**
39      * Check if the browser supports local storage.
40      *
41      * @method detectSupport
42      * @return {boolean} True if the browser supports local storage.
43      */
44     var detectSupport = function() {
45         if (config.jsrev == -1) {
46             // Disable cache if debugging.
47             return false;
48         }
49         if (typeof(window.localStorage) === "undefined") {
50             return false;
51         }
52         var testKey = 'test';
53         try {
54             localStorage = window.localStorage;
55             if (localStorage === null) {
56                 return false;
57             }
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);
62             return true;
63         } catch (ex) {
64             return false;
65         }
66     };
68     /**
69      * Add a unique prefix to all keys so multiple moodle sites do not share caches.
70      *
71      * @method prefixKey
72      * @param {string} key The cache key to prefix.
73      * @return {string} The new key
74      */
75     var prefixKey = function(key) {
76         return prefix + key;
77     };
79     /**
80      * Check the current jsrev version and clear the cache if it has been bumped.
81      *
82      * @method validateCache
83      */
84     var validateCache = function() {
85         var cacheVersion = localStorage.getItem(jsrevPrefix);
86         if (cacheVersion === null) {
87             localStorage.setItem(jsrevPrefix, config.jsrev);
88             return;
89         }
90         var moodleVersion = config.jsrev;
92         if (moodleVersion != cacheVersion) {
93             localStorage.clear();
94             localStorage.setItem(jsrevPrefix, config.jsrev);
95         }
96     };
98     /**
99      * Hash a string, used to make shorter key prefixes.
100      *
101      * @method hashString
102      * @param string source The string to hash
103      * @return int The int hash
104      */
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         /* eslint no-bitwise: "off" */
109         var hash = 0, i, chr, len;
110         if (source.length === 0) {
111             return hash;
112         }
113         for (i = 0, len = source.length; i < len; i++) {
114             chr   = source.charCodeAt(i);
115             hash  = ((hash << 5) - hash) + chr;
116             hash |= 0; // Convert to 32bit integer
117         }
118         return hash;
119     };
121     /**
122      * Init this module.
123      *
124      * This computes the hash prefixes from jsrev and friends.
125      */
126     var init = function() {
127         supported = detectSupport();
128         var hashSource = config.wwwroot + '/' + config.jsrev;
130         var hash = hashString(hashSource);
131         prefix = hash + '/';
132         hashSource = config.wwwroot + '/';
133         hash = hashString(hashSource);
134         jsrevPrefix = hash + '/jsrev';
135     };
137     // Run the module init.
138     init();
140     return /** @alias module:core/localstorage */ {
141         /**
142          * Get a value from local storage. Remember - all values must be strings.
143          *
144          * @method get
145          * @param {string} key The cache key to check.
146          * @return {boolean|string} False if the value is not in the cache, or some other error - a string otherwise.
147          */
148         get: function(key) {
149             if (!supported) {
150                 return false;
151             }
152             validateCache();
153             key = prefixKey(key);
155             return localStorage.getItem(key);
156         },
158         /**
159          * Set a value to local storage. Remember - all values must be strings.
160          *
161          * @method set
162          * @param {string} key The cache key to set.
163          * @param {string} value The value to set.
164          * @return {boolean} False if the value can't be saved in the cache, or some other error - true otherwise.
165          */
166         set: function(key, value) {
167             if (!supported) {
168                 return false;
169             }
170             validateCache();
171             key = prefixKey(key);
172             // This can throw exceptions when the storage limit is reached.
173             try {
174                 localStorage.setItem(key, value);
175             } catch (e) {
176                 return false;
177             }
178             return true;
179         }
181     };
182 });