1 // Copyright (c) 2012 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.
7 * Functions related to the 'client screen' for Chromoting.
12 /** @suppress {duplicate} */
13 var remoting
= remoting
|| {};
16 * @type {remoting.SessionConnector} The connector object, set when a connection
19 remoting
.connector
= null;
22 * @type {remoting.ClientSession} The client session object, set once the
23 * connector has invoked its onOk callback.
25 remoting
.clientSession
= null;
28 * Initiate an IT2Me connection.
30 remoting
.connectIT2Me = function() {
31 if (!remoting
.connector
) {
32 remoting
.connector
= new remoting
.SessionConnector(
33 document
.getElementById('session-mode'),
37 var accessCode
= document
.getElementById('access-code-entry').value
;
38 remoting
.setMode(remoting
.AppMode
.CLIENT_CONNECTING
);
39 remoting
.connector
.connectIT2Me(accessCode
);
43 * Update the remoting client layout in response to a resize event.
45 * @return {void} Nothing.
47 remoting
.onResize = function() {
48 if (remoting
.clientSession
) {
49 remoting
.clientSession
.onResize();
54 * Handle changes in the visibility of the window, for example by pausing video.
56 * @return {void} Nothing.
58 remoting
.onVisibilityChanged = function() {
59 if (remoting
.clientSession
) {
60 remoting
.clientSession
.pauseVideo(document
.webkitHidden
);
65 * Disconnect the remoting client.
67 * @return {void} Nothing.
69 remoting
.disconnect = function() {
70 if (!remoting
.clientSession
) {
73 if (remoting
.clientSession
.mode
== remoting
.ClientSession
.Mode
.IT2ME
) {
74 remoting
.setMode(remoting
.AppMode
.CLIENT_SESSION_FINISHED_IT2ME
);
76 remoting
.setMode(remoting
.AppMode
.CLIENT_SESSION_FINISHED_ME2ME
);
78 remoting
.clientSession
.disconnect(true);
79 remoting
.clientSession
= null;
80 console
.log('Disconnected.');
84 * Sends a Ctrl-Alt-Del sequence to the remoting client.
86 * @return {void} Nothing.
88 remoting
.sendCtrlAltDel = function() {
89 if (remoting
.clientSession
) {
90 console
.log('Sending Ctrl-Alt-Del.');
91 remoting
.clientSession
.sendCtrlAltDel();
96 * Sends a Print Screen keypress to the remoting client.
98 * @return {void} Nothing.
100 remoting
.sendPrintScreen = function() {
101 if (remoting
.clientSession
) {
102 console
.log('Sending Print Screen.');
103 remoting
.clientSession
.sendPrintScreen();
108 * Callback function called when the state of the client plugin changes. The
109 * current state is available via the |state| member variable.
111 * @param {number} oldState The previous state of the plugin.
112 * @param {number} newState The current state of the plugin.
114 function onClientStateChange_(oldState
, newState
) {
116 case remoting
.ClientSession
.State
.CLOSED
:
117 console
.log('Connection closed by host');
118 if (remoting
.clientSession
.mode
== remoting
.ClientSession
.Mode
.IT2ME
) {
119 remoting
.setMode(remoting
.AppMode
.CLIENT_SESSION_FINISHED_IT2ME
);
121 remoting
.setMode(remoting
.AppMode
.CLIENT_SESSION_FINISHED_ME2ME
);
125 case remoting
.ClientSession
.State
.FAILED
:
126 var error
= remoting
.clientSession
.getError();
127 console
.error('Client plugin reported connection failed: ' + error
);
129 error
= remoting
.Error
.UNEXPECTED
;
131 showConnectError_(error
);
135 console
.error('Unexpected client plugin state: ' + newState
);
136 // This should only happen if the web-app and client plugin get out of
137 // sync, so MISSING_PLUGIN is a suitable error.
138 showConnectError_(remoting
.Error
.MISSING_PLUGIN
);
141 remoting
.clientSession
.disconnect(false);
142 remoting
.clientSession
.removePlugin();
143 remoting
.clientSession
= null;
147 * Show a client-side error message.
149 * @param {remoting.Error} errorTag The error to be localized and
151 * @return {void} Nothing.
153 function showConnectError_(errorTag
) {
154 console
.error('Connection failed: ' + errorTag
);
155 var errorDiv
= document
.getElementById('connect-error-message');
156 l10n
.localizeElementFromTag(errorDiv
, /** @type {string} */ (errorTag
));
157 remoting
.accessCode
= '';
158 var mode
= remoting
.clientSession
? remoting
.clientSession
.mode
159 : remoting
.connector
.getConnectionMode();
160 if (mode
== remoting
.ClientSession
.Mode
.IT2ME
) {
161 remoting
.setMode(remoting
.AppMode
.CLIENT_CONNECT_FAILED_IT2ME
);
163 remoting
.setMode(remoting
.AppMode
.CLIENT_CONNECT_FAILED_ME2ME
);
168 * Set the text on the buttons shown under the error message so that they are
169 * easy to understand in the case where a successful connection failed, as
170 * opposed to the case where a connection never succeeded.
172 function setConnectionInterruptedButtonsText_() {
173 var button1
= document
.getElementById('client-reconnect-button');
174 l10n
.localizeElementFromTag(button1
, /*i18n-content*/'RECONNECT');
175 button1
.removeAttribute('autofocus');
176 var button2
= document
.getElementById('client-finished-me2me-button');
177 l10n
.localizeElementFromTag(button2
, /*i18n-content*/'OK');
178 button2
.setAttribute('autofocus', 'autofocus');
182 * Timer callback to update the statistics panel.
184 function updateStatistics_() {
185 if (!remoting
.clientSession
||
186 remoting
.clientSession
.state
!= remoting
.ClientSession
.State
.CONNECTED
) {
189 var perfstats
= remoting
.clientSession
.getPerfStats();
190 remoting
.stats
.update(perfstats
);
191 remoting
.clientSession
.logStatistics(perfstats
);
192 // Update the stats once per second.
193 window
.setTimeout(updateStatistics_
, 1000);
197 * Entry-point for Me2Me connections, handling showing of the host-upgrade nag
198 * dialog if necessary.
200 * @param {string} hostId The unique id of the host.
201 * @return {void} Nothing.
203 remoting
.connectMe2Me = function(hostId
) {
204 var host
= remoting
.hostList
.getHostForId(hostId
);
206 showConnectError_(remoting
.Error
.HOST_IS_OFFLINE
);
209 var webappVersion
= chrome
.runtime
.getManifest().version
;
210 if (remoting
.Host
.needsUpdate(host
, webappVersion
)) {
211 var needsUpdateMessage
=
212 document
.getElementById('host-needs-update-message');
213 l10n
.localizeElementFromTag(needsUpdateMessage
,
214 /*i18n-content*/'HOST_NEEDS_UPDATE_TITLE',
216 /** @type {Element} */
217 var connect
= document
.getElementById('host-needs-update-connect-button');
218 /** @type {Element} */
219 var cancel
= document
.getElementById('host-needs-update-cancel-button');
220 /** @param {Event} event */
221 var onClick = function(event
) {
222 connect
.removeEventListener('click', onClick
, false);
223 cancel
.removeEventListener('click', onClick
, false);
224 if (event
.target
== connect
) {
225 remoting
.connectMe2MeHostVersionAcknowledged_(host
);
227 remoting
.setMode(remoting
.AppMode
.HOME
);
230 connect
.addEventListener('click', onClick
, false);
231 cancel
.addEventListener('click', onClick
, false);
232 remoting
.setMode(remoting
.AppMode
.CLIENT_HOST_NEEDS_UPGRADE
);
234 remoting
.connectMe2MeHostVersionAcknowledged_(host
);
239 * Shows PIN entry screen localized to include the host name, and registers
240 * a host-specific one-shot event handler for the form submission.
242 * @param {remoting.Host} host The Me2Me host to which to connect.
243 * @return {void} Nothing.
245 remoting
.connectMe2MeHostVersionAcknowledged_ = function(host
) {
246 if (!remoting
.connector
) {
247 remoting
.connector
= new remoting
.SessionConnector(
248 document
.getElementById('session-mode'),
249 remoting
.onConnected
,
252 remoting
.setMode(remoting
.AppMode
.CLIENT_CONNECTING
);
254 /** @param {function(string):void} onPinFetched */
255 var requestPin = function(onPinFetched
) {
256 /** @type {Element} */
257 var pinForm
= document
.getElementById('pin-form');
258 /** @type {Element} */
259 var pinCancel
= document
.getElementById('cancel-pin-entry-button');
261 * Event handler for both the 'submit' and 'cancel' actions. Using
262 * a single handler for both greatly simplifies the task of making
263 * them one-shot. If separate handlers were used, each would have
264 * to unregister both itself and the other.
266 * @param {Event} event The click or submit event.
268 var onSubmitOrCancel = function(event
) {
269 pinForm
.removeEventListener('submit', onSubmitOrCancel
, false);
270 pinCancel
.removeEventListener('click', onSubmitOrCancel
, false);
271 var pinField
= document
.getElementById('pin-entry');
272 var pin
= pinField
.value
;
274 if (event
.target
== pinForm
) {
275 event
.preventDefault();
276 remoting
.setMode(remoting
.AppMode
.CLIENT_CONNECTING
);
279 remoting
.setMode(remoting
.AppMode
.HOME
);
282 pinForm
.addEventListener('submit', onSubmitOrCancel
, false);
283 pinCancel
.addEventListener('click', onSubmitOrCancel
, false);
285 var message
= document
.getElementById('pin-message');
286 l10n
.localizeElement(message
, host
.hostName
);
287 remoting
.setMode(remoting
.AppMode
.CLIENT_PIN_PROMPT
);
289 remoting
.connector
.connectMe2Me(host
, requestPin
);
292 /** @param {remoting.ClientSession} clientSession */
293 remoting
.onConnected = function(clientSession
) {
294 remoting
.clientSession
= clientSession
;
295 remoting
.clientSession
.setOnStateChange(onClientStateChange_
);
296 setConnectionInterruptedButtonsText_();
297 var connectedTo
= document
.getElementById('connected-to');
298 connectedTo
.innerText
= clientSession
.hostDisplayName
;
299 remoting
.setMode(remoting
.AppMode
.IN_SESSION
);
300 remoting
.toolbar
.center();
301 remoting
.toolbar
.preview();
302 remoting
.clipboard
.startSession();