diff options
Diffstat (limited to 'src/js/fiveui/js/settings.js')
-rw-r--r-- | src/js/fiveui/js/settings.js | 389 |
1 files changed, 389 insertions, 0 deletions
diff --git a/src/js/fiveui/js/settings.js b/src/js/fiveui/js/settings.js new file mode 100644 index 0000000..a17a9e0 --- /dev/null +++ b/src/js/fiveui/js/settings.js @@ -0,0 +1,389 @@ +/* + * Module : settings.js + * Copyright : (c) 2011-2012, Galois, Inc. + * + * Maintainer : + * Stability : Provisional + * Portability: Portable + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +var fiveui = fiveui || {}; + +(function() { + +/** + * Create a new instance of the Settings object + * + * @constructor + * @param {!Storage} store The Storage instance to use. + */ +fiveui.Settings = function(store) { + this.store = store; +}; + +_.extend(fiveui.Settings.prototype, { + + /** + * Retrieve an object associated with the key. + * + * @param {!string} key The key to look up. + * @return {?Object} The returned JavaScript object. + */ + get: function(key) { + var value = this.store.getItem(key); + if (value == null) { + return null; + } else { + return JSON.parse(value); + } + }, + + /** + * Store an object with the given key. + * + * @param {string} key the key. + * @param {Object} value the value. + * @return {void} + */ + set: function(key, value) { + this.store.setItem(key, JSON.stringify(value)); + }, + + /** + * @param {string} key The local storage entry to remove. + * @return {void} + */ + remove: function(key) { + this.store.removeItem(key); + }, + + /** + * Set the display default. + * + * @param {!boolean} def Whether or not to display the FiveUI Window + * when problems are reported. + */ + setDisplayDefault: function(def) { + this.set('displayDefault', def); + }, + + /** + * Get the display default. + * + * @return {!boolean} true to show the window as soon as problems are + * reported, false otherwise. + */ + getDisplayDefault: function() { + var def = this.get('displayDefault'); + + // double negation to normalize funny things like null + return !!def; + }, + + /** + * Add a mapping from url patterns to RuleSets (via rule set ids) + * + * @param {!string} url_pat A regular expression (actually, a glob) to match URLs against. + * @param {!number} rule_id The id of the RuleSet to use with any matching URL. + * @return {!number} The id of the new url pattern. + */ + addUrl: function(url_pat, rule_id) { + var pats = this.getUrls(); + + var new_id = fiveui.utils.getNewId(pats); + + this.updateUrl(new_id, url_pat, rule_id); + + // add it to the patterns list + pats.push(new_id); + this.set('urls', pats); + + return new_id; + }, + + updateUrl: function(id, url_pat, rule_id) { + this.set('urls.' + id, new fiveui.UrlPat(id, url_pat, rule_id)); + return id; + }, + + /** + * Retrieve the list of url patterns. + * + * @return {Array.<number>} An ordered list of the currently active + * url patterns. + */ + getUrls: function() { + return (/** @type {Array.<number>} */ this.get('urls')) || []; + }, + + /** + * Retrieve a specific url pattern. + * + * @param {!number} url_id The id of the url pattern to retrieve. + * @return {?fiveui.UrlPat} The matching UrlPat or null, + * if no pattern exists for url_id. + */ + getUrlPat: function(url_id) { + return /** @type {?fiveui.UrlPat} */ this.getById(url_id, 'urls', fiveui.UrlPat.fromJSON); + }, + + /** + * Remove a UrlPat from the persistent storage. + * + * @param {!number} pat_id The id of the UrlPat to remove. + * @return {void} + */ + remUrlPat: function(pat_id) { + this.remById(pat_id, 'urls'); + }, + + /** + * @param {!string} url A url to compare against the list of ordered + * url patterns in local storage. + * @return {?fiveui.UrlPat} The matching pattern, or null, if no + * mapping was found. + */ + checkUrl: function(url) { + var pats = this.getUrls(); + + // check for a possible match + for (var i = 0; i < pats.length; ++i) { + var pat = this.getUrlPat(pats[i]); + if (pat.match(url)) { + return pat; + } + } + + return null; + }, + + /** + * Retrieve the list of rule sets. + * + * @return {!Array.<number>} An ordered list of the configured rule sets. + */ + getRuleSets: function() { + return (/** @type {!Array.<number>} */ this.get('ruleSet')) || []; + }, + + + /** + * @param {!Object} ruleSet The new rule set, as an anonymous JSON object. + * @return {!fiveui.RuleSet} The new RuleSet object. + */ + addRuleSet: function(ruleSet) { + var ids = this.getRuleSets(); + var id = fiveui.utils.getNewId(ids); + + var newRS = this.updateRuleSet(id, ruleSet); + ids.push(id); + this.set('ruleSet', ids); + + return newRS; + }, + + /** + * Change a rule set without generating a new id. + * + * @param {!number} ruleSetId The id of the ruleset that is being modified. + * @param {!Object} ruleSet The rule set, as an anonymous JSON object. + * @return {!fiveui.RuleSet} The new RuleSet object. + */ + updateRuleSet: function(ruleSetId, ruleSet) { + var newRS = fiveui.RuleSet.fromJSON(ruleSetId, ruleSet); + this.set('ruleSet.'+ruleSetId, newRS); + return newRS; + }, + + /** + * @param {!number} id The id of the RuleSet to retrieve. + * @return {?fiveui.RuleSet} The RuleSet, or null, if no RuleSet was found. + */ + getRuleSet: function(id) { + return /** @type {?fiveui.RuleSet} */ this.getById(id, 'ruleSet', fiveui.RuleSet.fromJSON); + }, + + /** + * @param {!number} id The id of the rule set to remove. + * @return {!Array.<fiveui.UrlPat>} null if the remove succeeded, otherwise, + * returns the list of UrlPats that use this + * rule set, if any. + */ + remRuleSet: function(id) { + var matches = _.map(this.getRuleSetUrlPats(id), function(id) { + return this.getUrlPat(id); + }, this); + + if (0 == matches.length) { + this.remById(id, 'ruleSet'); + } + + return matches; + }, + + /** + * @param {!number} ruleSetId The rule set to retrieve url patterns for. + * @return {Array.<number>} Url pattern ids associated with this rule set. + */ + getRuleSetUrlPats: function(ruleSetId) { + var urls = this.getUrls(); + var patIds = []; + + _.each(urls, function(patId) { + var pat = this.getUrlPat(patId); + if(pat.rule_id == ruleSetId) { + patIds.push(patId); + } + }, this); + + return patIds; + }, + + /** + * @param {!number} id The nuber of the element to retrieve. + * @param {!string} listName The name of the portion of the localstorage hierarchy to search for id. + * @param {!function(number, !Object): *} fromJSON A deserialization function. + * + * @return {*} Either null, or the result of fromJSON. + */ + getById: function(id, listName, fromJSON) { + var obj = this.get(listName + '.' + id); + if (!obj) { + return null; + } + + return fromJSON(id, obj); + }, + + /** + * @param {!number} id The nuber of the element to retrieve. + * @param {!string} listName The name of the portion of the + * localstorage hierarchy to search for id. + */ + remById: function(id, listName) { + // remove it from the list of ids: + var ids = this.get(listName) || []; + + for (var i = 0; i < ids.length; ++i) { + if (ids[i] == id) { + ids.splice(i, 1); + this.set(listName, ids); + this.remove(listName + '.' + id); + break; + } + } + } +}); + + +/** + * @param {!fiveui.Chan} chan + * @param {!fiveui.Settings} settings + * @return {void} + */ +fiveui.Settings.manager = function(chan, settings) { + + var msg = new fiveui.Messenger(chan); + + msg.register('addRuleSet', function(ruleSet,respond){ + var newRS = settings.addRuleSet(ruleSet); + respond(newRS); + }); + + msg.register('updateRuleSet', function(updatedRS,respond){ + var newRS = settings.updateRuleSet(updatedRS.id, updatedRS); + respond(newRS); + }); + + msg.register('remRuleSet', function(ruleSetId, respond) { + var pats = settings.remRuleSet(ruleSetId); + respond({ + id: ruleSetId, + pats: pats, + removed: pats.length == 0 + }); + }); + + msg.register('getRuleSetUrlPats', function(ruleSetId, respond) { + var pats = settings.getUrls(); + var patIds = []; + + _.each(pats, function(patId) { + var pat = settings.getUrlPat(patId); + if(pat.rule_id == ruleSetId) { + patIds.push(patId); + } + }); + + respond(patIds); + }); + + // Retrieve the manifest, and return the object to the caller. Invokes the + // caller with `null` when the manifest fails to load. + msg.register('loadRuleSet', function(url, respond) { + fiveui.RuleSet.load(url, { + success:respond, + + error:function(msg) { + respond({ error : msg }); + }, + }); + }); + + msg.register('getRuleSet', function(ruleSetId, respond){ + respond(settings.getRuleSet(ruleSetId)); + }); + + msg.register('getRuleSets', function(unused, respond) { + var ruleSets = _.map(settings.getRuleSets(), + _.bind(settings.getRuleSet, settings)); + respond(ruleSets); + }); + + msg.register('getUrlPats', function(unused, respond){ + respond(_.map(settings.getUrls(), _.bind(settings.getUrlPat, settings))); + }); + + msg.register('addUrlPat', function(url, respond){ + var urlId = settings.addUrl(url.regex, url.rule_id); + respond(settings.getUrlPat(urlId)); + }); + + msg.register('updateUrlPat', function(pat, respond) { + var obj = settings.getUrlPat(pat.id); + settings.updateUrl(pat.id, pat.regex, pat.rule_id); + respond(pat); + }); + + msg.register('getUrlPat', function(urlPatId, respond){ + respond(settings.getUrlPat(urlPatId)); + }); + + msg.register('remUrlPat', function(urlPatId, respond){ + settings.remUrlPat(urlPatId); + respond(true); + }); + + msg.register('setDisplayDefault', function(def) { + settings.setDisplayDefault(def); + }); + + msg.register('getDisplayDefault', function(ignored, respond) { + respond(settings.getDisplayDefault()); + }); + +}; + +})(); |