Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(138)

Side by Side Diff: remoting/webapp/me2mom/host_list.js

Issue 8782001: Refactored HostList to better support bookmarking. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Linter and rebase. Created 9 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 /** 5 /**
6 * @fileoverview 6 * @fileoverview
7 * Class representing the host-list portion of the home screen UI. 7 * Class representing the host-list portion of the home screen UI.
8 */ 8 */
9 9
10 'use strict'; 10 'use strict';
11 11
12 /** @suppress {duplicate} */ 12 /** @suppress {duplicate} */
13 var remoting = remoting || {}; 13 var remoting = remoting || {};
14 14
15 /** 15 /**
16 * Create a host list consisting of the specified HTML elements, which should 16 * Create a host list consisting of the specified HTML elements, which should
17 * have a common parent that contains only host-list UI as it will be hidden 17 * have a common parent that contains only host-list UI as it will be hidden
18 * if the host-list is empty. 18 * if the host-list is empty.
19 *
19 * @constructor 20 * @constructor
20 * @param {Element} table The HTML <table> to contain host-list. 21 * @param {Element} table The HTML <table> to contain host-list.
21 * @param {Element} errorDiv The HTML <div> to display error messages. 22 * @param {Element} errorDiv The HTML <div> to display error messages.
22 */ 23 */
23 remoting.HostList = function(table, errorDiv) { 24 remoting.HostList = function(table, errorDiv) {
24 /** 25 /**
25 * @type {Element} 26 * @type {Element}
26 * @private 27 * @private
27 */ 28 */
28 this.table_ = table; 29 this.table_ = table;
29 /** 30 /**
30 * @type {Element} 31 * @type {Element}
31 * @private 32 * @private
32 */ 33 */
33 this.errorDiv_ = errorDiv; 34 this.errorDiv_ = errorDiv;
34 /** 35 /**
35 * @type {Array.<remoting.HostTableEntry>} 36 * @type {Array.<remoting.HostTableEntry>}
36 * @private 37 * @private
37 */ 38 */
38 this.hostTableEntries_ = null; 39 this.hostTableEntries_ = [];
40 /**
41 * @type {Array.<remoting.Host>}
42 * @private
43 */
44 this.hosts_ = [];
45 /**
46 * @type {string}
47 * @private
48 */
49 this.lastError_ = '';
Wez 2011/12/03 01:26:33 nit: blank line here, please
Jamie 2011/12/05 20:49:08 Done.
50 // Load the cache of the last host-list, if present.
51 var cached = /** @type {string} */
52 (window.localStorage.getItem(remoting.HostList.HOSTS_KEY));
Wez 2011/12/03 01:26:33 nit: indent
Jamie 2011/12/05 20:49:08 Done.
53 if (cached) {
54 try {
55 this.hosts_ = /** @type {Array} */ JSON.parse(cached);
56 } catch (err) {
57 console.error('Invalid host list cache:', /** @type {*} */(err));
58 }
59 }
39 }; 60 };
40 61
41 /** 62 /**
42 * Search the host list for a host with the specified id. 63 * Search the host list for a host with the specified id.
64 *
43 * @param {string} hostId The unique id of the host. 65 * @param {string} hostId The unique id of the host.
44 * @return {remoting.HostTableEntry?} The host table entry, if any. 66 * @return {remoting.Host?} The host, if any.
45 */ 67 */
46 remoting.HostList.prototype.getHostForId = function(hostId) { 68 remoting.HostList.prototype.getHostForId = function(hostId) {
47 for (var i = 0; i < this.hostTableEntries_.length; ++i) { 69 for (var i = 0; i < this.hosts_.length; ++i) {
48 if (this.hostTableEntries_[i].host.hostId == hostId) { 70 if (this.hosts_[i].hostId == hostId) {
49 return this.hostTableEntries_[i]; 71 return this.hosts_[i];
50 } 72 }
51 } 73 }
52 return null; 74 return null;
53 }; 75 };
54 76
55 /** 77 /**
56 * Query the Remoting Directory for the user's list of hosts. 78 * Query the Remoting Directory for the user's list of hosts.
57 * 79 *
80 * @param {function(boolean):void} onDone Callback invoked with true on success
81 * or false on failure.
58 * @return {void} Nothing. 82 * @return {void} Nothing.
59 */ 83 */
60 remoting.HostList.prototype.refresh = function() { 84 remoting.HostList.prototype.refresh = function(onDone) {
61 /** @type {remoting.HostList} */ 85 /** @type {remoting.HostList} */
62 var that = this; 86 var that = this;
63 /** @param {XMLHttpRequest} xhr */ 87 /** @param {XMLHttpRequest} xhr The response from the server. */
64 var parseHostListResponse = function(xhr) { 88 var parseHostListResponse = function(xhr) {
65 that.parseHostListResponse_(xhr); 89 that.parseHostListResponse_(xhr, onDone);
66 } 90 }
67 /** @param {string} token */ 91 /** @param {string} token The OAuth2 token. */
68 var getHosts = function(token) { 92 var getHosts = function(token) {
69 var headers = { 'Authorization': 'OAuth ' + token }; 93 var headers = { 'Authorization': 'OAuth ' + token };
70 remoting.xhr.get( 94 remoting.xhr.get(
71 'https://www.googleapis.com/chromoting/v1/@me/hosts', 95 'https://www.googleapis.com/chromoting/v1/@me/hosts',
72 parseHostListResponse, '', headers); 96 parseHostListResponse, '', headers);
73 }; 97 };
74 remoting.oauth2.callWithToken(getHosts); 98 remoting.oauth2.callWithToken(getHosts);
75 } 99 };
76 100
77 /** 101 /**
78 * Handle the results of the host list request. A success response will 102 * Handle the results of the host list request. A success response will
79 * include a JSON-encoded list of host descriptions, which we display if we're 103 * include a JSON-encoded list of host descriptions, which we display if we're
80 * able to successfully parse it. 104 * able to successfully parse it.
81 * 105 *
82 * @param {XMLHttpRequest} xhr The XHR object for the host list request. 106 * @param {XMLHttpRequest} xhr The XHR object for the host list request.
107 * @param {function(boolean):void} onDone The callback passed to |refresh|.
83 * @return {void} Nothing. 108 * @return {void} Nothing.
109 * @private
84 */ 110 */
85 remoting.HostList.prototype.parseHostListResponse_ = function(xhr) { 111 remoting.HostList.prototype.parseHostListResponse_ = function(xhr, onDone) {
86 try { 112 try {
87 if (xhr.status == 200) { 113 if (xhr.status == 200) {
88 var parsed_response = 114 var parsed_response =
89 /** @type {{data: {items: Array}}} */ JSON.parse(xhr.responseText); 115 /** @type {{data: {items: Array}}} */ JSON.parse(xhr.responseText);
90 if (parsed_response.data && parsed_response.data.items) { 116 if (parsed_response.data && parsed_response.data.items) {
91 this.setHosts_(parsed_response.data.items); 117 this.hosts_ = parsed_response.data.items;
118 this.lastError_ = '';
92 } 119 }
93 } else { 120 } else {
94 // Some other error. 121 // Some other error.
95 console.error('Bad status on host list query: ', xhr); 122 console.error('Bad status on host list query: ', xhr);
96 // For most errors in the 4xx range, tell the user to re-authorize us.
97 if (xhr.status == 403) { 123 if (xhr.status == 403) {
98 // The user's account is not enabled for Me2Me, so fail silently. 124 // The user's account is not enabled for Me2Me, so fail silently.
99 } else if (xhr.status >= 400 && xhr.status <= 499) { 125 this.hosts_ = [];
100 this.showError_(remoting.Error.GENERIC); 126 this.lastError_ = '';
127 } else {
128 // For other errors, tell the user to re-authorize us.
129 this.hosts_ = [];
130 this.lastError_ = remoting.Error.GENERIC;
Wez 2011/12/03 01:26:33 I specifically avoided sending them to the reautho
Jamie 2011/12/05 20:49:08 We have to show some error message in this case. I
Wez 2011/12/05 20:59:38 Suggesting courses of action that we know won't he
101 } 131 }
102 } 132 }
103 } catch (er) { 133 } catch (er) {
104 var typed_er = /** @type {Object} */ (er); 134 var typed_er = /** @type {Object} */ (er);
105 console.error('Error processing response: ', xhr, typed_er); 135 console.error('Error processing response: ', xhr, typed_er);
136 this.hosts_ = [];
137 this.lastError_ = remoting.Error.GENERIC;
Wez 2011/12/03 01:26:33 I specifically avoided barfing them to the reautho
Jamie 2011/12/05 20:49:08 See above.
106 } 138 }
107 } 139 window.localStorage.setItem(remoting.HostList.HOSTS_KEY,
140 JSON.stringify(this.hosts_));
141 onDone(this.lastError_ == '');
142 };
108 143
109 /** 144 /**
110 * Refresh the host list with up-to-date details. 145 * Display the list of hosts or error condition.
111 * @param {Array.<remoting.Host>} hosts The new host list. 146 *
112 * @return {void} Nothing. 147 * @return {void} Nothing.
113 * @private
114 */ 148 */
115 remoting.HostList.prototype.setHosts_ = function(hosts) { 149 remoting.HostList.prototype.display = function() {
116 this.table_.innerHTML = ''; 150 this.table_.innerHTML = '';
117 this.showError_(null); 151 this.errorDiv_.innerText = '';
118 this.hostTableEntries_ = []; 152 this.hostTableEntries_ = [];
119 153
120 /** @type {remoting.HostList} */ 154 /** @type {remoting.HostList} */
121 var that = this; 155 var that = this;
122 for (var i = 0; i < hosts.length; ++i) { 156 for (var i = 0; i < this.hosts_.length; ++i) {
123 /** @type {remoting.Host} */ 157 /** @type {remoting.Host} */
124 var host = hosts[i]; 158 var host = this.hosts_[i];
125 // Validate the entry to make sure it has all the fields we expect. 159 // Validate the entry to make sure it has all the fields we expect.
126 if (host.hostName && host.hostId && host.status && host.jabberId && 160 if (host.hostName && host.hostId && host.status && host.jabberId &&
127 host.publicKey) { 161 host.publicKey) {
128 var onRename = function() { that.renameHost_(host.hostId); } 162 var onRename = function() { that.renameHost_(host.hostId); }
129 var onDelete = function() { that.deleteHost_(host.hostId); } 163 var onDelete = function() { that.deleteHost_(host.hostId); }
130 var hostTableEntry = new remoting.HostTableEntry(); 164 var hostTableEntry = new remoting.HostTableEntry();
131 hostTableEntry.init(host, onRename, onDelete); 165 hostTableEntry.init(host, onRename, onDelete);
132 this.hostTableEntries_[i] = hostTableEntry; 166 this.hostTableEntries_[i] = hostTableEntry;
133 this.table_.appendChild(hostTableEntry.tableRow); 167 this.table_.appendChild(hostTableEntry.tableRow);
134 } 168 }
135 } 169 }
136 170
137 this.showOrHide_(this.hostTableEntries_.length != 0); 171 if (this.lastError_ != '') {
138 }; 172 l10n.localizeElementFromTag(this.errorDiv_, this.lastError_);
173 }
139 174
140 /** 175 this.showOrHide_(this.hosts_.length != 0 || this.lastError_ != '');
141 * Display a localized error message.
142 * @param {remoting.Error?} errorTag The error to display, or NULL to clear any
143 * previous error.
144 * @return {void} Nothing.
145 */
146 remoting.HostList.prototype.showError_ = function(errorTag) {
147 this.table_.innerHTML = '';
148 if (errorTag) {
149 l10n.localizeElementFromTag(this.errorDiv_,
150 /** @type {string} */ (errorTag));
151 this.showOrHide_(true);
152 } else {
153 this.errorDiv_.innerText = '';
154 }
155 }; 176 };
156 177
157 /** 178 /**
158 * Show or hide the host-list UI. 179 * Show or hide the host-list UI.
180 *
159 * @param {boolean} show True to show the UI, or false to hide it. 181 * @param {boolean} show True to show the UI, or false to hide it.
160 * @return {void} Nothing. 182 * @return {void} Nothing.
161 * @private 183 * @private
162 */ 184 */
163 remoting.HostList.prototype.showOrHide_ = function(show) { 185 remoting.HostList.prototype.showOrHide_ = function(show) {
164 var parent = /** @type {Element} */ (this.table_.parentNode); 186 var parent = /** @type {Element} */ (this.table_.parentNode);
165 parent.hidden = !show; 187 parent.hidden = !show;
166 if (show) { 188 if (show) {
167 parent.style.height = parent.scrollHeight + 'px'; 189 parent.style.height = parent.scrollHeight + 'px';
168 removeClass(parent, remoting.HostList.COLLAPSED_); 190 removeClass(parent, remoting.HostList.COLLAPSED_);
169 } else { 191 } else {
170 addClass(parent, remoting.HostList.COLLAPSED_); 192 addClass(parent, remoting.HostList.COLLAPSED_);
171 } 193 }
172 }; 194 };
173 195
174 /** 196 /**
175 * Remove a host from the list, and deregister it. 197 * Remove a host from the list, and deregister it.
198 *
176 * @param {string} hostId The id of the host to be removed. 199 * @param {string} hostId The id of the host to be removed.
177 * @return {void} Nothing. 200 * @return {void} Nothing.
178 * @private 201 * @private
179 */ 202 */
180 remoting.HostList.prototype.deleteHost_ = function(hostId) { 203 remoting.HostList.prototype.deleteHost_ = function(hostId) {
181 /** @type {remoting.HostTableEntry} */ 204 var host = this.getHostForId(hostId);
182 var hostTableEntry = this.getHostForId(hostId); 205 if (!host) {
183 if (!hostTableEntry) {
184 console.error('No host registered for id ' + hostId); 206 console.error('No host registered for id ' + hostId);
185 return; 207 return;
186 } 208 }
187 209
188 this.table_.removeChild(hostTableEntry.tableRow); 210 var index = this.hosts_.indexOf(host);
189 var index = this.hostTableEntries_.indexOf(hostTableEntry);
190 if (index != -1) { // Since we've just found it, index must be >= 0 211 if (index != -1) { // Since we've just found it, index must be >= 0
212 this.hosts_.splice(index, 1);
213 }
214 var hostTableEntry = null;
215 for (index = 0; index < this.hostTableEntries_.length; ++index) {
216 if (this.hostTableEntries_[index].host.hostId == hostId) {
217 hostTableEntry = this.hostTableEntries_[index];
218 break;
219 }
220 }
221 if (hostTableEntry) {
222 this.table_.removeChild(hostTableEntry.tableRow);
191 this.hostTableEntries_.splice(index, 1); 223 this.hostTableEntries_.splice(index, 1);
192 } 224 }
193 225
194 /** @param {string} token */ 226 /** @param {string} token The OAuth2 token. */
195 var deleteHost = function(token) { 227 var deleteHost = function(token) {
196 var headers = { 'Authorization': 'OAuth ' + token }; 228 var headers = { 'Authorization': 'OAuth ' + token };
197 remoting.xhr.remove( 229 remoting.xhr.remove(
198 'https://www.googleapis.com/chromoting/v1/@me/hosts/' + hostId, 230 'https://www.googleapis.com/chromoting/v1/@me/hosts/' + hostId,
199 function() {}, '', headers); 231 function() {}, '', headers);
200 } 232 }
201 remoting.oauth2.callWithToken(deleteHost); 233 remoting.oauth2.callWithToken(deleteHost);
202 234
203 this.showOrHide_(this.hostTableEntries_.length != 0); 235 this.showOrHide_(this.hostTableEntries_.length != 0);
204 }; 236 };
205 237
206 /** 238 /**
207 * Prepare a host for renaming by replacing its name with an edit box. 239 * Rename the specified host.
240 *
208 * @param {string} hostId The id of the host to be renamed. 241 * @param {string} hostId The id of the host to be renamed.
209 * @return {void} Nothing. 242 * @return {void} Nothing.
210 * @private 243 * @private
211 */ 244 */
212 remoting.HostList.prototype.renameHost_ = function(hostId) { 245 remoting.HostList.prototype.renameHost_ = function(hostId) {
213 /** @type {remoting.HostTableEntry} */ 246 /** @type {remoting.Host} */
214 var hostTableEntry = this.getHostForId(hostId); 247 var host = this.getHostForId(hostId);
215 if (!hostTableEntry) { 248 if (!host) {
216 console.error('No host registered for id ' + hostId); 249 console.error('No host registered for id ' + hostId);
217 return; 250 return;
218 } 251 }
219 /** @param {string} token */ 252 /** @param {string} token The OAuth2 token. */
220 var renameHost = function(token) { 253 var renameHost = function(token) {
221 var headers = { 254 var headers = {
222 'Authorization': 'OAuth ' + token, 255 'Authorization': 'OAuth ' + token,
223 'Content-type' : 'application/json; charset=UTF-8' 256 'Content-type' : 'application/json; charset=UTF-8'
224 }; 257 };
225 var newHostDetails = { data: { 258 var newHostDetails = { data: {
226 hostId: hostTableEntry.host.hostId, 259 hostId: host.hostId,
227 hostName: hostTableEntry.host.hostName, 260 hostName: host.hostName,
228 publicKey: hostTableEntry.host.publicKey 261 publicKey: host.publicKey
229 } }; 262 } };
230 remoting.xhr.put( 263 remoting.xhr.put(
231 'https://www.googleapis.com/chromoting/v1/@me/hosts/' + hostId, 264 'https://www.googleapis.com/chromoting/v1/@me/hosts/' + hostId,
232 function(xhr) {}, 265 function(xhr) {},
233 JSON.stringify(newHostDetails), 266 JSON.stringify(newHostDetails),
234 headers); 267 headers);
235 } 268 }
236 remoting.oauth2.callWithToken(renameHost); 269 remoting.oauth2.callWithToken(renameHost);
237 }; 270 };
238 271
239 /** 272 /**
240 * Class name for the host list when it is collapsed. 273 * Class name for the host list when it is collapsed.
241 * @private 274 * @private
242 */ 275 */
243 remoting.HostList.COLLAPSED_ = 'collapsed'; 276 remoting.HostList.COLLAPSED_ = 'collapsed';
244 277
278 /**
279 * Key name under which Me2Me hosts are cached.
280 */
281 remoting.HostList.HOSTS_KEY = 'me2me-cached-hosts';
282
245 /** @type {remoting.HostList} */ 283 /** @type {remoting.HostList} */
246 remoting.hostList = null; 284 remoting.hostList = null;
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698