1// Copyright 2014 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
5cr.define('options', function() {
6  /**
7   * SupervisedUserListData class.
8   * Handles requests for retrieving a list of existing supervised users which
9   * are supervised by the current profile. For each request a promise is
10   * returned, which is cached in order to reuse the retrieved supervised users
11   * for future requests. The first request will be handled asynchronously.
12   * @constructor
13   * @class
14   */
15  function SupervisedUserListData() {
16    this.observers_ = [];
17  };
18
19  cr.addSingletonGetter(SupervisedUserListData);
20
21  /**
22   * Receives a list of supervised users and resolves the promise.
23   * @param {Array.<Object>} supervisedUsers Array of supervised user objects.
24   *     Each object is of the form:
25   *       supervisedUser = {
26   *         id: "Supervised User ID",
27   *         name: "Supervised User Name",
28   *         iconURL: "chrome://path/to/icon/image",
29   *         onCurrentDevice: true or false,
30   *         needAvatar: true or false
31   *       }
32   * @private
33   */
34  SupervisedUserListData.prototype.receiveExistingSupervisedUsers_ =
35      function(supervisedUsers) {
36    if (!this.promise_) {
37      this.onDataChanged_(supervisedUsers);
38      return;
39    }
40    this.resolve_(supervisedUsers);
41  };
42
43  /**
44   * Called when there is a signin error when retrieving the list of supervised
45   * users. Rejects the promise and resets the cached promise to null.
46   * @private
47   */
48  SupervisedUserListData.prototype.onSigninError_ = function() {
49    if (!this.promise_) {
50      return;
51    }
52    this.reject_();
53    this.resetPromise_();
54  };
55
56  /**
57   * Handles the request for the list of existing supervised users by returning
58   * a promise for the requested data. If there is no cached promise yet, a new
59   * one will be created.
60   * @return {Promise} The promise containing the list of supervised users.
61   * @private
62   */
63  SupervisedUserListData.prototype.requestExistingSupervisedUsers_ =
64      function() {
65    if (this.promise_)
66      return this.promise_;
67    this.promise_ = this.createPromise_();
68    chrome.send('requestSupervisedUserImportUpdate');
69    return this.promise_;
70  };
71
72  /**
73   * Creates the promise containing the list of supervised users. The promise is
74   * resolved in receiveExistingSupervisedUsers_() or rejected in
75   * onSigninError_(). The promise is cached, so that for future requests it can
76   * be resolved immediately.
77   * @return {Promise} The promise containing the list of supervised users.
78   * @private
79   */
80  SupervisedUserListData.prototype.createPromise_ = function() {
81    var self = this;
82    return new Promise(function(resolve, reject) {
83      self.resolve_ = resolve;
84      self.reject_ = reject;
85    });
86  };
87
88  /**
89   * Resets the promise to null in order to avoid stale data. For the next
90   * request, a new promise will be created.
91   * @private
92   */
93  SupervisedUserListData.prototype.resetPromise_ = function() {
94    this.promise_ = null;
95  };
96
97  /**
98   * Initializes |promise| with the new data and also passes the new data to
99   * observers.
100   * @param {Array.<Object>} supervisedUsers Array of supervised user objects.
101   *     For the format of the objects, see receiveExistingSupervisedUsers_().
102   * @private
103   */
104  SupervisedUserListData.prototype.onDataChanged_ = function(supervisedUsers) {
105    this.promise_ = this.createPromise_();
106    this.resolve_(supervisedUsers);
107    for (var i = 0; i < this.observers_.length; ++i)
108      this.observers_[i].receiveExistingSupervisedUsers_(supervisedUsers);
109  };
110
111  /**
112   * Adds an observer to the list of observers.
113   * @param {Object} observer The observer to be added.
114   * @private
115   */
116  SupervisedUserListData.prototype.addObserver_ = function(observer) {
117    for (var i = 0; i < this.observers_.length; ++i)
118      assert(this.observers_[i] != observer);
119    this.observers_.push(observer);
120  };
121
122  /**
123   * Removes an observer from the list of observers.
124   * @param {Object} observer The observer to be removed.
125   * @private
126   */
127  SupervisedUserListData.prototype.removeObserver_ = function(observer) {
128    for (var i = 0; i < this.observers_.length; ++i) {
129      if (this.observers_[i] == observer) {
130        this.observers_.splice(i, 1);
131        return;
132      }
133    }
134  };
135
136  // Forward public APIs to private implementations.
137  cr.makePublic(SupervisedUserListData, [
138    'addObserver',
139    'onSigninError',
140    'receiveExistingSupervisedUsers',
141    'removeObserver',
142    'requestExistingSupervisedUsers',
143    'resetPromise',
144  ]);
145
146  // Export
147  return {
148    SupervisedUserListData: SupervisedUserListData,
149  };
150});
151