166a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis// Copyright (c) 2012 The Chromium Authors. All rights reserved.
266a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis// Use of this source code is governed by a BSD-style license that can be
366a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis// found in the LICENSE file.
466a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis
566a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis'use strict';
666a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis
766a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis/**
866a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis * @fileoverview Provides the Settings object.
966a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis */
1066a37686207944273ced825e0e8b6b6375f8c3deJamie Gennisbase.exportTo('base', function() {
1166a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis  var storage_ = localStorage;
1266a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis
1366a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis  /**
1466a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis   * Settings is a simple wrapper around local storage, to make it easier
1566a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis   * to test classes that have settings.
1666a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis   *
1766a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis   * May be called as new base.Settings() or simply base.Settings()
1866a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis   * @constructor
1966a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis   */
2066a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis  function Settings() {
2166a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis    return Settings;
2266a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis  };
2366a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis
2466a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis  /**
2566a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis   * Get the setting with the given name.
2666a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis   *
2766a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis   * @param {string} key The name of the setting.
2866a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis   * @param {string=} opt_default The default value to return if not set.
2966a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis   * @param {string=} opt_namespace If set, the setting name will be prefixed
3066a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis   * with this namespace, e.g. "categories.settingName". This is useful for
3166a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis   * a set of related settings.
3266a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis   */
3366a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis  Settings.get = function(key, opt_default, opt_namespace) {
3466a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis    key = Settings.namespace_(key, opt_namespace);
3566a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis    var rawVal = storage_.getItem(key);
3666a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis    if (rawVal === null || rawVal === undefined)
3766a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis      return opt_default;
3866a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis
3966a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis    // Old settings versions used to stringify objects instead of putting them
4066a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis    // into JSON. If those are encountered, parse will fail. In that case,
4166a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis    // "upgrade" the setting to the default value.
4266a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis    try {
4366a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis      return JSON.parse(rawVal).value;
4466a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis    } catch (e) {
4566a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis      storage_.removeItem(Settings.namespace_(key, opt_namespace));
4666a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis      return opt_default;
4766a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis    }
4866a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis  },
4966a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis
5066a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis  /**
5166a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis   * Set the setting with the given name to the given value.
5266a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis   *
5366a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis   * @param {string} key The name of the setting.
5466a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis   * @param {string} value The value of the setting.
5566a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis   * @param {string=} opt_namespace If set, the setting name will be prefixed
5666a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis   * with this namespace, e.g. "categories.settingName". This is useful for
5766a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis   * a set of related settings.
5866a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis   */
5966a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis  Settings.set = function(key, value, opt_namespace) {
6066a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis    if (value === undefined)
6166a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis      throw new Error('Settings.set: value must not be undefined');
6266a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis    var v = JSON.stringify({value: value});
6366a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis    storage_.setItem(Settings.namespace_(key, opt_namespace), v);
6466a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis  },
6566a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis
6666a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis  /**
6766a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis   * Return a list of all the keys, or all the keys in the given namespace
6866a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis   * if one is provided.
6966a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis   *
7066a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis   * @param {string=} opt_namespace If set, only return settings which
7166a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis   * begin with this prefix.
7266a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis   */
7366a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis  Settings.keys = function(opt_namespace) {
7466a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis    var result = [];
7566a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis    opt_namespace = opt_namespace || '';
7666a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis    for (var i = 0; i < storage_.length; i++) {
7766a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis      var key = storage_.key(i);
7866a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis      if (Settings.isnamespaced_(key, opt_namespace))
7966a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis        result.push(Settings.unnamespace_(key, opt_namespace));
8066a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis    }
8166a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis    return result;
8266a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis  },
8366a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis
8466a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis  Settings.isnamespaced_ = function(key, opt_namespace) {
8566a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis    return key.indexOf(Settings.normalize_(opt_namespace)) == 0;
8666a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis  },
8766a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis
8866a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis  Settings.namespace_ = function(key, opt_namespace) {
8966a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis    return Settings.normalize_(opt_namespace) + key;
9066a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis  },
9166a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis
9266a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis  Settings.unnamespace_ = function(key, opt_namespace) {
9366a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis    return key.replace(Settings.normalize_(opt_namespace), '');
9466a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis  },
9566a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis
9666a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis  /**
9766a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis   * All settings are prefixed with a global namespace to avoid collisions.
9866a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis   * Settings may also be namespaced with an additional prefix passed into
9966a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis   * the get, set, and keys methods in order to group related settings.
10066a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis   * This method makes sure the two namespaces are always set properly.
10166a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis   */
10266a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis  Settings.normalize_ = function(opt_namespace) {
10366a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis    return Settings.NAMESPACE + (opt_namespace ? opt_namespace + '.' : '');
10466a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis  }
10566a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis
10666a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis  Settings.setAlternativeStorageInstance = function(instance) {
10766a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis    storage_ = instance;
10866a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis  }
10966a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis  Settings.getAlternativeStorageInstance = function() {
11066a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis    if (storage_ === localStorage)
11166a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis      return undefined;
11266a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis    return storage_;
11366a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis  }
11466a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis
11566a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis  Settings.NAMESPACE = 'trace-viewer';
11666a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis
11766a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis  return {
11866a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis    Settings: Settings
11966a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis  };
12066a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis});
121