Separate Simple Backend creation from initialization.
[chromium-blink-merge.git] / remoting / webapp / client_screen.js
blob77ff7ecbf07e14ab1ba9ea027e16da85b75b23f0
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.
5 /**
6 * @fileoverview
7 * Functions related to the 'client screen' for Chromoting.
8 */
10 'use strict';
12 /** @suppress {duplicate} */
13 var remoting = remoting || {};
15 /**
16 * @type {remoting.SessionConnector} The connector object, set when a connection
17 * is initiated.
19 remoting.connector = null;
21 /**
22 * @type {remoting.ClientSession} The client session object, set once the
23 * connector has invoked its onOk callback.
25 remoting.clientSession = null;
27 /**
28 * Initiate an IT2Me connection.
30 remoting.connectIT2Me = function() {
31 if (!remoting.connector) {
32 remoting.connector = new remoting.SessionConnector(
33 document.getElementById('session-mode'),
34 remoting.onConnected,
35 showConnectError_);
37 var accessCode = document.getElementById('access-code-entry').value;
38 remoting.setMode(remoting.AppMode.CLIENT_CONNECTING);
39 remoting.connector.connectIT2Me(accessCode);
42 /**
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();
53 /**
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);
64 /**
65 * Disconnect the remoting client.
67 * @return {void} Nothing.
69 remoting.disconnect = function() {
70 if (!remoting.clientSession) {
71 return;
73 if (remoting.clientSession.mode == remoting.ClientSession.Mode.IT2ME) {
74 remoting.setMode(remoting.AppMode.CLIENT_SESSION_FINISHED_IT2ME);
75 } else {
76 remoting.setMode(remoting.AppMode.CLIENT_SESSION_FINISHED_ME2ME);
78 remoting.clientSession.disconnect(true);
79 remoting.clientSession = null;
80 console.log('Disconnected.');
83 /**
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();
95 /**
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) {
115 switch (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);
120 } else {
121 remoting.setMode(remoting.AppMode.CLIENT_SESSION_FINISHED_ME2ME);
123 break;
125 case remoting.ClientSession.State.FAILED:
126 var error = remoting.clientSession.getError();
127 console.error('Client plugin reported connection failed: ' + error);
128 if (error == null) {
129 error = remoting.Error.UNEXPECTED;
131 showConnectError_(error);
132 break;
134 default:
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);
139 break;
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
150 * displayed.
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);
162 } else {
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) {
187 return;
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);
205 if (!host) {
206 showConnectError_(remoting.Error.HOST_IS_OFFLINE);
207 return;
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',
215 host.hostName);
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);
226 } else {
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);
233 } else {
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,
250 showConnectError_);
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;
273 pinField.value = '';
274 if (event.target == pinForm) {
275 event.preventDefault();
276 remoting.setMode(remoting.AppMode.CLIENT_CONNECTING);
277 onPinFetched(pin);
278 } else {
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();
303 updateStatistics_();