Upstream version 11.39.266.0
[platform/framework/web/crosswalk.git] / src / remoting / webapp / paired_client_manager.js
1 // Copyright 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
7  * Dialog for showing the list of clients that are paired with this host.
8  */
9
10 'use strict';
11
12 /** @suppress {duplicate} */
13 var remoting = remoting || {};
14
15 /**
16  * Extract the appropriate fields from the input parameter, if present. Use the
17  * isValid() method to determine whether or not a valid paired client instance
18  * was provided.
19  *
20  * @param {Object} pairedClient The paired client, as returned by the native
21  *     host instance.
22  * @constructor
23  */
24 remoting.PairedClient = function(pairedClient) {
25   if (!pairedClient || typeof(pairedClient) != 'object') {
26     return;
27   }
28
29   this.clientId = /** @type {string} */ (pairedClient['clientId']);
30   this.clientName = /** @type {string} */ (pairedClient['clientName']);
31   this.createdTime = /** @type {number} */ (pairedClient['createdTime']);
32
33   /** @type {Element} */
34   this.tableRow = null;
35   /** @type {Element} */
36   this.deleteButton = null;
37 };
38
39 /**
40  * Create the DOM elements representing this client in the paired client
41  * manager dialog.
42  *
43  * @param {remoting.PairedClientManager} parent The paired client manager
44  *     dialog containing this row.
45  * @param {Element} tbody The <tbody> element to which to append the row.
46  */
47 remoting.PairedClient.prototype.createDom = function(parent, tbody) {
48   this.tableRow = document.createElement('tr');
49   var td = document.createElement('td');
50   td.innerText = new Date(this.createdTime).toLocaleDateString();
51   this.tableRow.appendChild(td);
52   td = document.createElement('td');
53   td.innerText = this.clientName;
54   this.tableRow.appendChild(td);
55   td = document.createElement('td');
56   this.deleteButton = document.createElement('a');
57   this.deleteButton.href = '#';
58   this.deleteButton.innerText = chrome.i18n.getMessage(
59       /*i18n-content*/'DELETE_PAIRED_CLIENT');
60   this.deleteButton.id = 'delete-client-' + this.clientId;
61   this.deleteButton.addEventListener(
62       'click',
63       parent.deletePairedClient.bind(parent, this),
64       false);
65   td.appendChild(this.deleteButton);
66   this.tableRow.appendChild(td);
67   tbody.appendChild(this.tableRow);
68 };
69
70 /**
71  * Show or hide the "Delete" button for this row.
72  *
73  * @param {boolean} show True to show the button; false to hide it.
74  */
75 remoting.PairedClient.prototype.showButton = function(show) {
76   this.deleteButton.hidden = !show;
77 };
78
79 /**
80  * @return {boolean} True if the constructor parameter was a well-formed
81  *     paired client instance.
82  */
83 remoting.PairedClient.prototype.isValid = function() {
84   return typeof(this.clientId) == 'string' &&
85          typeof(this.clientName) == 'string' &&
86          typeof(this.createdTime) == 'number';
87 };
88
89 /**
90  * Converts a raw object to an array of PairedClient instances. Returns null if
91  * the input object is incorrectly formatted.
92  *
93  * @param {*} pairedClients The object to convert.
94  * @return {Array.<remoting.PairedClient>} The converted result.
95  */
96 remoting.PairedClient.convertToPairedClientArray = function(pairedClients) {
97   if (!(pairedClients instanceof Array)) {
98     console.error('pairedClients is not an Array:', pairedClients);
99     return null;
100   }
101
102   var result = [];
103   for (var i = 0; i < pairedClients.length; i++) {
104     var pairedClient = new remoting.PairedClient(pairedClients[i]);
105     if (!pairedClient.isValid()) {
106       console.error('pairedClient[' + i + '] has incorrect format:',
107                     /** @type {*} */(pairedClients[i]));
108       return null;
109     }
110     result.push(pairedClient);
111   }
112   return result;
113 }
114
115 /**
116  * @param {remoting.HostController} hostController
117  * @param {HTMLElement} listContainer HTML <div> to contain the list of paired
118  *     clients.
119  * @param {HTMLElement} message HTML <div> containing the message notifying
120  *     the user that clients are paired and containing the link to open the
121  *     dialog.
122  * @param {HTMLElement} deleteAllButton HTML <button> inititating the "delete
123  *     all" action.
124  * @param {HTMLElement} closeButton HTML <button> to close the dialog.
125  * @param {HTMLElement} noPairedClients HTML <div> containing a message shown
126  *     when all clients have been deleted.
127  * @param {HTMLElement} workingSpinner HTML element containing a spinner
128  *     graphic shown while a deletion is in progress.
129  * @param {HTMLElement} errorDiv HTML <div> containing an error message shown
130  *     if a delete operation fails.
131  * @constructor
132  */
133 remoting.PairedClientManager = function(hostController, listContainer, message,
134                                         deleteAllButton, closeButton,
135                                         noPairedClients, workingSpinner,
136                                         errorDiv) {
137   /**
138    * @private
139    */
140   this.hostController_ = hostController;
141   /**
142    * @private
143    */
144   this.message_ = message;
145   /**
146    * @private
147    */
148   this.deleteAllButton_ = deleteAllButton;
149   /**
150    * @private
151    */
152   this.closeButton_ = closeButton;
153   /**
154    * @private
155    */
156   this.noPairedClients_ = noPairedClients;
157   /**
158    * @private
159    */
160   this.workingSpinner_ = workingSpinner;
161   /**
162    * @private
163    */
164   this.errorDiv_ = errorDiv;
165   /**
166    * @type {Element}
167    * @private
168    */
169   this.clientRows_ = listContainer.querySelector('tbody');
170   /**
171    * @type {Array.<remoting.PairedClient>}
172    */
173   this.pairedClients_ = [];
174
175   this.deleteAllButton_.addEventListener('click',
176                                          this.deleteAll_.bind(this),
177                                          false);
178 };
179
180 /**
181  * Populate the dialog with the list of paired clients and show or hide the
182  * message as appropriate.
183  *
184  * @param {*} pairedClients The list of paired clients as returned by the
185  *     native host component.
186  * @return {void} Nothing.
187  */
188 remoting.PairedClientManager.prototype.setPairedClients =
189     function(pairedClients) {
190   // Reset table.
191   while (this.clientRows_.lastChild) {
192     this.clientRows_.removeChild(this.clientRows_.lastChild);
193   }
194
195   this.pairedClients_ =
196     remoting.PairedClient.convertToPairedClientArray(pairedClients);
197   for (var i = 0; i < this.pairedClients_.length; ++i) {
198     var client = this.pairedClients_[i];
199     client.createDom(this, this.clientRows_);
200   }
201
202   // Show or hide the "this computer has paired clients" message.
203   this.setWorking_(false)
204 };
205
206 /**
207  * Enter or leave "working" mode. This indicates to the user that a delete
208  * operation is in progress. All dialog UI is disabled until it completes.
209  *
210  * @param {boolean} working True to enter "working" mode; false to leave it.
211  * @private
212  */
213 remoting.PairedClientManager.prototype.setWorking_ = function(working) {
214   var hasPairedClients = (this.pairedClients_.length != 0);
215   for (var i = 0; i < this.pairedClients_.length; ++i) {
216     this.pairedClients_[i].showButton(!working);
217   }
218   this.closeButton_.disabled = working;
219   this.workingSpinner_.hidden = !working;
220   this.errorDiv_.hidden = true;
221   this.message_.hidden = !hasPairedClients;
222   this.deleteAllButton_.disabled = working || !hasPairedClients;
223   this.noPairedClients_.hidden = hasPairedClients;
224 };
225
226 /**
227  * Error callback for delete operations.
228  *
229  * @param {remoting.Error} error The error message.
230  * @private
231  */
232 remoting.PairedClientManager.prototype.onError_ = function(error) {
233   this.setWorking_(false);
234   l10n.localizeElementFromTag(this.errorDiv_, error);
235   this.errorDiv_.hidden = false;
236 };
237
238 /**
239  * Delete a single paired client.
240  *
241  * @param {remoting.PairedClient} client The pairing to delete.
242  */
243 remoting.PairedClientManager.prototype.deletePairedClient = function(client) {
244   this.setWorking_(true);
245   this.hostController_.deletePairedClient(client.clientId,
246       this.setWorking_.bind(this, false),
247       this.onError_.bind(this));
248   this.clientRows_.removeChild(client.tableRow);
249   for (var i = 0; i < this.pairedClients_.length; ++i) {
250     if (this.pairedClients_[i] == client) {
251       this.pairedClients_.splice(i, 1);
252       break;
253     }
254   }
255 };
256
257 /**
258  * Delete all paired clients.
259  *
260  * @private
261  */
262 remoting.PairedClientManager.prototype.deleteAll_ = function() {
263   this.setWorking_(true);
264   this.hostController_.clearPairedClients(
265       this.setWorking_.bind(this, false),
266       this.onError_.bind(this));
267
268   while (this.clientRows_.lastChild) {
269     this.clientRows_.removeChild(this.clientRows_.lastChild);
270   }
271   this.pairedClients_ = [];
272 };
273
274 /**
275  * Get the id of the first paired client for testing.
276  *
277  * @private
278  * @return {string} The client id of the first paired client in the list.
279  */
280 remoting.PairedClientManager.prototype.getFirstClientIdForTesting_ =
281     function() {
282   return this.pairedClients_.length > 0 ? this.pairedClients_[0].clientId : '';
283 };
284
285
286 /** @type {remoting.PairedClientManager} */
287 remoting.pairedClientManager = null;