1<!DOCTYPE html>
2<!--
3Copyright (c) 2013 The Chromium Authors. All rights reserved.
4Use of this source code is governed by a BSD-style license that can be
5found in the LICENSE file.
6-->
7<link rel="import" href="/tracing/base/settings.html">
8
9<script>
10'use strict';
11
12tr.exportTo('tr.model', function() {
13  var Settings = tr.b.Settings;
14
15  /**
16   * A way to persist settings specific to parts of a trace model.
17   *
18   * This object should not be persisted because it builds up internal data
19   * structures that map model objects to settings keys. It should thus be
20   * created for the duration of whatever interaction(s) you're going to do with
21   * model settings, and then discarded.
22   *
23   * This system works on a notion of an object key: for an object's key, it
24   * considers all the other keys in the model. If it is unique, then the key is
25   * persisted to tr.b.Settings. However, if it is not unique, then the
26   * setting is stored on the object itself. Thus, objects with unique keys will
27   * be persisted across page reloads, whereas objects with nonunique keys will
28   * not.
29   */
30  function ModelSettings(model) {
31    this.model = model;
32    this.objectsByKey_ = [];
33    this.nonuniqueKeys_ = [];
34    this.buildObjectsByKeyMap_();
35    this.removeNonuniqueKeysFromSettings_();
36    this.ephemeralSettingsByGUID_ = {};
37  }
38
39  ModelSettings.prototype = {
40    buildObjectsByKeyMap_: function() {
41      var objects = [];
42      this.model.iterateAllPersistableObjects(function(o) {
43        objects.push(o);
44      });
45
46      var objectsByKey = {};
47      var NONUNIQUE_KEY = 'nonuniqueKey';
48      for (var i = 0; i < objects.length; i++) {
49        var object = objects[i];
50        var objectKey = object.getSettingsKey();
51        if (!objectKey)
52          continue;
53        if (objectsByKey[objectKey] === undefined) {
54          objectsByKey[objectKey] = object;
55          continue;
56        }
57        objectsByKey[objectKey] = NONUNIQUE_KEY;
58      }
59
60      var nonuniqueKeys = {};
61      tr.b.dictionaryKeys(objectsByKey).forEach(function(objectKey) {
62        if (objectsByKey[objectKey] !== NONUNIQUE_KEY)
63          return;
64        delete objectsByKey[objectKey];
65        nonuniqueKeys[objectKey] = true;
66      });
67
68      this.nonuniqueKeys = nonuniqueKeys;
69      this.objectsByKey_ = objectsByKey;
70    },
71
72    removeNonuniqueKeysFromSettings_: function() {
73      var settings = Settings.get('trace_model_settings', {});
74      var settingsChanged = false;
75      tr.b.dictionaryKeys(settings).forEach(function(objectKey) {
76        if (!this.nonuniqueKeys[objectKey])
77          return;
78        settingsChanged = true;
79        delete settings[objectKey];
80      }, this);
81      if (settingsChanged)
82        Settings.set('trace_model_settings', settings);
83    },
84
85    hasUniqueSettingKey: function(object) {
86      var objectKey = object.getSettingsKey();
87      if (!objectKey)
88        return false;
89      return this.objectsByKey_[objectKey] !== undefined;
90    },
91
92    getSettingFor: function(object, objectLevelKey, defaultValue) {
93      var objectKey = object.getSettingsKey();
94      if (!objectKey || !this.objectsByKey_[objectKey]) {
95        var settings = this.getEphemeralSettingsFor_(object);
96        var ephemeralValue = settings[objectLevelKey];
97        if (ephemeralValue !== undefined)
98          return ephemeralValue;
99        return defaultValue;
100      }
101
102      var settings = Settings.get('trace_model_settings', {});
103      if (!settings[objectKey])
104        settings[objectKey] = {};
105      var value = settings[objectKey][objectLevelKey];
106      if (value !== undefined)
107        return value;
108      return defaultValue;
109    },
110
111    setSettingFor: function(object, objectLevelKey, value) {
112      var objectKey = object.getSettingsKey();
113      if (!objectKey || !this.objectsByKey_[objectKey]) {
114        this.getEphemeralSettingsFor_(object)[objectLevelKey] = value;
115        return;
116      }
117
118      var settings = Settings.get('trace_model_settings', {});
119      if (!settings[objectKey])
120        settings[objectKey] = {};
121      if (settings[objectKey][objectLevelKey] === value)
122        return;
123      settings[objectKey][objectLevelKey] = value;
124      Settings.set('trace_model_settings', settings);
125    },
126
127    getEphemeralSettingsFor_: function(object) {
128      if (object.guid === undefined)
129        throw new Error('Only objects with GUIDs can be persisted');
130      if (this.ephemeralSettingsByGUID_[object.guid] === undefined)
131        this.ephemeralSettingsByGUID_[object.guid] = {};
132      return this.ephemeralSettingsByGUID_[object.guid];
133    }
134  };
135
136  return {
137    ModelSettings: ModelSettings
138  };
139});
140</script>
141