1// Copyright (c) 2013 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5/**
6 * @fileoverview Implementation of ScreenContext class: key-value storage for
7 * values that are shared between C++ and JS sides.
8 */
9cr.define('login', function() {
10  function require(condition, message) {
11    if (!condition) {
12      throw Error(message);
13    }
14  }
15
16  function checkKeyIsValid(key) {
17    var keyType = typeof key;
18    require(keyType === 'string', 'Invalid type of key: "' + keyType + '".');
19  }
20
21  function checkValueIsValid(value) {
22    var valueType = typeof value;
23    require(['string', 'boolean', 'number'].indexOf(valueType) != -1,
24        'Invalid type of value: "' + valueType + '".');
25  }
26
27  function ScreenContext() {
28    this.storage_ = {};
29    this.changes_ = {};
30  }
31
32  ScreenContext.prototype = {
33    /**
34     * Returns stored value for |key| or |defaultValue| if key not found in
35     * storage. Throws Error if key not found and |defaultValue| omitted.
36     */
37    get: function(key, defaultValue) {
38      checkKeyIsValid(key);
39      if (this.hasKey(key)) {
40        return this.storage_[key];
41      } else if (typeof defaultValue !== 'undefined') {
42        return defaultValue;
43      } else {
44        throw Error('Key "' + key + '" not found.');
45      }
46    },
47
48    /**
49     * Sets |value| for |key|. Returns true if call changes state of context,
50     * false otherwise.
51     */
52    set: function(key, value) {
53      checkKeyIsValid(key);
54      checkValueIsValid(value);
55      if (this.hasKey(key) && this.storage_[key] === value)
56        return false;
57      this.changes_[key] = value;
58      this.storage_[key] = value;
59      return true;
60    },
61
62    hasKey: function(key) {
63      checkKeyIsValid(key);
64      return this.storage_.hasOwnProperty(key);
65    },
66
67    hasChanges: function() {
68      return Object.keys(this.changes_).length > 0;
69    },
70
71    /**
72     * Applies |changes| to context. Returns Array of changed keys' names.
73     */
74    applyChanges: function(changes) {
75      require(!this.hasChanges(), 'Context has changes.');
76      Object.keys(changes).forEach(function(key) {
77        checkKeyIsValid(key);
78        checkValueIsValid(changes[key]);
79        this.storage_[key] = changes[key];
80      }, this);
81      return Object.keys(changes);
82    },
83
84    /**
85     * Returns changes made on context since previous call.
86     */
87    getChangesAndReset: function() {
88      var result = this.changes_;
89      this.changes_ = {};
90      return result;
91    }
92  };
93
94  return {
95    ScreenContext: ScreenContext
96  };
97});
98