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

Side by Side Diff: remoting/webapp/app_remoting/js/app_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: Update comments; remove desktopDelegateForTesting 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 application 7 * This class implements the functionality that is specific to application
8 * remoting ("AppRemoting" or AR). 8 * remoting ("AppRemoting" or AR).
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 * @implements {remoting.ProtocolExtension} 20 * @implements {remoting.ProtocolExtension}
21 * @extends {remoting.Application}
21 */ 22 */
22 remoting.AppRemoting = function(app) { 23 remoting.AppRemoting = function(appCapabilities) {
23 app.setDelegate(this); 24 base.inherits(this, remoting.Application, appCapabilities);
24 25
25 /** @private {remoting.ApplicationContextMenu} */ 26 /** @private {remoting.ApplicationContextMenu} */
26 this.contextMenu_ = null; 27 this.contextMenu_ = null;
27 28
28 /** @private {remoting.KeyboardLayoutsMenu} */ 29 /** @private {remoting.KeyboardLayoutsMenu} */
29 this.keyboardLayoutsMenu_ = null; 30 this.keyboardLayoutsMenu_ = null;
30 31
31 /** @private {remoting.WindowActivationMenu} */ 32 /** @private {remoting.WindowActivationMenu} */
32 this.windowActivationMenu_ = null; 33 this.windowActivationMenu_ = null;
33 34
(...skipping 18 matching lines...) Expand all
52 this.sharedSecret = ''; 53 this.sharedSecret = '';
53 54
54 this.host = { 55 this.host = {
55 /** @type {string} */ 56 /** @type {string} */
56 applicationId: '', 57 applicationId: '',
57 58
58 /** @type {string} */ 59 /** @type {string} */
59 hostId: ''}; 60 hostId: ''};
60 }; 61 };
61 62
63 /** @return {string} */
64 remoting.AppRemoting.prototype.runApplicationUrl = function() {
Jamie 2015/03/25 20:00:39 This shouldn't be a public member, I don't think.
garykac 2015/03/26 01:41:57 Done.
65 return remoting.settings.APP_REMOTING_API_BASE_URL + '/applications/' +
66 remoting.settings.getAppRemotingApplicationId() + '/run';
67 };
68
62 /** 69 /**
63 * Initialize the application. This is called before an OAuth token is requested 70 * Required for remoting.ApplicationInterface interface.
64 * and should be used for tasks such as initializing the DOM, registering event 71 *
65 * handlers, etc. 72 * @return {string} Application product name to be used in UI.
73 * @override
66 */ 74 */
67 remoting.AppRemoting.prototype.init = function() { 75 remoting.AppRemoting.prototype.getApplicationName = function() {
76 var manifest = chrome.runtime.getManifest();
77 return manifest.name;
78 };
79
80 /**
81 * Required for remoting.ApplicationInterface interface.
82 *
83 * @param {!remoting.Error} error The failure reason.
84 * @override
85 */
86 remoting.AppRemoting.prototype.signInFailed = function(error) {
87 this.onError(error);
88 };
89
90 /**
91 * Required for remoting.ApplicationInterface interface.
92 *
93 * @override
94 */
95 remoting.AppRemoting.prototype.initApplication = function() {
68 // TODO(jamiewalch): Remove ClientSession's dependency on remoting.fullscreen 96 // TODO(jamiewalch): Remove ClientSession's dependency on remoting.fullscreen
69 // so that this is no longer required. 97 // so that this is no longer required.
70 remoting.fullscreen = new remoting.FullscreenAppsV2(); 98 remoting.fullscreen = new remoting.FullscreenAppsV2();
71 99
72 var restoreHostWindows = function() { 100 var restoreHostWindows = function() {
73 if (remoting.clientSession) { 101 if (remoting.clientSession) {
74 remoting.clientSession.sendClientMessage('restoreAllWindows', ''); 102 remoting.clientSession.sendClientMessage('restoreAllWindows', '');
75 } 103 }
76 }; 104 };
77 chrome.app.window.current().onRestored.addListener(restoreHostWindows); 105 chrome.app.window.current().onRestored.addListener(restoreHostWindows);
78 106
79 remoting.windowShape.updateClientWindowShape(); 107 remoting.windowShape.updateClientWindowShape();
80 108
81 // Initialize the context menus. 109 // Initialize the context menus.
82 if (remoting.platformIsChromeOS()) { 110 if (remoting.platformIsChromeOS()) {
83 var adapter = new remoting.ContextMenuChrome(); 111 var adapter = new remoting.ContextMenuChrome();
84 } else { 112 } else {
85 var adapter = new remoting.ContextMenuDom( 113 var adapter = new remoting.ContextMenuDom(
86 document.getElementById('context-menu')); 114 document.getElementById('context-menu'));
87 } 115 }
88 this.contextMenu_ = new remoting.ApplicationContextMenu(adapter); 116 this.contextMenu_ = new remoting.ApplicationContextMenu(adapter);
89 this.keyboardLayoutsMenu_ = new remoting.KeyboardLayoutsMenu(adapter); 117 this.keyboardLayoutsMenu_ = new remoting.KeyboardLayoutsMenu(adapter);
90 this.windowActivationMenu_ = new remoting.WindowActivationMenu(adapter); 118 this.windowActivationMenu_ = new remoting.WindowActivationMenu(adapter);
91 119
92 remoting.LoadingWindow.show(); 120 remoting.LoadingWindow.show();
93 }; 121 };
94 122
95 /** 123 /**
96 * Start the application. Once start() is called, the delegate can assume that 124 * Required for remoting.ApplicationInterface interface.
97 * the user has consented to all permissions specified in the manifest.
98 * 125 *
99 * @param {remoting.SessionConnector} connector 126 * @param {string} token An OAuth access token.
100 * @param {string} token An OAuth access token. The delegate should not cache 127 * @override
101 * this token, but can assume that it will remain valid during application
102 * start-up.
103 */ 128 */
104 remoting.AppRemoting.prototype.start = function(connector, token) { 129 remoting.AppRemoting.prototype.startApplication = function(token) {
105 /** @type {remoting.AppRemoting} */ 130 /** @type {remoting.AppRemoting} */
106 var that = this; 131 var that = this;
107 132
108 /** @param {!remoting.Xhr.Response} xhrResponse */ 133 /** @param {!remoting.Xhr.Response} xhrResponse */
109 var parseAppHostResponse = function(xhrResponse) { 134 var parseAppHostResponse = function(xhrResponse) {
110 if (xhrResponse.status == 200) { 135 if (xhrResponse.status == 200) {
111 var response = /** @type {remoting.AppRemoting.AppHostResponse} */ 136 var response = /** @type {remoting.AppRemoting.AppHostResponse} */
112 (base.jsonParseSafe(xhrResponse.getText())); 137 (base.jsonParseSafe(xhrResponse.getText()));
113 if (response && 138 if (response &&
114 response.status && 139 response.status &&
(...skipping 25 matching lines...) Expand all
140 * @param {function(string, string):void} onThirdPartyTokenFetched 165 * @param {function(string, string):void} onThirdPartyTokenFetched
141 * Callback. 166 * Callback.
142 */ 167 */
143 var fetchThirdPartyToken = function( 168 var fetchThirdPartyToken = function(
144 tokenUrl, hostPublicKey, scope, onThirdPartyTokenFetched) { 169 tokenUrl, hostPublicKey, scope, onThirdPartyTokenFetched) {
145 // Use the authentication tokens returned by the app-remoting server. 170 // Use the authentication tokens returned by the app-remoting server.
146 onThirdPartyTokenFetched(host['authorizationCode'], 171 onThirdPartyTokenFetched(host['authorizationCode'],
147 host['sharedSecret']); 172 host['sharedSecret']);
148 }; 173 };
149 174
150 connector.connectMe2App(host, fetchThirdPartyToken); 175 that.sessionConnector_.connectMe2App(host, fetchThirdPartyToken);
151 } else if (response && response.status == 'pending') { 176 } else if (response && response.status == 'pending') {
152 that.handleError(new remoting.Error( 177 that.onError(new remoting.Error(
153 remoting.Error.Tag.SERVICE_UNAVAILABLE)); 178 remoting.Error.Tag.SERVICE_UNAVAILABLE));
154 } 179 }
155 } else { 180 } else {
156 console.error('Invalid "runApplication" response from server.'); 181 console.error('Invalid "runApplication" response from server.');
157 // TODO(garykac) Start using remoting.Error.fromHttpStatus once it has 182 // TODO(garykac) Start using remoting.Error.fromHttpStatus once it has
158 // been updated to properly report 'unknown' errors (rather than 183 // been updated to properly report 'unknown' errors (rather than
159 // reporting them as AUTHENTICATION_FAILED). 184 // reporting them as AUTHENTICATION_FAILED).
160 if (xhrResponse.status == 0) { 185 if (xhrResponse.status == 0) {
161 that.handleError(new remoting.Error( 186 that.onError(new remoting.Error(
162 remoting.Error.Tag.NETWORK_FAILURE)); 187 remoting.Error.Tag.NETWORK_FAILURE));
163 } else if (xhrResponse.status == 401) { 188 } else if (xhrResponse.status == 401) {
164 that.handleError(new remoting.Error( 189 that.onError(new remoting.Error(
165 remoting.Error.Tag.AUTHENTICATION_FAILED)); 190 remoting.Error.Tag.AUTHENTICATION_FAILED));
166 } else if (xhrResponse.status == 403) { 191 } else if (xhrResponse.status == 403) {
167 that.handleError(new remoting.Error( 192 that.onError(new remoting.Error(
168 remoting.Error.Tag.APP_NOT_AUTHORIZED)); 193 remoting.Error.Tag.APP_NOT_AUTHORIZED));
169 } else if (xhrResponse.status == 502 || xhrResponse.status == 503) { 194 } else if (xhrResponse.status == 502 || xhrResponse.status == 503) {
170 that.handleError(new remoting.Error( 195 that.onError(new remoting.Error(
171 remoting.Error.Tag.SERVICE_UNAVAILABLE)); 196 remoting.Error.Tag.SERVICE_UNAVAILABLE));
172 } else { 197 } else {
173 that.handleError(remoting.Error.unexpected()); 198 that.onError(remoting.Error.unexpected());
174 } 199 }
175 } 200 }
176 }; 201 };
177 202
178 new remoting.Xhr({ 203 new remoting.Xhr({
179 method: 'POST', 204 method: 'POST',
180 url: that.runApplicationUrl(), 205 url: that.runApplicationUrl(),
181 oauthToken: token 206 oauthToken: token
182 }).start().then(parseAppHostResponse); 207 }).start().then(parseAppHostResponse);
183 }; 208 };
184 209
185 /** 210 /**
186 * Report an authentication error to the user. This is called in lieu of start() 211 * Close the loading window before exiting.
187 * if the user cannot be authenticated or if they decline the app permissions.
188 *
189 * @param {!remoting.Error} error The failure reason.
190 */ 212 */
191 remoting.AppRemoting.prototype.signInFailed = function(error) { 213 remoting.AppRemoting.prototype.exit = function() {
192 this.handleError(error); 214 remoting.LoadingWindow.close();
215
216 // Call superclass exit() after we've closed all our windows.
217 remoting.Application.prototype.exit.call(this);
193 }; 218 };
194 219
195 /** 220 /**
196 * @return {string} Application product name to be used in UI.
197 */
198 remoting.AppRemoting.prototype.getApplicationName = function() {
199 var manifest = chrome.runtime.getManifest();
200 return manifest.name;
201 };
202
203 /** @return {string} */
204 remoting.AppRemoting.prototype.runApplicationUrl = function() {
205 return remoting.settings.APP_REMOTING_API_BASE_URL + '/applications/' +
206 remoting.settings.getAppRemotingApplicationId() + '/run';
207 };
208
209 /**
210 * Called when a new session has been connected. 221 * Called when a new session has been connected.
211 * 222 *
212 * @param {remoting.ConnectionInfo} connectionInfo 223 * @param {remoting.ConnectionInfo} connectionInfo
213 * @return {void} Nothing. 224 * @return {void} Nothing.
214 */ 225 */
215 remoting.AppRemoting.prototype.handleConnected = function(connectionInfo) { 226 remoting.AppRemoting.prototype.onConnected = function(connectionInfo) {
227 remoting.Application.prototype.onConnected.call(this, connectionInfo);
228
216 remoting.identity.getUserInfo().then( 229 remoting.identity.getUserInfo().then(
217 function(userInfo) { 230 function(userInfo) {
218 remoting.clientSession.sendClientMessage( 231 remoting.clientSession.sendClientMessage(
219 'setUserDisplayInfo', 232 'setUserDisplayInfo',
220 JSON.stringify({fullName: userInfo.name})); 233 JSON.stringify({fullName: userInfo.name}));
221 }); 234 });
222 235
223 remoting.app.getSessionConnector().registerProtocolExtension(this); 236 this.sessionConnector_.registerProtocolExtension(this);
224 237
225 this.connectedView_ = new remoting.AppConnectedView( 238 this.connectedView_ = new remoting.AppConnectedView(
226 document.getElementById('client-container'), connectionInfo); 239 document.getElementById('client-container'), connectionInfo);
227 240
228 // Map Cmd to Ctrl on Mac since hosts typically use Ctrl for keyboard 241 // Map Cmd to Ctrl on Mac since hosts typically use Ctrl for keyboard
229 // shortcuts, but we want them to act as natively as possible. 242 // shortcuts, but we want them to act as natively as possible.
230 if (remoting.platformIsMac()) { 243 if (remoting.platformIsMac()) {
231 connectionInfo.plugin().setRemapKeys('0x0700e3>0x0700e0,0x0700e7>0x0700e4'); 244 connectionInfo.plugin().setRemapKeys('0x0700e3>0x0700e0,0x0700e7>0x0700e4');
232 } 245 }
233 }; 246 };
234 247
235 /** 248 /**
236 * Called when the current session has been disconnected. 249 * Called when the current session has been disconnected.
237 * 250 *
238 * @return {void} Nothing. 251 * @return {void} Nothing.
239 */ 252 */
240 remoting.AppRemoting.prototype.handleDisconnected = function() { 253 remoting.AppRemoting.prototype.onDisconnected = function() {
254 remoting.Application.prototype.onDisconnected.call(this);
255
241 base.dispose(this.connectedView_); 256 base.dispose(this.connectedView_);
242 this.connectedView_ = null; 257 this.connectedView_ = null;
243 258
244 chrome.app.window.current().close(); 259 chrome.app.window.current().close();
245 }; 260 };
246 261
247 /** 262 /**
248 * Called when the current session's connection has failed. 263 * Called when the current session's connection has failed.
249 * 264 *
250 * @param {remoting.SessionConnector} connector
251 * @param {!remoting.Error} error 265 * @param {!remoting.Error} error
252 * @return {void} Nothing. 266 * @return {void} Nothing.
253 */ 267 */
254 remoting.AppRemoting.prototype.handleConnectionFailed = function( 268 remoting.AppRemoting.prototype.onConnectionFailed = function(error) {
255 connector, error) { 269 remoting.Application.prototype.onConnectionFailed.call(this, error);
256 this.handleError(error); 270
271 this.onError(error);
257 }; 272 };
258 273
259 /** @return {Array<string>} */ 274 /**
275 * Called when an error needs to be displayed to the user.
276 *
277 * @param {!remoting.Error} error The error to be localized and displayed.
278 * @return {void} Nothing.
279 */
280 remoting.AppRemoting.prototype.onError = function(error) {
281 remoting.Application.prototype.onError.call(this, error);
282
283 console.error('Connection failed: ' + error.toString());
284 remoting.LoadingWindow.close();
285 remoting.MessageWindow.showErrorMessage(
286 chrome.i18n.getMessage(/*i18n-content*/'CONNECTION_FAILED'),
287 chrome.i18n.getMessage(error.getTag()));
288 };
289
290
291 /**
292 * Required for remoting.ProtocolExtension interface.
293 *
294 * @return {Array<string>}
295 */
260 remoting.AppRemoting.prototype.getExtensionTypes = function() { 296 remoting.AppRemoting.prototype.getExtensionTypes = function() {
261 return ['openURL', 'onWindowRemoved', 'onWindowAdded', 297 return ['openURL', 'onWindowRemoved', 'onWindowAdded',
262 'onAllWindowsMinimized', 'setKeyboardLayouts', 'pingResponse']; 298 'onAllWindowsMinimized', 'setKeyboardLayouts', 'pingResponse'];
263 }; 299 };
264 300
265 /** 301 /**
302 * Required for remoting.ProtocolExtension interface.
303 *
266 * @param {function(string,string)} sendMessageToHost Callback to send a message 304 * @param {function(string,string)} sendMessageToHost Callback to send a message
267 * to the host. 305 * to the host.
268 */ 306 */
269 remoting.AppRemoting.prototype.startExtension = function(sendMessageToHost) { 307 remoting.AppRemoting.prototype.startExtension = function(sendMessageToHost) {
270 }; 308 };
271 309
272 /** 310 /**
311 * Required for remoting.ProtocolExtension interface.
312 *
273 * @param {string} type The message type. 313 * @param {string} type The message type.
274 * @param {Object} message The parsed extension message data. 314 * @param {Object} message The parsed extension message data.
275 */ 315 */
276 remoting.AppRemoting.prototype.onExtensionMessage = function(type, message) { 316 remoting.AppRemoting.prototype.onExtensionMessage = function(type, message) {
277 switch (type) { 317 switch (type) {
278 318
279 case 'openURL': 319 case 'openURL':
280 // URL requests from the hosted app are untrusted, so disallow anything 320 // URL requests from the hosted app are untrusted, so disallow anything
281 // other than HTTP or HTTPS. 321 // other than HTTP or HTTPS.
282 var url = base.getStringAttr(message, 'url'); 322 var url = base.getStringAttr(message, 'url');
(...skipping 29 matching lines...) Expand all
312 352
313 case 'pingResponse': 353 case 'pingResponse':
314 var then = base.getNumberAttr(message, 'timestamp'); 354 var then = base.getNumberAttr(message, 'timestamp');
315 var now = new Date().getTime(); 355 var now = new Date().getTime();
316 this.contextMenu_.updateConnectionRTT(now - then); 356 this.contextMenu_.updateConnectionRTT(now - then);
317 return true; 357 return true;
318 } 358 }
319 359
320 return false; 360 return false;
321 }; 361 };
322
323 /**
324 * Called when an error needs to be displayed to the user.
325 *
326 * @param {!remoting.Error} error The error to be localized and displayed.
327 * @return {void} Nothing.
328 */
329 remoting.AppRemoting.prototype.handleError = function(error) {
330 console.error('Connection failed: ' + error.toString());
331 remoting.LoadingWindow.close();
332 remoting.MessageWindow.showErrorMessage(
333 chrome.i18n.getMessage(/*i18n-content*/'CONNECTION_FAILED'),
334 chrome.i18n.getMessage(error.getTag()));
335 };
336
337 /**
338 * Close the loading window before exiting.
339 */
340 remoting.AppRemoting.prototype.handleExit = function() {
341 remoting.LoadingWindow.close();
342 };
OLDNEW
« no previous file with comments | « no previous file | remoting/webapp/app_remoting/js/ar_main.js » ('j') | remoting/webapp/base/js/application.js » ('J')

Powered by Google App Engine
This is Rietveld 408576698