15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/**
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @fileoverview
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Functions related to the 'client screen' for Chromoting.
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)'use strict';
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/** @suppress {duplicate} */
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)var remoting = remoting || {};
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/**
162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * @type {remoting.SessionConnector} The connector object, set when a connection
172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) *     is initiated.
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)remoting.connector = null;
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/**
222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * @type {remoting.ClientSession} The client session object, set once the
232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) *     connector has invoked its onOk callback.
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)remoting.clientSession = null;
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/**
282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * Initiate an IT2Me connection.
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)remoting.connectIT2Me = function() {
31c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (!remoting.connector) {
32c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    remoting.connector = new remoting.SessionConnector(
33c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        document.getElementById('session-mode'),
34c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        remoting.onConnected,
35c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        showConnectError_);
36c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  var accessCode = document.getElementById('access-code-entry').value;
382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  remoting.setMode(remoting.AppMode.CLIENT_CONNECTING);
392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  remoting.connector.connectIT2Me(accessCode);
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/**
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Update the remoting client layout in response to a resize event.
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @return {void} Nothing.
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)remoting.onResize = function() {
482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (remoting.clientSession) {
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    remoting.clientSession.onResize();
502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/**
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Handle changes in the visibility of the window, for example by pausing video.
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @return {void} Nothing.
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)remoting.onVisibilityChanged = function() {
592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (remoting.clientSession) {
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    remoting.clientSession.pauseVideo(document.webkitHidden);
612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/**
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Disconnect the remoting client.
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @return {void} Nothing.
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)remoting.disconnect = function() {
702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!remoting.clientSession) {
712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return;
722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (remoting.clientSession.mode == remoting.ClientSession.Mode.IT2ME) {
742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    remoting.setMode(remoting.AppMode.CLIENT_SESSION_FINISHED_IT2ME);
752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  } else {
762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    remoting.setMode(remoting.AppMode.CLIENT_SESSION_FINISHED_ME2ME);
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  remoting.clientSession.disconnect(true);
792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  remoting.clientSession = null;
802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  console.log('Disconnected.');
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/**
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Sends a Ctrl-Alt-Del sequence to the remoting client.
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @return {void} Nothing.
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)remoting.sendCtrlAltDel = function() {
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (remoting.clientSession) {
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    console.log('Sending Ctrl-Alt-Del.');
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    remoting.clientSession.sendCtrlAltDel();
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/**
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Sends a Print Screen keypress to the remoting client.
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @return {void} Nothing.
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)remoting.sendPrintScreen = function() {
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (remoting.clientSession) {
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    console.log('Sending Print Screen.');
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    remoting.clientSession.sendPrintScreen();
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/**
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Callback function called when the state of the client plugin changes. The
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * current state is available via the |state| member variable.
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @param {number} oldState The previous state of the plugin.
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @param {number} newState The current state of the plugin.
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)function onClientStateChange_(oldState, newState) {
1152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  switch (newState) {
1162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    case remoting.ClientSession.State.CLOSED:
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      console.log('Connection closed by host');
1182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      if (remoting.clientSession.mode == remoting.ClientSession.Mode.IT2ME) {
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        remoting.setMode(remoting.AppMode.CLIENT_SESSION_FINISHED_IT2ME);
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      } else {
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        remoting.setMode(remoting.AppMode.CLIENT_SESSION_FINISHED_ME2ME);
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
1232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      break;
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    case remoting.ClientSession.State.FAILED:
1262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      var error = remoting.clientSession.getError();
1272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      console.error('Client plugin reported connection failed: ' + error);
1282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      if (error == null) {
1292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        error = remoting.Error.UNEXPECTED;
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
1312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      showConnectError_(error);
1322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      break;
1332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    default:
1352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      console.error('Unexpected client plugin state: ' + newState);
1362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      // This should only happen if the web-app and client plugin get out of
1372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      // sync, so MISSING_PLUGIN is a suitable error.
1382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      showConnectError_(remoting.Error.MISSING_PLUGIN);
1392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      break;
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  remoting.clientSession.disconnect(false);
1422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  remoting.clientSession.removePlugin();
1432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  remoting.clientSession = null;
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/**
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Show a client-side error message.
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @param {remoting.Error} errorTag The error to be localized and
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *     displayed.
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @return {void} Nothing.
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)function showConnectError_(errorTag) {
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  console.error('Connection failed: ' + errorTag);
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  var errorDiv = document.getElementById('connect-error-message');
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  l10n.localizeElementFromTag(errorDiv, /** @type {string} */ (errorTag));
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  remoting.accessCode = '';
1582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  var mode = remoting.clientSession ? remoting.clientSession.mode
1592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                    : remoting.connector.getConnectionMode();
1602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (mode == remoting.ClientSession.Mode.IT2ME) {
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    remoting.setMode(remoting.AppMode.CLIENT_CONNECT_FAILED_IT2ME);
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    remoting.setMode(remoting.AppMode.CLIENT_CONNECT_FAILED_ME2ME);
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/**
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Set the text on the buttons shown under the error message so that they are
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * easy to understand in the case where a successful connection failed, as
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * opposed to the case where a connection never succeeded.
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)function setConnectionInterruptedButtonsText_() {
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  var button1 = document.getElementById('client-reconnect-button');
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  l10n.localizeElementFromTag(button1, /*i18n-content*/'RECONNECT');
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  button1.removeAttribute('autofocus');
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  var button2 = document.getElementById('client-finished-me2me-button');
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  l10n.localizeElementFromTag(button2, /*i18n-content*/'OK');
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  button2.setAttribute('autofocus', 'autofocus');
1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/**
1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Timer callback to update the statistics panel.
1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)function updateStatistics_() {
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!remoting.clientSession ||
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      remoting.clientSession.state != remoting.ClientSession.State.CONNECTED) {
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  var perfstats = remoting.clientSession.getPerfStats();
1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  remoting.stats.update(perfstats);
1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  remoting.clientSession.logStatistics(perfstats);
1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Update the stats once per second.
1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  window.setTimeout(updateStatistics_, 1000);
1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/**
1972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * Entry-point for Me2Me connections, handling showing of the host-upgrade nag
1982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * dialog if necessary.
1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @param {string} hostId The unique id of the host.
2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @return {void} Nothing.
2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
2032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)remoting.connectMe2Me = function(hostId) {
2042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  var host = remoting.hostList.getHostForId(hostId);
2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!host) {
2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    showConnectError_(remoting.Error.HOST_IS_OFFLINE);
2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  var webappVersion = chrome.runtime.getManifest().version;
2102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (remoting.Host.needsUpdate(host, webappVersion)) {
2112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    var needsUpdateMessage =
2122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        document.getElementById('host-needs-update-message');
2132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    l10n.localizeElementFromTag(needsUpdateMessage,
2142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                /*i18n-content*/'HOST_NEEDS_UPDATE_TITLE',
2152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                host.hostName);
2162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    /** @type {Element} */
2172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    var connect = document.getElementById('host-needs-update-connect-button');
2182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    /** @type {Element} */
2192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    var cancel = document.getElementById('host-needs-update-cancel-button');
2202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    /** @param {Event} event */
2212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    var onClick = function(event) {
2222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      connect.removeEventListener('click', onClick, false);
2232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      cancel.removeEventListener('click', onClick, false);
2242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      if (event.target == connect) {
2252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        remoting.connectMe2MeHostVersionAcknowledged_(host);
2262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      } else {
227c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        remoting.setMode(remoting.AppMode.HOME);
2282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      }
2292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
2302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    connect.addEventListener('click', onClick, false);
2312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    cancel.addEventListener('click', onClick, false);
2322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    remoting.setMode(remoting.AppMode.CLIENT_HOST_NEEDS_UPGRADE);
2332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  } else {
2342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    remoting.connectMe2MeHostVersionAcknowledged_(host);
2352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/**
2392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * Shows PIN entry screen localized to include the host name, and registers
2402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * a host-specific one-shot event handler for the form submission.
2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
2422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * @param {remoting.Host} host The Me2Me host to which to connect.
2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @return {void} Nothing.
2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
2452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)remoting.connectMe2MeHostVersionAcknowledged_ = function(host) {
246c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (!remoting.connector) {
247c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    remoting.connector = new remoting.SessionConnector(
248c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        document.getElementById('session-mode'),
249c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        remoting.onConnected,
250c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        showConnectError_);
251c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  remoting.setMode(remoting.AppMode.CLIENT_CONNECTING);
2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
254c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  /**
255c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)   * @param {string} tokenUrl Token-issue URL received from the host.
256c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)   * @param {string} scope OAuth scope to request the token for.
257c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)   * @param {string} hostPublicKey Host public key (DER and Base64 encoded).
258c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)   * @param {function(string, string):void} onThirdPartyTokenFetched Callback.
259c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)   */
260c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  var fetchThirdPartyToken = function(
261c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      tokenUrl, hostPublicKey, scope, onThirdPartyTokenFetched) {
262c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    var thirdPartyTokenFetcher = new remoting.ThirdPartyTokenFetcher(
263c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        tokenUrl, hostPublicKey, scope, host.tokenUrlPatterns,
264c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        onThirdPartyTokenFetched);
265c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    thirdPartyTokenFetcher.fetchToken();
266c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  };
267c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
26890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  /**
26990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)   * @param {boolean} supportsPairing
27090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)   * @param {function(string):void} onPinFetched
27190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)   */
27290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  var requestPin = function(supportsPairing, onPinFetched) {
2732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    /** @type {Element} */
2742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    var pinForm = document.getElementById('pin-form');
275c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    /** @type {Element} */
276c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    var pinCancel = document.getElementById('cancel-pin-entry-button');
277868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    /** @type {Element} */
278868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    var rememberPin = document.getElementById('remember-pin');
279868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    /** @type {Element} */
280868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    var rememberPinCheckbox = document.getElementById('remember-pin-checkbox');
281c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    /**
282c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)     * Event handler for both the 'submit' and 'cancel' actions. Using
283c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)     * a single handler for both greatly simplifies the task of making
284c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)     * them one-shot. If separate handlers were used, each would have
285c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)     * to unregister both itself and the other.
286c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)     *
287c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)     * @param {Event} event The click or submit event.
288c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)     */
289c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    var onSubmitOrCancel = function(event) {
290c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      pinForm.removeEventListener('submit', onSubmitOrCancel, false);
291c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      pinCancel.removeEventListener('click', onSubmitOrCancel, false);
292c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      var pinField = document.getElementById('pin-entry');
293c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      var pin = pinField.value;
294c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      pinField.value = '';
295c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      if (event.target == pinForm) {
296c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        event.preventDefault();
297eee4ebda36ebfcb751dd752751c071ef22e33b33Torne (Richard Coles)
298eee4ebda36ebfcb751dd752751c071ef22e33b33Torne (Richard Coles)        // Set the focus away from the password field. This has to be done
299eee4ebda36ebfcb751dd752751c071ef22e33b33Torne (Richard Coles)        // before the password field gets hidden, to work around a Blink
300eee4ebda36ebfcb751dd752751c071ef22e33b33Torne (Richard Coles)        // clipboard-handling bug - http://crbug.com/281523.
301eee4ebda36ebfcb751dd752751c071ef22e33b33Torne (Richard Coles)        document.getElementById('pin-connect-button').focus();
302eee4ebda36ebfcb751dd752751c071ef22e33b33Torne (Richard Coles)
303c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        remoting.setMode(remoting.AppMode.CLIENT_CONNECTING);
304c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        onPinFetched(pin);
305868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        if (/** @type {boolean} */(rememberPinCheckbox.checked)) {
306868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)          remoting.connector.pairingRequested = true;
307868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        }
308c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      } else {
309c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        remoting.setMode(remoting.AppMode.HOME);
310c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      }
3112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    };
312c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    pinForm.addEventListener('submit', onSubmitOrCancel, false);
313c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    pinCancel.addEventListener('click', onSubmitOrCancel, false);
31490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    rememberPin.hidden = !supportsPairing;
315868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    rememberPinCheckbox.checked = false;
3162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    var message = document.getElementById('pin-message');
3172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    l10n.localizeElement(message, host.hostName);
3182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    remoting.setMode(remoting.AppMode.CLIENT_PIN_PROMPT);
3192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  };
320868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
321868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  /** @param {Object} settings */
322868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  var connectMe2MeHostSettingsRetrieved = function(settings) {
323868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    /** @type {string} */
324868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    var clientId = '';
325868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    /** @type {string} */
326868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    var sharedSecret = '';
327868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    var pairingInfo = /** @type {Object} */ (settings['pairingInfo']);
328868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    if (pairingInfo) {
329868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      clientId = /** @type {string} */ (pairingInfo['clientId']);
330868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      sharedSecret = /** @type {string} */ (pairingInfo['sharedSecret']);
331868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    }
332868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    remoting.connector.connectMe2Me(host, requestPin, fetchThirdPartyToken,
333868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                    clientId, sharedSecret);
334868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
335868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
336868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  remoting.HostSettings.load(host.hostId, connectMe2MeHostSettingsRetrieved);
3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)/** @param {remoting.ClientSession} clientSession */
3402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)remoting.onConnected = function(clientSession) {
3412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  remoting.clientSession = clientSession;
3422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  remoting.clientSession.setOnStateChange(onClientStateChange_);
3432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  setConnectionInterruptedButtonsText_();
3442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  var connectedTo = document.getElementById('connected-to');
3452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  connectedTo.innerText = clientSession.hostDisplayName;
3462385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch  document.getElementById('access-code-entry').value = '';
3472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  remoting.setMode(remoting.AppMode.IN_SESSION);
3482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  remoting.toolbar.center();
3492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  remoting.toolbar.preview();
3502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  remoting.clipboard.startSession();
3512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  updateStatistics_();
352868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (remoting.connector.pairingRequested) {
353868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    /**
354868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)     * @param {string} clientId
355868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)     * @param {string} sharedSecret
356868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)     */
357868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    var onPairingComplete = function(clientId, sharedSecret) {
358868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      var pairingInfo = {
359868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        pairingInfo: {
360868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)          clientId: clientId,
361868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)          sharedSecret: sharedSecret
362868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        }
363868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      };
364868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      remoting.HostSettings.save(clientSession.hostId, pairingInfo);
3654311e82a78ceafbe0585f51d4c8a86df9f21aa0dBen Murdoch      remoting.connector.updatePairingInfo(clientId, sharedSecret);
366868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    };
367a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch    // Use the platform name as a proxy for the local computer name.
368a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch    // TODO(jamiewalch): Use a descriptive name for the local computer, for
369a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch    // example, its Chrome Sync name.
370a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch    var clientName = '';
371a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch    if (navigator.platform.indexOf('Mac') != -1) {
372a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch      clientName = 'Mac';
373a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch    } else if (navigator.platform.indexOf('Win32') != -1) {
374a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch      clientName = 'Windows';
375a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch    } else if (navigator.userAgent.match(/\bCrOS\b/)) {
376a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch      clientName = 'ChromeOS';
377a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch    } else if (navigator.platform.indexOf('Linux') != -1) {
378a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch      clientName = 'Linux';
379a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch    } else {
380a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch      console.log('Unrecognized client platform. Using navigator.platform.');
381a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch      clientName = navigator.platform;
382a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch    }
383a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch    clientSession.requestPairing(clientName, onPairingComplete);
384868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
3852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)};
386