| // Copyright 2013 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| /** |
| * @fileoverview |
| * Dialog for showing the list of clients that are paired with this host. |
| */ |
| |
| 'use strict'; |
| |
| /** @suppress {duplicate} */ |
| var remoting = remoting || {}; |
| |
| /** |
| * Extract the appropriate fields from the input parameter, if present. Use the |
| * isValid() method to determine whether or not a valid paired client instance |
| * was provided. |
| * |
| * @param {Object} pairedClient The paired client, as returned by the native |
| * host instance. |
| * @constructor |
| */ |
| remoting.PairedClient = function(pairedClient) { |
| if (!pairedClient || typeof(pairedClient) != 'object') { |
| return; |
| } |
| |
| this.clientId = /** @type {string} */ (pairedClient['clientId']); |
| this.clientName = /** @type {string} */ (pairedClient['clientName']); |
| this.createdTime = /** @type {number} */ (pairedClient['createdTime']); |
| |
| /** @type {Element} */ |
| this.tableRow = null; |
| /** @type {Element} */ |
| this.deleteButton = null; |
| }; |
| |
| /** |
| * Create the DOM elements representing this client in the paired client |
| * manager dialog. |
| * |
| * @param {remoting.PairedClientManager} parent The paired client manager |
| * dialog containing this row. |
| * @param {Element} tbody The <tbody> element to which to append the row. |
| */ |
| remoting.PairedClient.prototype.createDom = function(parent, tbody) { |
| this.tableRow = document.createElement('tr'); |
| var td = document.createElement('td'); |
| td.innerText = new Date(this.createdTime).toLocaleDateString(); |
| this.tableRow.appendChild(td); |
| td = document.createElement('td'); |
| td.innerText = this.clientName; |
| this.tableRow.appendChild(td); |
| td = document.createElement('td'); |
| this.deleteButton = document.createElement('a'); |
| this.deleteButton.href = '#'; |
| this.deleteButton.innerText = chrome.i18n.getMessage( |
| /*i18n-content*/'DELETE_PAIRED_CLIENT'); |
| this.deleteButton.id = 'delete-client-' + this.clientId; |
| this.deleteButton.addEventListener( |
| 'click', |
| parent.deletePairedClient.bind(parent, this), |
| false); |
| td.appendChild(this.deleteButton); |
| this.tableRow.appendChild(td); |
| tbody.appendChild(this.tableRow); |
| }; |
| |
| /** |
| * Show or hide the "Delete" button for this row. |
| * |
| * @param {boolean} show True to show the button; false to hide it. |
| */ |
| remoting.PairedClient.prototype.showButton = function(show) { |
| this.deleteButton.hidden = !show; |
| }; |
| |
| /** |
| * @return {boolean} True if the constructor parameter was a well-formed |
| * paired client instance. |
| */ |
| remoting.PairedClient.prototype.isValid = function() { |
| return typeof(this.clientId) == 'string' && |
| typeof(this.clientName) == 'string' && |
| typeof(this.createdTime) == 'number'; |
| }; |
| |
| /** |
| * Converts a raw object to an array of PairedClient instances. Returns null if |
| * the input object is incorrectly formatted. |
| * |
| * @param {*} pairedClients The object to convert. |
| * @return {Array.<remoting.PairedClient>} The converted result. |
| */ |
| remoting.PairedClient.convertToPairedClientArray = function(pairedClients) { |
| if (!(pairedClients instanceof Array)) { |
| console.error('pairedClients is not an Array:', pairedClients); |
| return null; |
| } |
| |
| var result = []; |
| for (var i = 0; i < pairedClients.length; i++) { |
| var pairedClient = new remoting.PairedClient(pairedClients[i]); |
| if (!pairedClient.isValid()) { |
| console.error('pairedClient[' + i + '] has incorrect format:', |
| /** @type {*} */(pairedClients[i])); |
| return null; |
| } |
| result.push(pairedClient); |
| } |
| return result; |
| } |
| |
| /** |
| * @param {remoting.HostController} hostController |
| * @param {HTMLElement} listContainer HTML <div> to contain the list of paired |
| * clients. |
| * @param {HTMLElement} message HTML <div> containing the message notifying |
| * the user that clients are paired and containing the link to open the |
| * dialog. |
| * @param {HTMLElement} deleteAllButton HTML <button> inititating the "delete |
| * all" action. |
| * @param {HTMLElement} closeButton HTML <button> to close the dialog. |
| * @param {HTMLElement} noPairedClients HTML <div> containing a message shown |
| * when all clients have been deleted. |
| * @param {HTMLElement} workingSpinner HTML element containing a spinner |
| * graphic shown while a deletion is in progress. |
| * @param {HTMLElement} errorDiv HTML <div> containing an error message shown |
| * if a delete operation fails. |
| * @constructor |
| */ |
| remoting.PairedClientManager = function(hostController, listContainer, message, |
| deleteAllButton, closeButton, |
| noPairedClients, workingSpinner, |
| errorDiv) { |
| /** |
| * @private |
| */ |
| this.hostController_ = hostController; |
| /** |
| * @private |
| */ |
| this.message_ = message; |
| /** |
| * @private |
| */ |
| this.deleteAllButton_ = deleteAllButton; |
| /** |
| * @private |
| */ |
| this.closeButton_ = closeButton; |
| /** |
| * @private |
| */ |
| this.noPairedClients_ = noPairedClients; |
| /** |
| * @private |
| */ |
| this.workingSpinner_ = workingSpinner; |
| /** |
| * @private |
| */ |
| this.errorDiv_ = errorDiv; |
| /** |
| * @type {Element} |
| * @private |
| */ |
| this.clientRows_ = listContainer.querySelector('tbody'); |
| /** |
| * @type {Array.<remoting.PairedClient>} |
| */ |
| this.pairedClients_ = []; |
| |
| this.deleteAllButton_.addEventListener('click', |
| this.deleteAll_.bind(this), |
| false); |
| }; |
| |
| /** |
| * Populate the dialog with the list of paired clients and show or hide the |
| * message as appropriate. |
| * |
| * @param {*} pairedClients The list of paired clients as returned by the |
| * native host component. |
| * @return {void} Nothing. |
| */ |
| remoting.PairedClientManager.prototype.setPairedClients = |
| function(pairedClients) { |
| // Reset table. |
| while (this.clientRows_.lastChild) { |
| this.clientRows_.removeChild(this.clientRows_.lastChild); |
| } |
| |
| this.pairedClients_ = |
| remoting.PairedClient.convertToPairedClientArray(pairedClients); |
| for (var i = 0; i < this.pairedClients_.length; ++i) { |
| var client = this.pairedClients_[i]; |
| client.createDom(this, this.clientRows_); |
| } |
| |
| // Show or hide the "this computer has paired clients" message. |
| this.setWorking_(false) |
| }; |
| |
| /** |
| * Enter or leave "working" mode. This indicates to the user that a delete |
| * operation is in progress. All dialog UI is disabled until it completes. |
| * |
| * @param {boolean} working True to enter "working" mode; false to leave it. |
| * @private |
| */ |
| remoting.PairedClientManager.prototype.setWorking_ = function(working) { |
| var hasPairedClients = (this.pairedClients_.length != 0); |
| for (var i = 0; i < this.pairedClients_.length; ++i) { |
| this.pairedClients_[i].showButton(!working); |
| } |
| this.closeButton_.disabled = working; |
| this.workingSpinner_.hidden = !working; |
| this.errorDiv_.hidden = true; |
| this.message_.hidden = !hasPairedClients; |
| this.deleteAllButton_.disabled = working || !hasPairedClients; |
| this.noPairedClients_.hidden = hasPairedClients; |
| }; |
| |
| /** |
| * Error callback for delete operations. |
| * |
| * @param {remoting.Error} error The error message. |
| * @private |
| */ |
| remoting.PairedClientManager.prototype.onError_ = function(error) { |
| this.setWorking_(false); |
| l10n.localizeElementFromTag(this.errorDiv_, error); |
| this.errorDiv_.hidden = false; |
| }; |
| |
| /** |
| * Delete a single paired client. |
| * |
| * @param {remoting.PairedClient} client The pairing to delete. |
| */ |
| remoting.PairedClientManager.prototype.deletePairedClient = function(client) { |
| this.setWorking_(true); |
| this.hostController_.deletePairedClient(client.clientId, |
| this.setWorking_.bind(this, false), |
| this.onError_.bind(this)); |
| this.clientRows_.removeChild(client.tableRow); |
| for (var i = 0; i < this.pairedClients_.length; ++i) { |
| if (this.pairedClients_[i] == client) { |
| this.pairedClients_.splice(i, 1); |
| break; |
| } |
| } |
| }; |
| |
| /** |
| * Delete all paired clients. |
| * |
| * @private |
| */ |
| remoting.PairedClientManager.prototype.deleteAll_ = function() { |
| this.setWorking_(true); |
| this.hostController_.clearPairedClients( |
| this.setWorking_.bind(this, false), |
| this.onError_.bind(this)); |
| |
| while (this.clientRows_.lastChild) { |
| this.clientRows_.removeChild(this.clientRows_.lastChild); |
| } |
| this.pairedClients_ = []; |
| }; |
| |
| /** |
| * Get the id of the first paired client for testing. |
| * |
| * @private |
| * @return {string} The client id of the first paired client in the list. |
| */ |
| remoting.PairedClientManager.prototype.getFirstClientIdForTesting_ = |
| function() { |
| return this.pairedClients_.length > 0 ? this.pairedClients_[0].clientId : ''; |
| }; |
| |
| |
| /** @type {remoting.PairedClientManager} */ |
| remoting.pairedClientManager = null; |