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

Side by Side Diff: remoting/webapp/crd/js/desktop_remoting.js

Issue 1016373003: [Chromoting] Change Application.Delegate to proper subclass of Application. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Protect many things Created 5 years, 9 months 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
OLDNEW
1 // Copyright 2014 The Chromium Authors. All rights reserved. 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 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 * This class implements the functionality that is specific to desktop 7 * This class implements the functionality that is specific to desktop
8 * remoting ("Chromoting" or CRD). 8 * remoting ("Chromoting" or CRD).
9 */ 9 */
10 10
11 'use strict'; 11 'use strict';
12 12
13 /** @suppress {duplicate} */ 13 /** @suppress {duplicate} */
14 var remoting = remoting || {}; 14 var remoting = remoting || {};
15 15
16 /** 16 /**
17 * @param {remoting.Application} app The main app that owns this delegate. 17 * @param {Array<string>} appCapabilities Array of application capabilities.
18 * @constructor 18 * @constructor
19 * @implements {remoting.Application.Delegate} 19 * @implements {remoting.ApplicationInterface}
20 * @extends {remoting.Application}
20 */ 21 */
21 remoting.DesktopRemoting = function(app) { 22 remoting.DesktopRemoting = function(appCapabilities) {
22 /** 23 base.inherits(this, remoting.Application, appCapabilities);
23 * TODO(garykac): Remove this reference to the Application. It's only
24 * needed to get the current mode when reporting errors. So we should be
25 * able to refactor and remove this reference cycle.
26 *
27 * @private {remoting.Application}
28 */
29 this.app_ = app;
30 app.setDelegate(this);
31 24
32 /** 25 /**
33 * Whether to refresh the JID and retry the connection if the current JID 26 * Whether to refresh the JID and retry the connection if the current JID
34 * is offline. 27 * is offline.
35 * 28 *
36 * @private {boolean} 29 * @private {boolean}
37 */ 30 */
38 this.refreshHostJidIfOffline_ = true; 31 this.refreshHostJidIfOffline_ = true;
39 32
40 /** @private {remoting.DesktopConnectedView} */ 33 /** @private {remoting.DesktopConnectedView} */
41 this.connectedView_ = null; 34 this.connectedView_ = null;
42
43 remoting.desktopDelegateForTesting = this;
44 }; 35 };
45 36
46 /** 37 /**
47 * Initialize the application and register all event handlers. After this 38 * @return {string} Application product name to be used in UI.
48 * is called, the app is running and waiting for user events. 39 * @override {remoting.ApplicationInterface}
49 *
50 * @return {void} Nothing.
51 */ 40 */
52 remoting.DesktopRemoting.prototype.init = function() { 41 remoting.DesktopRemoting.prototype.getApplicationName = function() {
42 return chrome.i18n.getMessage(/*i18n-content*/'PRODUCT_NAME');
43 };
44
45 /**
46 * @param {!remoting.Error} error The failure reason.
47 * @override {remoting.ApplicationInterface}
48 */
49 remoting.DesktopRemoting.prototype.signInFailed_ = function(error) {
50 remoting.showErrorMessage(error);
51 };
52
53 /**
54 * @override {remoting.ApplicationInterface}
55 */
56 remoting.DesktopRemoting.prototype.initApplication_ = function() {
53 remoting.initElementEventHandlers(); 57 remoting.initElementEventHandlers();
54 58
55 if (base.isAppsV2()) { 59 if (base.isAppsV2()) {
56 remoting.windowFrame = new remoting.WindowFrame( 60 remoting.windowFrame = new remoting.WindowFrame(
57 document.getElementById('title-bar')); 61 document.getElementById('title-bar'));
58 remoting.optionsMenu = remoting.windowFrame.createOptionsMenu(); 62 remoting.optionsMenu = remoting.windowFrame.createOptionsMenu();
59 63
60 var START_FULLSCREEN = 'start-fullscreen'; 64 var START_FULLSCREEN = 'start-fullscreen';
61 remoting.fullscreen = new remoting.FullscreenAppsV2(); 65 remoting.fullscreen = new remoting.FullscreenAppsV2();
62 remoting.fullscreen.addListener(function(isFullscreen) { 66 remoting.fullscreen.addListener(function(isFullscreen) {
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after
115 document.getElementById('startup-mode-box-it2me').hidden = false; 119 document.getElementById('startup-mode-box-it2me').hidden = false;
116 } 120 }
117 }; 121 };
118 this.isWindowed_(onIsWindowed); 122 this.isWindowed_(onIsWindowed);
119 } 123 }
120 124
121 remoting.ClientPlugin.factory.preloadPlugin(); 125 remoting.ClientPlugin.factory.preloadPlugin();
122 }; 126 };
123 127
124 /** 128 /**
125 * Start the application. Once start() is called, the delegate can assume that 129 * @param {string} token An OAuth access token.
126 * the user has consented to all permissions specified in the manifest. 130 * @override {remoting.ApplicationInterface}
127 *
128 * @param {remoting.SessionConnector} connector
129 * @param {string} token An OAuth access token. The delegate should not cache
130 * this token, but can assume that it will remain valid during application
131 * start-up.
132 */ 131 */
133 remoting.DesktopRemoting.prototype.start = function(connector, token) { 132 remoting.DesktopRemoting.prototype.startApplication_ = function(token) {
134 remoting.identity.getEmail().then( 133 remoting.identity.getEmail().then(
135 function(/** string */ email) { 134 function(/** string */ email) {
136 document.getElementById('current-email').innerText = email; 135 document.getElementById('current-email').innerText = email;
137 document.getElementById('get-started-it2me').disabled = false; 136 document.getElementById('get-started-it2me').disabled = false;
138 document.getElementById('get-started-me2me').disabled = false; 137 document.getElementById('get-started-me2me').disabled = false;
139 }); 138 });
140 }; 139 };
141 140
142 /** 141 /** @override {remoting.ApplicationInterface} */
143 * Report an authentication error to the user. This is called in lieu of start() 142 remoting.DesktopRemoting.prototype.exitApplication_ = function() {
144 * if the user cannot be authenticated or if they decline the app permissions. 143 this.exit_();
145 *
146 * @param {!remoting.Error} error The failure reason.
147 */
148 remoting.DesktopRemoting.prototype.signInFailed = function(error) {
149 remoting.showErrorMessage(error);
150 }; 144 };
151 145
152 /** 146 /**
153 * @return {string} Application product name to be used in UI. 147 * @param {remoting.ConnectionInfo} connectionInfo
148 * @override {remoting.ApplicationInterface}
154 */ 149 */
155 remoting.DesktopRemoting.prototype.getApplicationName = function() { 150 remoting.DesktopRemoting.prototype.onConnected_ = function(connectionInfo) {
156 return chrome.i18n.getMessage(/*i18n-content*/'PRODUCT_NAME'); 151 this.initSession_(connectionInfo);
157 };
158 152
159 /**
160 * Called when a new session has been connected.
161 *
162 * @param {remoting.ConnectionInfo} connectionInfo
163 * @return {void} Nothing.
164 */
165 remoting.DesktopRemoting.prototype.handleConnected = function(connectionInfo) {
166 // Set the text on the buttons shown under the error message so that they are 153 // Set the text on the buttons shown under the error message so that they are
167 // easy to understand in the case where a successful connection failed, as 154 // easy to understand in the case where a successful connection failed, as
168 // opposed to the case where a connection never succeeded. 155 // opposed to the case where a connection never succeeded.
169 // TODO(garykac): Investigate to see if these need to be reverted to their 156 // TODO(garykac): Investigate to see if these need to be reverted to their
170 // original values in the onDisconnected method. 157 // original values in the onDisconnected_ method.
171 var button1 = document.getElementById('client-reconnect-button'); 158 var button1 = document.getElementById('client-reconnect-button');
172 l10n.localizeElementFromTag(button1, /*i18n-content*/'RECONNECT'); 159 l10n.localizeElementFromTag(button1, /*i18n-content*/'RECONNECT');
173 button1.removeAttribute('autofocus'); 160 button1.removeAttribute('autofocus');
174 var button2 = document.getElementById('client-finished-me2me-button'); 161 var button2 = document.getElementById('client-finished-me2me-button');
175 l10n.localizeElementFromTag(button2, /*i18n-content*/'OK'); 162 l10n.localizeElementFromTag(button2, /*i18n-content*/'OK');
176 button2.setAttribute('autofocus', 'autofocus'); 163 button2.setAttribute('autofocus', 'autofocus');
177 164
178 // Reset the refresh flag so that the next connection will retry if needed. 165 // Reset the refresh flag so that the next connection will retry if needed.
179 this.refreshHostJidIfOffline_ = true; 166 this.refreshHostJidIfOffline_ = true;
180 167
181 document.getElementById('access-code-entry').value = ''; 168 document.getElementById('access-code-entry').value = '';
182 remoting.setMode(remoting.AppMode.IN_SESSION); 169 remoting.setMode(remoting.AppMode.IN_SESSION);
183 if (!base.isAppsV2()) { 170 if (!base.isAppsV2()) {
184 remoting.toolbar.center(); 171 remoting.toolbar.center();
185 remoting.toolbar.preview(); 172 remoting.toolbar.preview();
186 } 173 }
187 174
188 this.connectedView_ = new remoting.DesktopConnectedView( 175 this.connectedView_ = new remoting.DesktopConnectedView(
189 document.getElementById('client-container'), connectionInfo); 176 document.getElementById('client-container'), connectionInfo);
190 177
191 // By default, under ChromeOS, remap the right Control key to the right 178 // By default, under ChromeOS, remap the right Control key to the right
192 // Win / Cmd key. 179 // Win / Cmd key.
193 if (remoting.platformIsChromeOS()) { 180 if (remoting.platformIsChromeOS()) {
194 connectionInfo.plugin().setRemapKeys('0x0700e4>0x0700e7'); 181 connectionInfo.plugin().setRemapKeys('0x0700e4>0x0700e7');
195 } 182 }
196 183
197 if (connectionInfo.mode() === remoting.DesktopConnectedView.Mode.ME2ME) { 184 if (connectionInfo.mode() === remoting.DesktopConnectedView.Mode.ME2ME) {
198 var sessionConnector = remoting.app.getSessionConnector();
199 if (remoting.app.hasCapability(remoting.ClientSession.Capability.CAST)) { 185 if (remoting.app.hasCapability(remoting.ClientSession.Capability.CAST)) {
200 sessionConnector.registerProtocolExtension( 186 this.sessionConnector_.registerProtocolExtension(
201 new remoting.CastExtensionHandler()); 187 new remoting.CastExtensionHandler());
202 } 188 }
203 sessionConnector.registerProtocolExtension( 189 this.sessionConnector_.registerProtocolExtension(
204 new remoting.GnubbyAuthHandler()); 190 new remoting.GnubbyAuthHandler());
205 } 191 }
206 192
207 if (remoting.pairingRequested) { 193 if (remoting.pairingRequested) {
194 var that = this;
208 /** 195 /**
209 * @param {string} clientId 196 * @param {string} clientId
210 * @param {string} sharedSecret 197 * @param {string} sharedSecret
211 */ 198 */
212 var onPairingComplete = function(clientId, sharedSecret) { 199 var onPairingComplete = function(clientId, sharedSecret) {
213 var connector = remoting.app.getSessionConnector(); 200 var connector = that.sessionConnector_;
214 var host = remoting.hostList.getHostForId(connector.getHostId()); 201 var host = remoting.hostList.getHostForId(connector.getHostId());
215 host.options.pairingInfo.clientId = clientId; 202 host.options.pairingInfo.clientId = clientId;
216 host.options.pairingInfo.sharedSecret = sharedSecret; 203 host.options.pairingInfo.sharedSecret = sharedSecret;
217 host.options.save(); 204 host.options.save();
218 connector.updatePairingInfo(clientId, sharedSecret); 205 connector.updatePairingInfo(clientId, sharedSecret);
219 }; 206 };
220 // Use the platform name as a proxy for the local computer name. 207 // Use the platform name as a proxy for the local computer name.
221 // TODO(jamiewalch): Use a descriptive name for the local computer, for 208 // TODO(jamiewalch): Use a descriptive name for the local computer, for
222 // example, its Chrome Sync name. 209 // example, its Chrome Sync name.
223 var clientName = ''; 210 var clientName = '';
224 if (remoting.platformIsMac()) { 211 if (remoting.platformIsMac()) {
225 clientName = 'Mac'; 212 clientName = 'Mac';
226 } else if (remoting.platformIsWindows()) { 213 } else if (remoting.platformIsWindows()) {
227 clientName = 'Windows'; 214 clientName = 'Windows';
228 } else if (remoting.platformIsChromeOS()) { 215 } else if (remoting.platformIsChromeOS()) {
229 clientName = 'ChromeOS'; 216 clientName = 'ChromeOS';
230 } else if (remoting.platformIsLinux()) { 217 } else if (remoting.platformIsLinux()) {
231 clientName = 'Linux'; 218 clientName = 'Linux';
232 } else { 219 } else {
233 console.log('Unrecognized client platform. Using navigator.platform.'); 220 console.log('Unrecognized client platform. Using navigator.platform.');
234 clientName = navigator.platform; 221 clientName = navigator.platform;
235 } 222 }
236 connectionInfo.session().requestPairing(clientName, onPairingComplete); 223 connectionInfo.session().requestPairing(clientName, onPairingComplete);
237 } 224 }
238 }; 225 };
239 226
240 /** 227 /**
241 * Called when the current session has been disconnected. 228 * @override {remoting.ApplicationInterface}
242 *
243 * @return {void} Nothing.
244 */ 229 */
245 remoting.DesktopRemoting.prototype.handleDisconnected = function() { 230 remoting.DesktopRemoting.prototype.onDisconnected_ = function() {
246 var mode = this.connectedView_.getMode(); 231 var mode = this.connectedView_.getMode();
247 if (mode === remoting.DesktopConnectedView.Mode.IT2ME) { 232 if (mode === remoting.DesktopConnectedView.Mode.IT2ME) {
248 remoting.setMode(remoting.AppMode.CLIENT_SESSION_FINISHED_IT2ME); 233 remoting.setMode(remoting.AppMode.CLIENT_SESSION_FINISHED_IT2ME);
249 } else { 234 } else {
250 remoting.setMode(remoting.AppMode.CLIENT_SESSION_FINISHED_ME2ME); 235 remoting.setMode(remoting.AppMode.CLIENT_SESSION_FINISHED_ME2ME);
251 } 236 }
252 base.dispose(this.connectedView_); 237 base.dispose(this.connectedView_);
253 this.connectedView_ = null; 238 this.connectedView_ = null;
254 }; 239 };
255 240
256 /** 241 /**
257 * Called when the current session's connection has failed.
258 *
259 * @param {remoting.SessionConnector} connector
260 * @param {!remoting.Error} error 242 * @param {!remoting.Error} error
261 * @return {void} Nothing. 243 * @override {remoting.ApplicationInterface}
262 */ 244 */
263 remoting.DesktopRemoting.prototype.handleConnectionFailed = function( 245 remoting.DesktopRemoting.prototype.onConnectionFailed_ = function(error) {
264 connector, error) {
265 var that = this; 246 var that = this;
266 var onHostListRefresh = function(/** boolean */ success) { 247 var onHostListRefresh = function(/** boolean */ success) {
267 if (success) { 248 if (success) {
249 var connector = that.sessionConnector_;
268 var host = remoting.hostList.getHostForId(connector.getHostId()); 250 var host = remoting.hostList.getHostForId(connector.getHostId());
269 if (host) { 251 if (host) {
270 connector.retryConnectMe2Me(host); 252 connector.retryConnectMe2Me(host);
271 return; 253 return;
272 } 254 }
273 } 255 }
274 that.handleError(error); 256 that.onError_(error);
275 }; 257 };
276 258
277 var mode = this.app_.getSessionConnector().getConnectionMode(); 259 var mode = this.sessionConnector_.getConnectionMode();
278 if (error.hasTag(remoting.Error.Tag.HOST_IS_OFFLINE) && 260 if (error.hasTag(remoting.Error.Tag.HOST_IS_OFFLINE) &&
279 mode === remoting.DesktopConnectedView.Mode.ME2ME && 261 mode === remoting.DesktopConnectedView.Mode.ME2ME &&
280 this.refreshHostJidIfOffline_) { 262 this.refreshHostJidIfOffline_) {
281 this.refreshHostJidIfOffline_ = false; 263 this.refreshHostJidIfOffline_ = false;
282 264
283 // The plugin will be re-created when the host finished refreshing 265 // The plugin will be re-created when the host finished refreshing
284 remoting.hostList.refresh(onHostListRefresh); 266 remoting.hostList.refresh(onHostListRefresh);
285 } else { 267 } else {
286 this.handleError(error); 268 this.onError_(error);
287 } 269 }
288 }; 270 };
289 271
290 /** 272 /**
291 * Called when an error needs to be displayed to the user.
292 *
293 * @param {!remoting.Error} error The error to be localized and displayed. 273 * @param {!remoting.Error} error The error to be localized and displayed.
294 * @return {void} Nothing. 274 * @override {remoting.ApplicationInterface}
295 */ 275 */
296 remoting.DesktopRemoting.prototype.handleError = function(error) { 276 remoting.DesktopRemoting.prototype.onError_ = function(error) {
297 console.error('Connection failed: ' + error.toString()); 277 console.error('Connection failed: ' + error.toString());
298 var mode = this.connectedView_ ? this.connectedView_.getMode() 278 var mode = this.connectedView_ ? this.connectedView_.getMode()
299 : this.app_.getSessionConnector().getConnectionMode(); 279 : this.sessionConnector_.getConnectionMode();
300 base.dispose(this.connectedView_); 280 base.dispose(this.connectedView_);
301 this.connectedView_ = null; 281 this.connectedView_ = null;
302 282
303 if (error.hasTag(remoting.Error.Tag.AUTHENTICATION_FAILED)) { 283 if (error.hasTag(remoting.Error.Tag.AUTHENTICATION_FAILED)) {
304 remoting.setMode(remoting.AppMode.HOME); 284 remoting.setMode(remoting.AppMode.HOME);
305 remoting.handleAuthFailureAndRelaunch(); 285 remoting.handleAuthFailureAndRelaunch();
306 return; 286 return;
307 } 287 }
308 288
309 // Reset the refresh flag so that the next connection will retry if needed. 289 // Reset the refresh flag so that the next connection will retry if needed.
310 this.refreshHostJidIfOffline_ = true; 290 this.refreshHostJidIfOffline_ = true;
311 291
312 var errorDiv = document.getElementById('connect-error-message'); 292 var errorDiv = document.getElementById('connect-error-message');
313 l10n.localizeElementFromTag(errorDiv, error.getTag()); 293 l10n.localizeElementFromTag(errorDiv, error.getTag());
314 294
315 if (mode == remoting.DesktopConnectedView.Mode.IT2ME) { 295 if (mode == remoting.DesktopConnectedView.Mode.IT2ME) {
316 remoting.setMode(remoting.AppMode.CLIENT_CONNECT_FAILED_IT2ME); 296 remoting.setMode(remoting.AppMode.CLIENT_CONNECT_FAILED_IT2ME);
317 } else { 297 } else {
318 remoting.setMode(remoting.AppMode.CLIENT_CONNECT_FAILED_ME2ME); 298 remoting.setMode(remoting.AppMode.CLIENT_CONNECT_FAILED_ME2ME);
319 } 299 }
320 }; 300 };
321 301
322 /** 302 /**
323 * No cleanup required for desktop remoting.
324 */
325 remoting.DesktopRemoting.prototype.handleExit = function() {
326 };
327
328 /**
329 * Determine whether or not the app is running in a window. 303 * Determine whether or not the app is running in a window.
330 * @param {function(boolean):void} callback Callback to receive whether or not 304 * @param {function(boolean):void} callback Callback to receive whether or not
331 * the current tab is running in windowed mode. 305 * the current tab is running in windowed mode.
332 * @private 306 * @private
333 */ 307 */
334 remoting.DesktopRemoting.prototype.isWindowed_ = function(callback) { 308 remoting.DesktopRemoting.prototype.isWindowed_ = function(callback) {
335 /** @param {chrome.Window} win The current window. */ 309 /** @param {chrome.Window} win The current window. */
336 var windowCallback = function(win) { 310 var windowCallback = function(win) {
337 callback(win.type == 'popup'); 311 callback(win.type == 'popup');
338 }; 312 };
(...skipping 12 matching lines...) Expand all
351 } 325 }
352 } 326 }
353 327
354 /** 328 /**
355 * If an IT2Me client or host is active then prompt the user before closing. 329 * If an IT2Me client or host is active then prompt the user before closing.
356 * If a Me2Me client is active then don't bother, since closing the window is 330 * If a Me2Me client is active then don't bother, since closing the window is
357 * the more intuitive way to end a Me2Me session, and re-connecting is easy. 331 * the more intuitive way to end a Me2Me session, and re-connecting is easy.
358 * @private 332 * @private
359 */ 333 */
360 remoting.DesktopRemoting.prototype.promptClose_ = function() { 334 remoting.DesktopRemoting.prototype.promptClose_ = function() {
361 var sessionConnector = remoting.app.getSessionConnector(); 335 var sessionConnector = this.sessionConnector_;
362 if (sessionConnector && 336 if (sessionConnector &&
363 sessionConnector.getConnectionMode() == 337 sessionConnector.getConnectionMode() ==
364 remoting.DesktopConnectedView.Mode.IT2ME) { 338 remoting.DesktopConnectedView.Mode.IT2ME) {
365 switch (remoting.currentMode) { 339 switch (remoting.currentMode) {
366 case remoting.AppMode.CLIENT_CONNECTING: 340 case remoting.AppMode.CLIENT_CONNECTING:
367 case remoting.AppMode.HOST_WAITING_FOR_CODE: 341 case remoting.AppMode.HOST_WAITING_FOR_CODE:
368 case remoting.AppMode.HOST_WAITING_FOR_CONNECTION: 342 case remoting.AppMode.HOST_WAITING_FOR_CONNECTION:
369 case remoting.AppMode.HOST_SHARED: 343 case remoting.AppMode.HOST_SHARED:
370 case remoting.AppMode.IN_SESSION: 344 case remoting.AppMode.IN_SESSION:
371 return chrome.i18n.getMessage(/*i18n-content*/'CLOSE_PROMPT'); 345 return chrome.i18n.getMessage(/*i18n-content*/'CLOSE_PROMPT');
372 default: 346 default:
373 return null; 347 return null;
374 } 348 }
375 } 349 }
376 }; 350 };
377 351
378 /** @returns {remoting.DesktopConnectedView} */ 352 /** @returns {remoting.DesktopConnectedView} */
379 remoting.DesktopRemoting.prototype.getConnectedViewForTesting = function() { 353 remoting.DesktopRemoting.prototype.getConnectedViewForTesting = function() {
380 return this.connectedView_; 354 return this.connectedView_;
381 }; 355 };
382
383 /**
384 * Global instance of remoting.DesktopRemoting used for testing.
385 * @type {remoting.DesktopRemoting}
386 */
387 remoting.desktopDelegateForTesting = null;
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698