Revert of [Webapp Refactor] Remove remoting.SessionConnector. (patchset #3 id:60001...
[chromium-blink-merge.git] / remoting / webapp / crd / js / me2me_activity.js
blob7f91246c40bb343a8860682cca48360e58b9f519
1 // Copyright 2015 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.
5 /** @suppress {duplicate} */
6 var remoting = remoting || {};
8 (function() {
10 'use strict';
12 /**
13  * @param {remoting.Host} host
14  *
15  * @constructor
16  * @implements {remoting.Activity}
17  */
18 remoting.Me2MeActivity = function(host) {
19   /** @private */
20   this.host_ = host;
21   /** @private */
22   this.pinDialog_ =
23       new remoting.PinDialog(document.getElementById('pin-dialog'), host);
24   /** @private */
25   this.hostUpdateDialog_ = new remoting.HostNeedsUpdateDialog(
26       document.getElementById('host-needs-update-dialog'), this.host_);
28   /** @private */
29   this.retryOnHostOffline_ = true;
31   /** @private {remoting.SmartReconnector} */
32   this.reconnector_ = null;
34   /** @private {remoting.DesktopRemotingActivity} */
35   this.desktopActivity_ = null;
38 remoting.Me2MeActivity.prototype.dispose = function() {
39   base.dispose(this.desktopActivity_);
40   this.desktopActivity_ = null;
43 remoting.Me2MeActivity.prototype.start = function() {
44   var webappVersion = chrome.runtime.getManifest().version;
45   var that = this;
47   this.hostUpdateDialog_.showIfNecessary(webappVersion).then(function() {
48     return that.host_.options.load();
49   }).then(function() {
50     that.connect_(true);
51   }).catch(function(/** remoting.Error */ error) {
52     if (error.hasTag(remoting.Error.Tag.CANCELLED)) {
53       remoting.setMode(remoting.AppMode.HOME);
54     }
55   });
58 remoting.Me2MeActivity.prototype.stop = function() {
59   this.desktopActivity_.stop();
62 /** @return {remoting.DesktopRemotingActivity} */
63 remoting.Me2MeActivity.prototype.getDesktopActivity = function() {
64   return this.desktopActivity_;
67 /**
68  * @param {boolean} suppressHostOfflineError
69  * @private
70  */
71 remoting.Me2MeActivity.prototype.connect_ = function(suppressHostOfflineError) {
72   remoting.setMode(remoting.AppMode.CLIENT_CONNECTING);
73   base.dispose(this.desktopActivity_);
74   this.desktopActivity_ = new remoting.DesktopRemotingActivity(this);
75   var connector = remoting.SessionConnector.factory.createConnector(
76         document.getElementById('client-container'),
77         remoting.app_capabilities(),
78         this.desktopActivity_);
80   connector.connect(
81       remoting.Application.Mode.ME2ME,
82       this.host_, this.createCredentialsProvider_(), suppressHostOfflineError);
85 /**
86  * @return {remoting.CredentialsProvider}
87  * @private
88  */
89 remoting.Me2MeActivity.prototype.createCredentialsProvider_ = function() {
90   var host = this.host_;
91   var that = this;
93   /**
94    * @param {string} tokenUrl Token-issue URL received from the host.
95    * @param {string} hostPublicKey Host public key (DER and Base64 encoded).
96    * @param {string} scope OAuth scope to request the token for.
97    * @param {function(string, string):void} onThirdPartyTokenFetched Callback.
98    */
99   var fetchThirdPartyToken = function(
100       tokenUrl, hostPublicKey, scope, onThirdPartyTokenFetched) {
101     var thirdPartyTokenFetcher = new remoting.ThirdPartyTokenFetcher(
102         tokenUrl, hostPublicKey, scope, host.tokenUrlPatterns,
103         onThirdPartyTokenFetched);
104     thirdPartyTokenFetcher.fetchToken();
105   };
107   /**
108    * @param {boolean} supportsPairing
109    * @param {function(string):void} onPinFetched
110    */
111   var requestPin = function(supportsPairing, onPinFetched) {
112     that.pinDialog_.show(supportsPairing).then(function(/** string */ pin) {
113       remoting.setMode(remoting.AppMode.CLIENT_CONNECTING);
114       onPinFetched(pin);
115     }).catch(function(/** remoting.Error */ error) {
116       base.debug.assert(error.hasTag(remoting.Error.Tag.CANCELLED));
117       remoting.setMode(remoting.AppMode.HOME);
118     });
119   };
121   return new remoting.CredentialsProvider({
122     fetchPin: requestPin,
123     pairingInfo: /** @type{remoting.PairingInfo} */ (
124         base.deepCopy(host.options.pairingInfo)),
125     fetchThirdPartyToken: fetchThirdPartyToken
126   });
130  * @param {!remoting.Error} error
131  */
132 remoting.Me2MeActivity.prototype.onConnectionFailed = function(error) {
133   if (error.hasTag(remoting.Error.Tag.HOST_IS_OFFLINE) &&
134       this.retryOnHostOffline_) {
135     var that = this;
136     var onHostListRefresh = function(/** boolean */ success) {
137       if (success) {
138         // Get the host from the hostList for the refreshed JID.
139         that.host_ = remoting.hostList.getHostForId(that.host_.hostId);
140         that.connect_(false);
141         return;
142       }
143       that.onError(error);
144     };
145     this.retryOnHostOffline_ = false;
147     // The plugin will be re-created when the host finished refreshing
148     remoting.hostList.refresh(onHostListRefresh);
149   } else {
150     this.onError(error);
151   }
155  * @param {!remoting.ConnectionInfo} connectionInfo
156  */
157 remoting.Me2MeActivity.prototype.onConnected = function(connectionInfo) {
158   // Reset the refresh flag so that the next connection will retry if needed.
159   this.retryOnHostOffline_ = true;
161   var plugin = connectionInfo.plugin();
162   if (plugin.hasCapability(remoting.ClientSession.Capability.CAST)) {
163     plugin.extensions().register(new remoting.CastExtensionHandler());
164   }
165   plugin.extensions().register(new remoting.GnubbyAuthHandler());
166   this.pinDialog_.requestPairingIfNecessary(connectionInfo.plugin());
168   base.dispose(this.reconnector_);
169   this.reconnector_ = new remoting.SmartReconnector(
170       this.connect_.bind(this, false),
171       this.stop.bind(this),
172       connectionInfo.session());
175 remoting.Me2MeActivity.prototype.onDisconnected = function() {
176   this.showFinishDialog_(remoting.AppMode.CLIENT_SESSION_FINISHED_ME2ME);
180  * @param {!remoting.Error} error
181  */
182 remoting.Me2MeActivity.prototype.onError = function(error) {
183   var errorDiv = document.getElementById('connect-error-message');
184   l10n.localizeElementFromTag(errorDiv, error.getTag());
185   this.showFinishDialog_(remoting.AppMode.CLIENT_CONNECT_FAILED_ME2ME);
189  * @param {remoting.AppMode} mode
190  * @private
191  */
192 remoting.Me2MeActivity.prototype.showFinishDialog_ = function(mode) {
193   var dialog = new remoting.MessageDialog(
194       mode,
195       document.getElementById('client-finished-me2me-button'),
196       document.getElementById('client-reconnect-button'));
198   /** @typedef {remoting.MessageDialog.Result} */
199   var Result = remoting.MessageDialog.Result;
200   var that = this;
202   dialog.show().then(function(/** Result */result) {
203     if (result === Result.PRIMARY) {
204       remoting.setMode(remoting.AppMode.HOME);
205     } else {
206       that.connect_(true);
207     }
208   });
212  * @param {HTMLElement} rootElement
213  * @param {remoting.Host} host
214  * @constructor
215  */
216 remoting.HostNeedsUpdateDialog = function(rootElement, host) {
217   /** @private */
218   this.host_ = host;
219   /** @private */
220   this.dialog_ = new remoting.MessageDialog(
221       remoting.AppMode.CLIENT_HOST_NEEDS_UPGRADE,
222       rootElement.querySelector('.connect-button'),
223       rootElement.querySelector('.cancel-button'));
225   l10n.localizeElementFromTag(
226       rootElement.querySelector('.host-needs-update-message'),
227       /*i18n-content*/'HOST_NEEDS_UPDATE_TITLE', host.hostName);
231  * Shows the HostNeedsUpdateDialog if the user is trying to connect to a legacy
232  * host.
234  * @param {string} webappVersion
235  * @return {Promise}  Promise that resolves when no update is required or
236  *    when the user ignores the update warning.  Rejects with
237  *    |remoting.Error.CANCELLED| if the user cancels the connection.
238  */
239 remoting.HostNeedsUpdateDialog.prototype.showIfNecessary =
240     function(webappVersion) {
241   if (!remoting.Host.needsUpdate(this.host_, webappVersion)) {
242     return Promise.resolve();
243   }
244   /** @typedef {remoting.MessageDialog.Result} */
245   var Result = remoting.MessageDialog.Result;
246   return this.dialog_.show().then(function(/** Result */ result) {
247     if (result === Result.SECONDARY) {
248       return Promise.reject(new remoting.Error(remoting.Error.Tag.CANCELLED));
249     }
250   });
254  * @param {HTMLElement} rootElement
255  * @param {remoting.Host} host
256  * @constructor
257  */
258 remoting.PinDialog = function(rootElement, host) {
259   /** @private */
260   this.rootElement_ = rootElement;
261   /** @private */
262   this.pairingCheckbox_ = rootElement.querySelector('.pairing-checkbox');
263   /** @private */
264   this.pinInput_ = rootElement.querySelector('.pin-inputField');
265   /** @private */
266   this.host_ = host;
267   /** @private */
268   this.dialog_ = new remoting.InputDialog(
269     remoting.AppMode.CLIENT_PIN_PROMPT,
270     this.rootElement_.querySelector('form'),
271     this.pinInput_,
272     this.rootElement_.querySelector('.cancel-button'));
277  * @param {boolean} supportsPairing
278  * @return {Promise<string>}  Promise that resolves with the PIN or rejects with
279  *    |remoting.Error.CANCELLED| if the user cancels the connection.
280  */
281 remoting.PinDialog.prototype.show = function(supportsPairing) {
282   // Reset the UI.
283   this.pairingCheckbox_.checked = false;
284   this.rootElement_.querySelector('.pairing-section').hidden = !supportsPairing;
285   var message = this.rootElement_.querySelector('.pin-message');
286   l10n.localizeElement(message, this.host_.hostName);
287   this.pinInput_.value = '';
288   return this.dialog_.show();
292  * @param {remoting.ClientPlugin} plugin
293  */
294 remoting.PinDialog.prototype.requestPairingIfNecessary = function(plugin) {
295   if (this.pairingCheckbox_.checked) {
296     var that = this;
297     /**
298      * @param {string} clientId
299      * @param {string} sharedSecret
300      */
301     var onPairingComplete = function(clientId, sharedSecret) {
302       that.host_.options.pairingInfo.clientId = clientId;
303       that.host_.options.pairingInfo.sharedSecret = sharedSecret;
304       that.host_.options.save();
305     };
307     // Use the platform name as a proxy for the local computer name.
308     // TODO(jamiewalch): Use a descriptive name for the local computer, for
309     // example, its Chrome Sync name.
310     var clientName = '';
311     if (remoting.platformIsMac()) {
312       clientName = 'Mac';
313     } else if (remoting.platformIsWindows()) {
314       clientName = 'Windows';
315     } else if (remoting.platformIsChromeOS()) {
316       clientName = 'ChromeOS';
317     } else if (remoting.platformIsLinux()) {
318       clientName = 'Linux';
319     } else {
320       console.log('Unrecognized client platform. Using navigator.platform.');
321       clientName = navigator.platform;
322     }
323     plugin.requestPairing(clientName, onPairingComplete);
324   }
327 })();