| <!DOCTYPE html> |
| <!-- |
| Copyright (c) 2014 The Chromium Authors. All rights reserved. |
| Use of this source code is governed by a BSD-style license that can be |
| found in the LICENSE file. |
| --> |
| <link rel="import" href="/tracing/base/base.html"> |
| <script> |
| 'use strict'; |
| |
| /** |
| * @fileoverview Provides the Settings object. |
| */ |
| tr.exportTo('tr.b', function() { |
| /** |
| * Settings is a simple wrapper around local storage, to make it easier |
| * to test classes that have settings. |
| * |
| * May be called as new tr.b.Settings() or simply tr.b.Settings() |
| * @constructor |
| */ |
| function Settings() { |
| return Settings; |
| }; |
| |
| if (tr.b.unittest && tr.b.unittest.TestRunner) { |
| tr.b.unittest.TestRunner.addEventListener( |
| 'tr-unittest-will-run', |
| function() { |
| if (tr.isHeadless) |
| Settings.setAlternativeStorageInstance(new HeadlessStorage()); |
| else |
| Settings.setAlternativeStorageInstance(global.sessionStorage); |
| }); |
| } |
| |
| function SessionSettings() { |
| return SessionSettings; |
| } |
| |
| function AddStaticStorageFunctionsToClass_(input_class, storage) { |
| input_class.storage_ = storage; |
| |
| /** |
| * Get the setting with the given name. |
| * |
| * @param {string} key The name of the setting. |
| * @param {string=} opt_default The default value to return if not set. |
| * @param {string=} opt_namespace If set, the setting name will be prefixed |
| * with this namespace, e.g. "categories.settingName". This is useful for |
| * a set of related settings. |
| */ |
| input_class.get = function(key, opt_default, opt_namespace) { |
| key = input_class.namespace_(key, opt_namespace); |
| var rawVal = input_class.storage_.getItem(key); |
| if (rawVal === null || rawVal === undefined) |
| return opt_default; |
| |
| // Old settings versions used to stringify objects instead of putting them |
| // into JSON. If those are encountered, parse will fail. In that case, |
| // "upgrade" the setting to the default value. |
| try { |
| return JSON.parse(rawVal).value; |
| } catch (e) { |
| input_class.storage_.removeItem(key); |
| return opt_default; |
| } |
| }; |
| |
| /** |
| * Set the setting with the given name to the given value. |
| * |
| * @param {string} key The name of the setting. |
| * @param {string} value The value of the setting. |
| * @param {string=} opt_namespace If set, the setting name will be prefixed |
| * with this namespace, e.g. "categories.settingName". This is useful for |
| * a set of related settings. |
| */ |
| input_class.set = function(key, value, opt_namespace) { |
| if (value === undefined) |
| throw new Error('Settings.set: value must not be undefined'); |
| var v = JSON.stringify({value: value}); |
| input_class.storage_.setItem( |
| input_class.namespace_(key, opt_namespace), v); |
| }; |
| |
| /** |
| * Return a list of all the keys, or all the keys in the given namespace |
| * if one is provided. |
| * |
| * @param {string=} opt_namespace If set, only return settings which |
| * begin with this prefix. |
| */ |
| input_class.keys = function(opt_namespace) { |
| var result = []; |
| opt_namespace = opt_namespace || ''; |
| for (var i = 0; i < input_class.storage_.length; i++) { |
| var key = input_class.storage_.key(i); |
| if (input_class.isnamespaced_(key, opt_namespace)) |
| result.push(input_class.unnamespace_(key, opt_namespace)); |
| } |
| return result; |
| }; |
| |
| input_class.isnamespaced_ = function(key, opt_namespace) { |
| return key.indexOf(input_class.normalize_(opt_namespace)) == 0; |
| }; |
| |
| input_class.namespace_ = function(key, opt_namespace) { |
| return input_class.normalize_(opt_namespace) + key; |
| }; |
| |
| input_class.unnamespace_ = function(key, opt_namespace) { |
| return key.replace(input_class.normalize_(opt_namespace), ''); |
| }; |
| |
| /** |
| * All settings are prefixed with a global namespace to avoid collisions. |
| * input_class may also be namespaced with an additional prefix passed into |
| * the get, set, and keys methods in order to group related settings. |
| * This method makes sure the two namespaces are always set properly. |
| */ |
| input_class.normalize_ = function(opt_namespace) { |
| return input_class.NAMESPACE + (opt_namespace ? opt_namespace + '.' : ''); |
| }; |
| |
| input_class.setAlternativeStorageInstance = function(instance) { |
| input_class.storage_ = instance; |
| }; |
| |
| input_class.getAlternativeStorageInstance = function() { |
| if (!tr.isHeadless && input_class.storage_ === localStorage) |
| return undefined; |
| return input_class.storage_; |
| }; |
| |
| input_class.NAMESPACE = 'trace-viewer'; |
| }; |
| |
| function HeadlessStorage() { |
| this.length = 0; |
| this.hasItem_ = {}; |
| this.items_ = {}; |
| this.itemsAsArray_ = undefined; |
| } |
| HeadlessStorage.prototype = { |
| key: function(index) { |
| return this.itemsAsArray[index]; |
| }, |
| |
| get itemsAsArray() { |
| if (this.itemsAsArray_ !== undefined) |
| return this.itemsAsArray_; |
| var itemsAsArray = []; |
| for (var k in this.items_) |
| itemsAsArray.push(k); |
| this.itemsAsArray_ = itemsAsArray; |
| return this.itemsAsArray_; |
| }, |
| |
| getItem: function(key) { |
| if (!this.hasItem_[key]) |
| return null; |
| return this.items_[key]; |
| }, |
| |
| removeItem: function(key) { |
| if (!this.hasItem_[key]) |
| return; |
| var value = this.items_[key]; |
| delete this.hasItem_[key]; |
| delete this.items_[key]; |
| this.length--; |
| this.itemsAsArray_ = undefined; |
| return value; |
| }, |
| |
| setItem: function(key, value) { |
| if (this.hasItem_[key]) { |
| this.items_[key] = value; |
| return; |
| } |
| this.items_[key] = value; |
| this.hasItem_[key] = true; |
| this.length++; |
| this.itemsAsArray_ = undefined; |
| return value; |
| } |
| }; |
| |
| if (tr.isHeadless) { |
| AddStaticStorageFunctionsToClass_(Settings, new HeadlessStorage()); |
| AddStaticStorageFunctionsToClass_(SessionSettings, new HeadlessStorage()); |
| } else { |
| AddStaticStorageFunctionsToClass_(Settings, localStorage); |
| AddStaticStorageFunctionsToClass_(SessionSettings, sessionStorage); |
| } |
| |
| return { |
| Settings: Settings, |
| SessionSettings: SessionSettings |
| }; |
| }); |
| </script> |