| Index: remoting/webapp/me2mom/host_screen.js
|
| diff --git a/remoting/webapp/me2mom/host_screen.js b/remoting/webapp/me2mom/host_screen.js
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..87f614a50307e1b4273878c5ef2d49a8d2938a49
|
| --- /dev/null
|
| +++ b/remoting/webapp/me2mom/host_screen.js
|
| @@ -0,0 +1,269 @@
|
| +// Copyright (c) 2011 The Chromium Authors. All rights reserved.
|
| +// Use of this source code is governed by a BSD-style license that can be
|
| +// found in the LICENSE file.
|
| +
|
| +/**
|
| + * @fileoverview
|
| + * Functions related to the 'host screen' for Chromoting.
|
| + */
|
| +
|
| +'use strict';
|
| +
|
| +/** @suppress {duplicate} */
|
| +var remoting = remoting || {};
|
| +
|
| +(function() {
|
| +
|
| +/**
|
| + * @type {boolean} Whether or not the last share was cancelled by the user.
|
| + * This controls what screen is shown when the host plugin signals
|
| + * completion.
|
| + */
|
| +var lastShareWasCancelled_ = false;
|
| +
|
| +/**
|
| + * Start a host session. This is the main entry point for the host screen,
|
| + * called directly from the onclick action of a button on the home screen.
|
| + */
|
| +remoting.tryShare = function() {
|
| + remoting.debug.log('Attempting to share...');
|
| + lastShareWasCancelled_ = false;
|
| + if (remoting.oauth2.needsNewAccessToken()) {
|
| + remoting.debug.log('Refreshing token...');
|
| + remoting.oauth2.refreshAccessToken(function() {
|
| + if (remoting.oauth2.needsNewAccessToken()) {
|
| + // If we still need it, we're going to infinite loop.
|
| + showShareError_(/*i18n-content*/'ERROR_AUTHENTICATION_FAILED');
|
| + throw 'Unable to get access token';
|
| + }
|
| + remoting.tryShare();
|
| + });
|
| + return;
|
| + }
|
| +
|
| + onNatTraversalPolicyChanged_(true); // Hide warning by default.
|
| + remoting.setMode(remoting.AppMode.HOST_WAITING_FOR_CODE);
|
| + document.getElementById('cancel-button').disabled = false;
|
| + disableTimeoutCountdown_();
|
| +
|
| + var div = document.getElementById('host-plugin-container');
|
| + remoting.hostSession = new remoting.HostSession();
|
| + remoting.hostSession.createPluginAndConnect(
|
| + document.getElementById('host-plugin-container'),
|
| + /** @type {string} */(remoting.oauth2.getCachedEmail()),
|
| + remoting.oauth2.getAccessToken(),
|
| + onNatTraversalPolicyChanged_,
|
| + onHostStateChanged_,
|
| + logDebugInfo_);
|
| +};
|
| +
|
| +/**
|
| + * Callback for the host plugin to notify the web app of state changes.
|
| + * @param {remoting.HostSession.State} state The new state of the plugin.
|
| + */
|
| +function onHostStateChanged_(state) {
|
| + if (state == remoting.HostSession.State.STARTING) {
|
| + // Nothing to do here.
|
| + remoting.debug.log('Host plugin state: STARTING');
|
| +
|
| + } else if (state == remoting.HostSession.State.REQUESTED_ACCESS_CODE) {
|
| + // Nothing to do here.
|
| + remoting.debug.log('Host plugin state: REQUESTED_ACCESS_CODE');
|
| +
|
| + } else if (state == remoting.HostSession.State.RECEIVED_ACCESS_CODE) {
|
| + remoting.debug.log('Host plugin state: RECEIVED_ACCESS_CODE');
|
| + var accessCode = remoting.hostSession.getAccessCode();
|
| + var accessCodeDisplay = document.getElementById('access-code-display');
|
| + accessCodeDisplay.innerText = '';
|
| + // Display the access code in groups of four digits for readability.
|
| + var kDigitsPerGroup = 4;
|
| + for (var i = 0; i < accessCode.length; i += kDigitsPerGroup) {
|
| + var nextFourDigits = document.createElement('span');
|
| + nextFourDigits.className = 'access-code-digit-group';
|
| + nextFourDigits.innerText = accessCode.substring(i, i + kDigitsPerGroup);
|
| + accessCodeDisplay.appendChild(nextFourDigits);
|
| + }
|
| + accessCodeExpiresIn_ = remoting.hostSession.getAccessCodeLifetime();
|
| + if (accessCodeExpiresIn_ > 0) { // Check it hasn't expired.
|
| + accessCodeTimerId_ = setInterval(
|
| + 'remoting.decrementAccessCodeTimeout_()', 1000);
|
| + timerRunning_ = true;
|
| + updateAccessCodeTimeoutElement_();
|
| + updateTimeoutStyles_();
|
| + remoting.setMode(remoting.AppMode.HOST_WAITING_FOR_CONNECTION);
|
| + } else {
|
| + // This can only happen if the cloud tells us that the code lifetime is
|
| + // <= 0s, which shouldn't happen so we don't care how clean this UX is.
|
| + remoting.debug.log('Access code already invalid on receipt!');
|
| + remoting.cancelShare();
|
| + }
|
| +
|
| + } else if (state == remoting.HostSession.State.CONNECTED) {
|
| + remoting.debug.log('Host plugin state: CONNECTED');
|
| + var element = document.getElementById('host-shared-message');
|
| + var client = remoting.hostSession.getClient();
|
| + l10n.localizeElement(element, client);
|
| + remoting.setMode(remoting.AppMode.HOST_SHARED);
|
| + disableTimeoutCountdown_();
|
| +
|
| + } else if (state == remoting.HostSession.State.DISCONNECTING) {
|
| + remoting.debug.log('Host plugin state: DISCONNECTING');
|
| +
|
| + } else if (state == remoting.HostSession.State.DISCONNECTED) {
|
| + remoting.debug.log('Host plugin state: DISCONNECTED');
|
| + if (remoting.currentMode != remoting.AppMode.HOST_SHARE_FAILED) {
|
| + // If an error is being displayed, then the plugin should not be able to
|
| + // hide it by setting the state. Errors must be dismissed by the user
|
| + // clicking OK, which puts the app into mode HOME.
|
| + if (lastShareWasCancelled_) {
|
| + remoting.setMode(remoting.AppMode.HOME);
|
| + } else {
|
| + remoting.setMode(remoting.AppMode.HOST_SHARE_FINISHED);
|
| + }
|
| + }
|
| + remoting.hostSession.removePlugin();
|
| +
|
| + } else if (state == remoting.HostSession.State.ERROR) {
|
| + remoting.debug.log('Host plugin state: ERROR');
|
| + showShareError_(/*i18n-content*/'ERROR_GENERIC');
|
| + } else {
|
| + remoting.debug.log('Unknown state -> ' + state);
|
| + }
|
| +}
|
| +
|
| +/**
|
| + * This is the callback that the host plugin invokes to indicate that there
|
| + * is additional debug log info to display.
|
| + * @param {string} msg The message (which will not be localized) to be logged.
|
| + */
|
| +function logDebugInfo_(msg) {
|
| + remoting.debug.log('plugin: ' + msg);
|
| +}
|
| +
|
| +/**
|
| + * Show a host-side error message.
|
| + *
|
| + * @param {string} errorTag The error message to be localized and displayed.
|
| + * @return {void} Nothing.
|
| + */
|
| +function showShareError_(errorTag) {
|
| + var errorDiv = document.getElementById('host-plugin-error');
|
| + l10n.localizeElementFromTag(errorDiv, errorTag);
|
| + remoting.debug.log('Sharing error: ' + errorTag);
|
| + remoting.setMode(remoting.AppMode.HOST_SHARE_FAILED);
|
| +}
|
| +
|
| +/**
|
| + * Cancel an active or pending share operation.
|
| + *
|
| + * @return {void} Nothing.
|
| + */
|
| +remoting.cancelShare = function() {
|
| + remoting.debug.log('Canceling share...');
|
| + remoting.lastShareWasCancelled = true;
|
| + try {
|
| + remoting.hostSession.disconnect();
|
| + } catch (error) {
|
| + // Hack to force JSCompiler type-safety.
|
| + var errorTyped = /** @type {{description: string}} */ error;
|
| + remoting.debug.log('Error disconnecting: ' + errorTyped.description +
|
| + '. The host plugin probably crashed.');
|
| + // TODO(jamiewalch): Clean this up. We should have a class representing
|
| + // the host plugin, like we do for the client, which should handle crash
|
| + // reporting and it should use a more detailed error message than the
|
| + // default 'generic' one. See crbug.com/94624
|
| + showShareError_(/*i18n-content*/'ERROR_GENERIC');
|
| + }
|
| + disableTimeoutCountdown_();
|
| +};
|
| +
|
| +/**
|
| + * @type {boolean} Whether or not the access code timeout countdown is running.
|
| + */
|
| +var timerRunning_ = false;
|
| +
|
| +/**
|
| + * @type {number} The id of the access code expiry countdown timer.
|
| + */
|
| +var accessCodeTimerId_ = 0;
|
| +
|
| +/**
|
| + * @type {number} The number of seconds until the access code expires.
|
| + */
|
| +var accessCodeExpiresIn_ = 0;
|
| +
|
| +/**
|
| + * The timer callback function, which needs to be visible from the global
|
| + * namespace.
|
| + */
|
| +remoting.decrementAccessCodeTimeout_ = function() {
|
| + --accessCodeExpiresIn_;
|
| + updateAccessCodeTimeoutElement_();
|
| +};
|
| +
|
| +/**
|
| + * Stop the access code timeout countdown if it is running.
|
| + */
|
| +function disableTimeoutCountdown_() {
|
| + if (timerRunning_) {
|
| + clearInterval(accessCodeTimerId_);
|
| + timerRunning_ = false;
|
| + updateTimeoutStyles_();
|
| + }
|
| +}
|
| +
|
| +/**
|
| + * Constants controlling the access code timer countdown display.
|
| + */
|
| +var ACCESS_CODE_TIMER_DISPLAY_THRESHOLD_ = 30;
|
| +var ACCESS_CODE_RED_THRESHOLD_ = 10;
|
| +
|
| +/**
|
| + * Show/hide or restyle various elements, depending on the remaining countdown
|
| + * and timer state.
|
| + *
|
| + * @return {boolean} True if the timeout is in progress, false if it has
|
| + * expired.
|
| + */
|
| +function updateTimeoutStyles_() {
|
| + if (timerRunning_) {
|
| + if (accessCodeExpiresIn_ <= 0) {
|
| + remoting.cancelShare();
|
| + return false;
|
| + }
|
| + if (accessCodeExpiresIn_ <= ACCESS_CODE_RED_THRESHOLD_) {
|
| + addClass(document.getElementById('access-code-display'), 'expiring');
|
| + } else {
|
| + removeClass(document.getElementById('access-code-display'), 'expiring');
|
| + }
|
| + }
|
| + document.getElementById('access-code-countdown').hidden =
|
| + (accessCodeExpiresIn_ > ACCESS_CODE_TIMER_DISPLAY_THRESHOLD_) ||
|
| + !timerRunning_;
|
| + return true;
|
| +}
|
| +
|
| +/**
|
| + * Update the text and appearance of the access code timeout element to
|
| + * reflect the time remaining.
|
| + */
|
| +function updateAccessCodeTimeoutElement_() {
|
| + var pad = (accessCodeExpiresIn_ < 10) ? '0:0' : '0:';
|
| + l10n.localizeElement(document.getElementById('seconds-remaining'),
|
| + pad + accessCodeExpiresIn_);
|
| + if (!updateTimeoutStyles_()) {
|
| + disableTimeoutCountdown_();
|
| + }
|
| +}
|
| +
|
| +/**
|
| + * Callback to show or hide the NAT traversal warning when the policy changes.
|
| + * @param {boolean} enabled True if NAT traversal is enabled.
|
| + * @return {void} Nothing.
|
| + */
|
| +function onNatTraversalPolicyChanged_(enabled) {
|
| + var container = document.getElementById('nat-box-container');
|
| + container.hidden = enabled;
|
| +}
|
| +
|
| +}());
|
|
|