Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1582)

Unified Diff: remoting/webapp/me2mom/remoting.js

Issue 8416007: Refactored web-app (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Added consistency comment. Moved debug log keyboard shortcut handling. Created 9 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: remoting/webapp/me2mom/remoting.js
diff --git a/remoting/webapp/me2mom/remoting.js b/remoting/webapp/me2mom/remoting.js
index 2f4250b0fe2d8ee6252c9a757a34a145cfc5ae69..3e86b05c8af7746b7a53f9ee031ae9773f230be7 100644
--- a/remoting/webapp/me2mom/remoting.js
+++ b/remoting/webapp/me2mom/remoting.js
@@ -7,202 +7,31 @@
/** @suppress {duplicate} */
var remoting = remoting || {};
-/**
- * Whether or not the plugin should scale itself.
- * @type {boolean}
- */
-remoting.scaleToFit = false;
-
-/** @type {remoting.ClientSession} */
-remoting.session = null;
-
-/** @type {string} */ remoting.accessCode = '';
-/** @type {number} */ remoting.accessCodeTimerId = 0;
-/** @type {number} */ remoting.accessCodeExpiresIn = 0;
-/** @type {remoting.AppMode} */ remoting.currentMode;
-/** @type {string} */ remoting.hostJid = '';
-/** @type {string} */ remoting.hostPublicKey = '';
-/** @type {boolean} */ remoting.lastShareWasCancelled = false;
-/** @type {boolean} */ remoting.timerRunning = false;
-/** @type {string} */ remoting.username = '';
-
-/** @enum {string} */
-remoting.AppMode = {
- HOME: 'home',
- UNAUTHENTICATED: 'auth',
- CLIENT: 'client',
- CLIENT_UNCONNECTED: 'client.unconnected',
- CLIENT_CONNECTING: 'client.connecting',
- CLIENT_CONNECT_FAILED: 'client.connect-failed',
- CLIENT_SESSION_FINISHED: 'client.session-finished',
- HOST: 'host',
- HOST_WAITING_FOR_CODE: 'host.waiting-for-code',
- HOST_WAITING_FOR_CONNECTION: 'host.waiting-for-connection',
- HOST_SHARED: 'host.shared',
- HOST_SHARE_FAILED: 'host.share-failed',
- HOST_SHARE_FINISHED: 'host.share-finished',
- IN_SESSION: 'in-session'
-};
+/** @type {remoting.HostSession} */ remoting.hostSession = null;
(function() {
-window.addEventListener('blur', pluginLostFocus_, false);
-
-function pluginLostFocus_() {
- // If the plug loses input focus, release all keys as a precaution against
- // leaving them 'stuck down' on the host.
- if (remoting.session && remoting.session.plugin) {
- remoting.session.plugin.releaseAllKeys();
- }
-}
-
-/** @type {string} */
-remoting.HOST_PLUGIN_ID = 'host-plugin-id';
-
-/** @enum {string} */
-remoting.ClientError = {
- NO_RESPONSE: /*i18n-content*/'ERROR_NO_RESPONSE',
- INVALID_ACCESS_CODE: /*i18n-content*/'ERROR_INVALID_ACCESS_CODE',
- MISSING_PLUGIN: /*i18n-content*/'ERROR_MISSING_PLUGIN',
- OAUTH_FETCH_FAILED: /*i18n-content*/'ERROR_AUTHENTICATION_FAILED',
- HOST_IS_OFFLINE: /*i18n-content*/'ERROR_HOST_IS_OFFLINE',
- INCOMPATIBLE_PROTOCOL: /*i18n-content*/'ERROR_INCOMPATIBLE_PROTOCOL',
- BAD_PLUGIN_VERSION: /*i18n-content*/'ERROR_BAD_PLUGIN_VERSION',
- OTHER_ERROR: /*i18n-content*/'ERROR_GENERIC'
-};
-
-// Constants representing keys used for storing persistent application state.
-var KEY_APP_MODE_ = 'remoting-app-mode';
-var KEY_EMAIL_ = 'remoting-email';
-var KEY_USE_P2P_API_ = 'remoting-use-p2p-api';
-
-// Some constants for pretty-printing the access code.
-/** @type {number} */ var kSupportIdLen = 7;
-/** @type {number} */ var kHostSecretLen = 5;
-/** @type {number} */ var kAccessCodeLen = kSupportIdLen + kHostSecretLen;
-/** @type {number} */ var kDigitsPerGroup = 4;
-
/**
- * @param {string} classes A space-separated list of classes.
- * @param {string} cls The class to check for.
- * @return {boolean} True if |cls| is found within |classes|.
+ * Entry point for app initialization.
*/
-function hasClass(classes, cls) {
- return classes.match(new RegExp('(\\s|^)' + cls + '(\\s|$)')) != null;
-}
-
-/**
- * @param {Element} element The element to which to add the class.
- * @param {string} cls The new class.
- * @return {void} Nothing.
- */
-function addClass(element, cls) {
- if (!hasClass(element.className, cls)) {
- var padded = element.className == '' ? '' : element.className + ' ';
- element.className = padded + cls;
- }
-}
-
-/**
- * @param {Element} element The element from which to remove the class.
- * @param {string} cls The new class.
- * @return {void} Nothing.
- */
-function removeClass(element, cls) {
- element.className =
- element.className.replace(new RegExp('\\b' + cls + '\\b', 'g'), '')
- .replace(' ', ' ');
-}
-
-function retrieveEmail_(access_token) {
- var headers = {
- 'Authorization': 'OAuth ' + remoting.oauth2.getAccessToken()
- };
-
- /** @param {XMLHttpRequest} xhr The XHR response. */
- var onResponse = function(xhr) {
- if (xhr.status != 200) {
- // TODO(ajwong): Have a better way of showing an error.
- remoting.debug.log('Unable to get email');
- document.getElementById('current-email').innerText = '???';
- return;
- }
-
- // TODO(ajwong): See if we can't find a JSON endpoint.
- setEmail(xhr.responseText.split('&')[0].split('=')[1]);
- };
-
- // TODO(ajwong): Update to new v2 API.
- remoting.xhr.get('https://www.googleapis.com/userinfo/email',
- onResponse, '', headers);
-}
-
-function refreshEmail_() {
- if (!getEmail() && remoting.oauth2.isAuthenticated()) {
- remoting.oauth2.callWithToken(retrieveEmail_);
- }
-}
-
-/**
- * @param {string} value The email address to place in local storage.
- * @return {void} Nothing.
- */
-function setEmail(value) {
- window.localStorage.setItem(KEY_EMAIL_, value);
- document.getElementById('current-email').innerText = value;
-}
-
-/**
- * @return {?string} The email address associated with the auth credentials.
- */
-function getEmail() {
- var result = window.localStorage.getItem(KEY_EMAIL_);
- return typeof result == 'string' ? result : null;
-}
-
-function exchangedCodeForToken_() {
- if (!remoting.oauth2.isAuthenticated()) {
- alert('Your OAuth2 token was invalid. Please try again.');
- }
- /** @param {string} token The auth token. */
- var retrieveEmail = function(token) { retrieveEmail_(token); }
- remoting.oauth2.callWithToken(retrieveEmail);
-}
-
-remoting.clearOAuth2 = function() {
- remoting.oauth2.clear();
- window.localStorage.removeItem(KEY_EMAIL_);
- remoting.setMode(remoting.AppMode.UNAUTHENTICATED);
-}
-
-remoting.toggleDebugLog = function() {
- var debugLog = document.getElementById('debug-log');
- if (debugLog.hidden) {
- debugLog.hidden = false;
- } else {
- debugLog.hidden = true;
- }
-}
-
remoting.init = function() {
l10n.localize();
var button = document.getElementById('toggle-scaling');
button.title = chrome.i18n.getMessage(/*i18n-content*/'TOOLTIP_SCALING');
// Create global objects.
remoting.oauth2 = new remoting.OAuth2();
- remoting.debug =
- new remoting.DebugLog(document.getElementById('debug-messages'));
- /** @type {XMLHttpRequest} */
- remoting.supportHostsXhr = null;
+ remoting.debug = new remoting.DebugLog(
+ document.getElementById('debug-messages'),
+ document.getElementById('statistics'));
refreshEmail_();
- var email = getEmail();
+ var email = remoting.oauth2.getCachedEmail();
if (email) {
document.getElementById('current-email').innerText = email;
}
- remoting.setMode(getAppStartupMode());
- if (isHostModeSupported()) {
+ remoting.setMode(getAppStartupMode_());
+ if (isHostModeSupported_()) {
var unsupported = document.getElementById('client-footer-text-cros');
unsupported.parentNode.removeChild(unsupported);
} else {
@@ -211,553 +40,106 @@ remoting.init = function() {
document.getElementById('client-footer-text-cros').id =
'client-footer-text';
}
-}
-
-/**
- * Change the app's modal state to |mode|, which is considered to be a dotted
- * hierachy of modes. For example, setMode('host.shared') will show any modal
- * elements with an data-ui-mode attribute of 'host' or 'host.shared' and hide
- * all others.
- *
- * @param {remoting.AppMode} mode The new modal state, expressed as a dotted
- * hiearchy.
- */
-remoting.setMode = function(mode) {
- var modes = mode.split('.');
- for (var i = 1; i < modes.length; ++i)
- modes[i] = modes[i - 1] + '.' + modes[i];
- var elements = document.querySelectorAll('[data-ui-mode]');
- for (var i = 0; i < elements.length; ++i) {
- /** @type {Element} */ var element = elements[i];
- var hidden = true;
- for (var m = 0; m < modes.length; ++m) {
- if (hasClass(element.getAttribute('data-ui-mode'), modes[m])) {
- hidden = false;
- break;
- }
- }
- element.hidden = hidden;
- }
- remoting.debug.log('App mode: ' + mode);
- remoting.currentMode = mode;
- if (mode == remoting.AppMode.IN_SESSION) {
- document.removeEventListener('keydown', remoting.checkHotkeys, false);
- } else {
- document.addEventListener('keydown', remoting.checkHotkeys, false);
- }
-}
-
-/**
- * Get the major mode that the app is running in.
- * @return {string} The app's current major mode.
- */
-remoting.getMajorMode = function() {
- return remoting.currentMode.split('.')[0];
-}
-
-remoting.tryShare = function() {
- remoting.debug.log('Attempting to share...');
- remoting.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;
- }
-
- remoting.setMode(remoting.AppMode.HOST_WAITING_FOR_CODE);
- document.getElementById('cancel-button').disabled = false;
- disableTimeoutCountdown_();
-
- var div = document.getElementById('host-plugin-container');
- var plugin = /** @type {remoting.HostPlugin} */
- document.createElement('embed');
- plugin.type = remoting.PLUGIN_MIMETYPE;
- plugin.id = remoting.HOST_PLUGIN_ID;
- // Hiding the plugin means it doesn't load, so make it size zero instead.
- plugin.width = 0;
- plugin.height = 0;
- div.appendChild(plugin);
- onNatTraversalPolicyChanged_(true); // Hide warning by default.
- plugin.onNatTraversalPolicyChanged = onNatTraversalPolicyChanged_;
- plugin.onStateChanged = onStateChanged_;
- plugin.logDebugInfo = debugInfoCallback_;
- plugin.localize(chrome.i18n.getMessage);
- plugin.connect(/** @type {string} */ (getEmail()),
- 'oauth2:' + remoting.oauth2.getAccessToken());
-}
-function disableTimeoutCountdown_() {
- if (remoting.timerRunning) {
- clearInterval(remoting.accessCodeTimerId);
- remoting.timerRunning = false;
- updateTimeoutStyles_();
- }
+ window.addEventListener('blur', pluginLostFocus_, false);
}
-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 (remoting.timerRunning) {
- if (remoting.accessCodeExpiresIn <= 0) {
+remoting.cancelPendingOperation = function() {
+ document.getElementById('cancel-button').disabled = true;
+ switch (remoting.getMajorMode()) {
+ case remoting.AppMode.HOST:
remoting.cancelShare();
- return false;
- }
- if (remoting.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 =
- (remoting.accessCodeExpiresIn > ACCESS_CODE_TIMER_DISPLAY_THRESHOLD) ||
- !remoting.timerRunning;
- return true;
-}
-
-remoting.decrementAccessCodeTimeout_ = function() {
- --remoting.accessCodeExpiresIn;
- remoting.updateAccessCodeTimeoutElement_();
-}
-
-remoting.updateAccessCodeTimeoutElement_ = function() {
- var pad = (remoting.accessCodeExpiresIn < 10) ? '0:0' : '0:';
- l10n.localizeElement(document.getElementById('seconds-remaining'),
- pad + remoting.accessCodeExpiresIn);
- if (!updateTimeoutStyles_()) {
- disableTimeoutCountdown_();
+ break;
+ case remoting.AppMode.CLIENT:
+ remoting.cancelConnect();
+ break;
}
}
/**
- * 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;
-}
-
-/**
- * Callback for the host plugin to notify the web app of state changes.
- * @param {number} state The new state of the plugin.
+ * If the client is connected, or the host is shared, prompt before closing.
+ *
+ * @return {?string} The prompt string if a connection is active.
*/
-function onStateChanged_(state) {
- var plugin = /** @type {remoting.HostPlugin} */
- document.getElementById(remoting.HOST_PLUGIN_ID);
- if (state == plugin.STARTING) {
- // Nothing to do here.
- remoting.debug.log('Host plugin state: STARTING');
- } else if (state == plugin.REQUESTED_ACCESS_CODE) {
- // Nothing to do here.
- remoting.debug.log('Host plugin state: REQUESTED_ACCESS_CODE');
- } else if (state == plugin.RECEIVED_ACCESS_CODE) {
- remoting.debug.log('Host plugin state: RECEIVED_ACCESS_CODE');
- var accessCode = plugin.accessCode;
- var accessCodeDisplay = document.getElementById('access-code-display');
- accessCodeDisplay.innerText = '';
- // Display the access code in groups of four digits for readability.
- 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);
- }
- remoting.accessCodeExpiresIn = plugin.accessCodeLifetime;
- if (remoting.accessCodeExpiresIn > 0) { // Check it hasn't expired.
- remoting.accessCodeTimerId = setInterval(
- 'remoting.decrementAccessCodeTimeout_()', 1000);
- remoting.timerRunning = true;
- remoting.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 == plugin.CONNECTED) {
- remoting.debug.log('Host plugin state: CONNECTED');
- var element = document.getElementById('host-shared-message');
- var client = plugin.client;
- l10n.localizeElement(element, client);
- remoting.setMode(remoting.AppMode.HOST_SHARED);
- disableTimeoutCountdown_();
- } else if (state == plugin.DISCONNECTING) {
- remoting.debug.log('Host plugin state: DISCONNECTING');
- } else if (state == plugin.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 (remoting.lastShareWasCancelled) {
- remoting.setMode(remoting.AppMode.HOME);
- } else {
- remoting.setMode(remoting.AppMode.HOST_SHARE_FINISHED);
- }
- }
- plugin.parentNode.removeChild(plugin);
- } else if (state == plugin.ERROR) {
- remoting.debug.log('Host plugin state: ERROR');
- showShareError_(/*i18n-content*/'ERROR_GENERIC');
- } else {
- remoting.debug.log('Unknown state -> ' + state);
+remoting.promptClose = function() {
+ switch (remoting.currentMode) {
+ case remoting.AppMode.CLIENT_CONNECTING:
+ case remoting.AppMode.HOST_WAITING_FOR_CODE:
+ case remoting.AppMode.HOST_WAITING_FOR_CONNECTION:
+ case remoting.AppMode.HOST_SHARED:
+ case remoting.AppMode.IN_SESSION:
+ var result = chrome.i18n.getMessage(/*i18n-content*/'CLOSE_PROMPT');
+ return result;
+ default:
+ return null;
}
}
/**
- * 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 debugInfoCallback_(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.
+ * Sign the user out of Chromoting by clearing the OAuth refresh token.
*/
-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);
+remoting.clearOAuth2 = function() {
+ remoting.oauth2.clear();
+ window.localStorage.removeItem(KEY_EMAIL_);
+ remoting.setMode(remoting.AppMode.UNAUTHENTICATED);
}
/**
- * Cancel an active or pending share operation.
- *
- * @return {void} Nothing.
+ * Callback function called when the browser window loses focus. In this case,
+ * release all keys to prevent them becoming 'stuck down' on the host.
*/
-remoting.cancelShare = function() {
- remoting.debug.log('Canceling share...');
- remoting.lastShareWasCancelled = true;
- var plugin = /** @type {remoting.HostPlugin} */
- document.getElementById(remoting.HOST_PLUGIN_ID);
- try {
- plugin.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');
+function pluginLostFocus_() {
+ if (remoting.clientSession && remoting.clientSession.plugin) {
+ remoting.clientSession.plugin.releaseAllKeys();
}
- disableTimeoutCountdown_();
}
/**
- * Cancel an incomplete connect operation.
- *
- * @return {void} Nothing.
+ * If the user is authenticated, but there is no email address cached, get one.
*/
-remoting.cancelConnect = function() {
- if (remoting.supportHostsXhr) {
- remoting.supportHostsXhr.abort();
- remoting.supportHostsXhr = null;
- }
- if (remoting.session) {
- remoting.session.removePlugin();
- remoting.session = null;
- }
- remoting.setMode(remoting.AppMode.HOME);
-}
-
-function updateStatistics() {
- if (!remoting.session)
- return;
- if (remoting.session.state != remoting.ClientSession.State.CONNECTED)
- return;
- var stats = remoting.session.stats();
-
- var units = '';
- var videoBandwidth = stats['video_bandwidth'];
- if (videoBandwidth < 1024) {
- units = 'Bps';
- } else if (videoBandwidth < 1048576) {
- units = 'KiBps';
- videoBandwidth = videoBandwidth / 1024;
- } else if (videoBandwidth < 1073741824) {
- units = 'MiBps';
- videoBandwidth = videoBandwidth / 1048576;
- } else {
- units = 'GiBps';
- videoBandwidth = videoBandwidth / 1073741824;
- }
-
- var statistics = document.getElementById('statistics');
- statistics.innerText =
- 'Bandwidth: ' + videoBandwidth.toFixed(2) + units +
- ', Frame Rate: ' +
- (stats['video_frame_rate'] ?
- stats['video_frame_rate'].toFixed(2) + ' fps' : 'n/a') +
- ', Capture: ' + stats['capture_latency'].toFixed(2) + 'ms' +
- ', Encode: ' + stats['encode_latency'].toFixed(2) + 'ms' +
- ', Decode: ' + stats['decode_latency'].toFixed(2) + 'ms' +
- ', Render: ' + stats['render_latency'].toFixed(2) + 'ms' +
- ', Latency: ' + stats['roundtrip_latency'].toFixed(2) + 'ms';
-
- // Update the stats once per second.
- window.setTimeout(updateStatistics, 1000);
-}
-
-function showToolbarPreview_() {
- var toolbar = document.getElementById('session-toolbar');
- addClass(toolbar, 'toolbar-preview');
- window.setTimeout(removeClass, 3000, toolbar, 'toolbar-preview');
-}
-
-/** @param {number} oldState The previous state of the plugin. */
-function onClientStateChange_(oldState) {
- if (!remoting.session) {
- // If the connection has been cancelled, then we no longer have a reference
- // to the session object and should ignore any state changes.
- return;
- }
- var state = remoting.session.state;
- if (state == remoting.ClientSession.State.CREATED) {
- remoting.debug.log('Created plugin');
- } else if (state == remoting.ClientSession.State.BAD_PLUGIN_VERSION) {
- showConnectError_(remoting.ClientError.BAD_PLUGIN_VERSION);
- } else if (state == remoting.ClientSession.State.CONNECTING) {
- remoting.debug.log('Connecting as ' + remoting.username);
- } else if (state == remoting.ClientSession.State.INITIALIZING) {
- remoting.debug.log('Initializing connection');
- } else if (state == remoting.ClientSession.State.CONNECTED) {
- if (remoting.session) {
- remoting.setMode(remoting.AppMode.IN_SESSION);
- recenterToolbar_();
- showToolbarPreview_();
- updateStatistics();
- }
- } else if (state == remoting.ClientSession.State.CLOSED) {
- if (oldState == remoting.ClientSession.State.CONNECTED) {
- remoting.session.removePlugin();
- remoting.session = null;
- remoting.debug.log('Connection closed by host');
- remoting.setMode(remoting.AppMode.CLIENT_SESSION_FINISHED);
- } else {
- // The transition from CONNECTING to CLOSED state may happen
- // only with older client plugins. Current version should go the
- // FAILED state when connection fails.
- showConnectError_(remoting.ClientError.INVALID_ACCESS_CODE);
- }
- } else if (state == remoting.ClientSession.State.CONNECTION_FAILED) {
- remoting.debug.log('Client plugin reported connection failed: ' +
- remoting.session.error);
- if (remoting.session.error ==
- remoting.ClientSession.ConnectionError.HOST_IS_OFFLINE) {
- showConnectError_(remoting.ClientError.HOST_IS_OFFLINE);
- } else if (remoting.session.error ==
- remoting.ClientSession.ConnectionError.SESSION_REJECTED) {
- showConnectError_(remoting.ClientError.INVALID_ACCESS_CODE);
- } else if (remoting.session.error ==
- remoting.ClientSession.ConnectionError.INCOMPATIBLE_PROTOCOL) {
- showConnectError_(remoting.ClientError.INCOMPATIBLE_PROTOCOL);
- } else if (remoting.session.error ==
- remoting.ClientSession.ConnectionError.NETWORK_FAILURE) {
- showConnectError_(remoting.ClientError.OTHER_ERROR);
- } else {
- showConnectError_(remoting.ClientError.OTHER_ERROR);
- }
- } else {
- remoting.debug.log('Unexpected client plugin state: ' + state);
- // This should only happen if the web-app and client plugin get out of
- // sync, and even then the version check should allow compatibility.
- showConnectError_(remoting.ClientError.MISSING_PLUGIN);
+function refreshEmail_() {
+ if (!getEmail_() && remoting.oauth2.isAuthenticated()) {
+ remoting.oauth2.getEmail(setEmail_);
}
}
-function startSession_() {
- remoting.debug.log('Starting session...');
- var accessCode = document.getElementById('access-code-entry');
- accessCode.value = ''; // The code has been validated and won't work again.
- remoting.username =
- /** @type {string} email must be non-NULL to get here */ getEmail();
- remoting.session =
- new remoting.ClientSession(remoting.hostJid, remoting.hostPublicKey,
- remoting.accessCode, remoting.username,
- onClientStateChange_);
- /** @param {string} token The auth token. */
- var createPluginAndConnect = function(token) {
- remoting.session.createPluginAndConnect(
- document.getElementById('session-mode'),
- token);
- };
- remoting.oauth2.callWithToken(createPluginAndConnect);
-}
+/** The key under which the email address is stored. */
+var KEY_EMAIL_ = 'remoting-email';
/**
- * Show a client-side error message.
+ * Save the user's email address in local storage.
*
- * @param {remoting.ClientError} errorTag The error to be localized and
- * displayed.
- * @return {void} Nothing.
- */
-function showConnectError_(errorTag) {
- remoting.debug.log('Connection failed: ' + errorTag);
- var errorDiv = document.getElementById('connect-error-message');
- l10n.localizeElementFromTag(errorDiv, /** @type {string} */ (errorTag));
- remoting.accessCode = '';
- if (remoting.session) {
- remoting.session.disconnect();
- remoting.session = null;
- }
- remoting.setMode(remoting.AppMode.CLIENT_CONNECT_FAILED);
-}
-
-/**
- * @param {XMLHttpRequest} xhr The XMLHttpRequest object.
+ * @param {?string} email The email address to place in local storage.
* @return {void} Nothing.
*/
-function parseServerResponse_(xhr) {
- remoting.supportHostsXhr = null;
- remoting.debug.log('parseServerResponse: status = ' + xhr.status);
- if (xhr.status == 200) {
- var host = /** @type {{data: {jabberId: string, publicKey: string}}} */
- JSON.parse(xhr.responseText);
- if (host.data && host.data.jabberId && host.data.publicKey) {
- remoting.hostJid = host.data.jabberId;
- remoting.hostPublicKey = host.data.publicKey;
- var split = remoting.hostJid.split('/');
- document.getElementById('connected-to').innerText = split[0];
- startSession_();
- return;
- }
- }
- var errorMsg = remoting.ClientError.OTHER_ERROR;
- if (xhr.status == 404) {
- errorMsg = remoting.ClientError.INVALID_ACCESS_CODE;
- } else if (xhr.status == 0) {
- errorMsg = remoting.ClientError.NO_RESPONSE;
- } else {
- remoting.debug.log('The server responded: ' + xhr.responseText);
- }
- showConnectError_(errorMsg);
-}
-
-/** @param {string} accessCode The access code, as entered by the user.
- * @return {string} The normalized form of the code (whitespace removed). */
-function normalizeAccessCode_(accessCode) {
- // Trim whitespace.
- // TODO(sergeyu): Do we need to do any other normalization here?
- return accessCode.replace(/\s/g, '');
-}
-
-/** @param {string} supportId The canonicalized support ID. */
-function resolveSupportId(supportId) {
- var headers = {
- 'Authorization': 'OAuth ' + remoting.oauth2.getAccessToken()
- };
-
- remoting.supportHostsXhr = remoting.xhr.get(
- 'https://www.googleapis.com/chromoting/v1/support-hosts/' +
- encodeURIComponent(supportId),
- parseServerResponse_,
- '',
- headers);
-}
-
-remoting.tryConnect = function() {
- document.getElementById('cancel-button').disabled = false;
- if (remoting.oauth2.needsNewAccessToken()) {
- remoting.oauth2.refreshAccessToken(function(xhr) {
- if (remoting.oauth2.needsNewAccessToken()) {
- // Failed to get access token
- remoting.debug.log('tryConnect: OAuth2 token fetch failed');
- showConnectError_(remoting.ClientError.OAUTH_FETCH_FAILED);
- return;
- }
- remoting.tryConnectWithAccessToken();
- });
+function setEmail_(email) {
+ if (email) {
+ document.getElementById('current-email').innerText = email;
} else {
- remoting.tryConnectWithAccessToken();
+ // TODO(ajwong): Have a better way of showing an error.
+ document.getElementById('current-email').innerText = '???';
}
}
-remoting.tryConnectWithAccessToken = function() {
- if (!remoting.wcsLoader) {
- remoting.wcsLoader = new remoting.WcsLoader();
- }
- /** @param {function(string):void} setToken The callback function. */
- var callWithToken = function(setToken) {
- remoting.oauth2.callWithToken(setToken);
- };
- remoting.wcsLoader.start(
- remoting.oauth2.getAccessToken(),
- callWithToken,
- remoting.tryConnectWithWcs);
-}
-
/**
- * WcsLoader callback, called when the wcs script has been loaded, or on error.
- * @param {boolean} success True if the script was loaded successfully.
+ * Read the user's email address from local storage.
+ *
+ * @return {?string} The email address associated with the auth credentials.
*/
-remoting.tryConnectWithWcs = function(success) {
- if (success) {
- var accessCode = document.getElementById('access-code-entry').value;
- remoting.accessCode = normalizeAccessCode_(accessCode);
- // At present, only 12-digit access codes are supported, of which the first
- // 7 characters are the supportId.
- if (remoting.accessCode.length != kAccessCodeLen) {
- remoting.debug.log('Bad access code length');
- showConnectError_(remoting.ClientError.INVALID_ACCESS_CODE);
- } else {
- var supportId = remoting.accessCode.substring(0, kSupportIdLen);
- remoting.setMode(remoting.AppMode.CLIENT_CONNECTING);
- resolveSupportId(supportId);
- }
- } else {
- showConnectError_(remoting.ClientError.OAUTH_FETCH_FAILED);
- }
-}
-
-remoting.cancelPendingOperation = function() {
- document.getElementById('cancel-button').disabled = true;
- switch (remoting.getMajorMode()) {
- case remoting.AppMode.HOST:
- remoting.cancelShare();
- break;
- case remoting.AppMode.CLIENT:
- remoting.cancelConnect();
- break;
- }
+function getEmail_() {
+ var result = window.localStorage.getItem(KEY_EMAIL_);
+ return typeof result == 'string' ? result : null;
}
-
/**
* Gets the major-mode that this application should start up in.
*
* @return {remoting.AppMode} The mode to start in.
*/
-function getAppStartupMode() {
+function getAppStartupMode_() {
if (!remoting.oauth2.isAuthenticated()) {
return remoting.AppMode.UNAUTHENTICATED;
}
- if (isHostModeSupported()) {
+ if (isHostModeSupported_()) {
return remoting.AppMode.HOME;
} else {
return remoting.AppMode.CLIENT_UNCONNECTED;
@@ -769,86 +151,8 @@ function getAppStartupMode() {
*
* @return {boolean} True if Host mode is supported.
*/
-function isHostModeSupported() {
+function isHostModeSupported_() {
// Currently, sharing on Chromebooks is not supported.
return !navigator.userAgent.match(/\bCrOS\b/);
}
-
-/**
- * Enable or disable scale-to-fit.
- *
- * @param {Element} button The scale-to-fit button. The style of this button is
- * updated to reflect the new scaling state.
- * @return {void} Nothing.
- */
-remoting.toggleScaleToFit = function(button) {
- remoting.scaleToFit = !remoting.scaleToFit;
- if (remoting.scaleToFit) {
- addClass(button, 'toggle-button-active');
- } else {
- removeClass(button, 'toggle-button-active');
- }
- remoting.session.updateDimensions();
-}
-
-/**
- * Update the remoting client layout in response to a resize event.
- *
- * @return {void} Nothing.
- */
-remoting.onResize = function() {
- if (remoting.session)
- remoting.session.onWindowSizeChanged();
- recenterToolbar_();
-}
-
-/**
- * Disconnect the remoting client.
- *
- * @return {void} Nothing.
- */
-remoting.disconnect = function() {
- if (remoting.session) {
- remoting.session.disconnect();
- remoting.session = null;
- remoting.debug.log('Disconnected.');
- remoting.setMode(remoting.AppMode.CLIENT_SESSION_FINISHED);
- }
-}
-
-/**
- * If the client is connected, or the host is shared, prompt before closing.
- *
- * @return {?string} The prompt string if a connection is active.
- */
-remoting.promptClose = function() {
- switch (remoting.currentMode) {
- case remoting.AppMode.CLIENT_CONNECTING:
- case remoting.AppMode.HOST_WAITING_FOR_CODE:
- case remoting.AppMode.HOST_WAITING_FOR_CONNECTION:
- case remoting.AppMode.HOST_SHARED:
- case remoting.AppMode.IN_SESSION:
- var result = chrome.i18n.getMessage(/*i18n-content*/'CLOSE_PROMPT');
- return result;
- default:
- return null;
- }
-}
-
-/**
- * @param {Event} event The keyboard event.
- * @return {void} Nothing.
- */
-remoting.checkHotkeys = function(event) {
- if (String.fromCharCode(event.which) == 'D') {
- remoting.toggleDebugLog();
- }
-}
-
-function recenterToolbar_() {
- var toolbar = document.getElementById('session-toolbar');
- var toolbarX = (window.innerWidth - toolbar.clientWidth) / 2;
- toolbar.style['left'] = toolbarX + 'px';
-}
-
}());

Powered by Google App Engine
This is Rietveld 408576698