summaryrefslogtreecommitdiffstats
path: root/remoting
diff options
context:
space:
mode:
authorjamiewalch@chromium.org <jamiewalch@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-02-07 04:10:10 +0000
committerjamiewalch@chromium.org <jamiewalch@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-02-07 04:10:10 +0000
commit79ff6327718beb0ecbbc5b5c79d1d426acf8f669 (patch)
treedac87d3aa9c8c79f0d6ff9dc10886af95092f2a9 /remoting
parentcec910c0d1b82303a8e94503eb3feab5e9353a6c (diff)
downloadchromium_src-79ff6327718beb0ecbbc5b5c79d1d426acf8f669.zip
chromium_src-79ff6327718beb0ecbbc5b5c79d1d426acf8f669.tar.gz
chromium_src-79ff6327718beb0ecbbc5b5c79d1d426acf8f669.tar.bz2
Factor connection setup out of client_screen.js.
client_screen.js is a bit of a mixed bag of functions with only a loose common theme. This CL pulls out the largest single feature, connection setup, into a separate class, eliminating lots of global state as a result. As a side-effect, it speeds up connections by parallelizing the WCS driver load and fixes the referenced bugs. BUG=173788,174113 Review URL: https://chromiumcodereview.appspot.com/12177003 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@181187 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'remoting')
-rw-r--r--remoting/remoting.gyp1
-rw-r--r--remoting/webapp/all_js_load.gtestjs1
-rw-r--r--remoting/webapp/client_screen.js506
-rw-r--r--remoting/webapp/client_session.js67
-rw-r--r--remoting/webapp/event_handlers.js14
-rw-r--r--remoting/webapp/main.html1
-rw-r--r--remoting/webapp/remoting.js9
-rw-r--r--remoting/webapp/session_connector.js404
-rw-r--r--remoting/webapp/ui_mode.js4
9 files changed, 549 insertions, 458 deletions
diff --git a/remoting/remoting.gyp b/remoting/remoting.gyp
index 82361fe..e3c2716 100644
--- a/remoting/remoting.gyp
+++ b/remoting/remoting.gyp
@@ -186,6 +186,7 @@
'webapp/plugin_settings.js',
'webapp/xhr_proxy.js',
'webapp/remoting.js',
+ 'webapp/session_connector.js',
'webapp/server_log_entry.js',
'webapp/stats_accumulator.js',
'webapp/storage.js',
diff --git a/remoting/webapp/all_js_load.gtestjs b/remoting/webapp/all_js_load.gtestjs
index 59164bc..57d719f 100644
--- a/remoting/webapp/all_js_load.gtestjs
+++ b/remoting/webapp/all_js_load.gtestjs
@@ -49,6 +49,7 @@ AllJsLoadTest.prototype = {
'plugin_settings.js',
'xhr_proxy.js',
'remoting.js',
+ 'session_connector.js',
'server_log_entry.js',
'stats_accumulator.js',
'storage.js',
diff --git a/remoting/webapp/client_screen.js b/remoting/webapp/client_screen.js
index a5922e1..1140dc7 100644
--- a/remoting/webapp/client_screen.js
+++ b/remoting/webapp/client_screen.js
@@ -13,93 +13,29 @@
var remoting = remoting || {};
/**
- * @type {remoting.ClientSession} The client session object, set once the
- * access code has been successfully verified.
- */
-remoting.clientSession = null;
-
-/**
- * @type {string} The normalized access code.
- */
-remoting.accessCode = '';
-
-/**
- * @type {string} The host's JID, returned by the server.
- */
-remoting.hostJid = '';
-
-/**
- * @type {string} For Me2Me connections, the id of the current host.
- */
-remoting.hostId = '';
-
-/**
- * @type {boolean} For Me2Me connections. Set to true if connection
- * must be retried on failure.
- */
-remoting.retryIfOffline = false;
-
-/**
- * @type {string} The host's public key, returned by the server.
- */
-remoting.hostPublicKey = '';
-
-/**
- * @type {XMLHttpRequest} The XHR object corresponding to the current
- * support-hosts request, if there is one outstanding.
- * @private
+ * @type {remoting.SessionConnector} The connector object, set when a connection
+ * is initiated.
*/
-remoting.supportHostsXhr_ = null;
+remoting.connector = null;
/**
- * @type {remoting.ClientSession.Mode?}
+ * @type {remoting.ClientSession} The client session object, set once the
+ * connector has invoked its onOk callback.
*/
-remoting.currentConnectionType = null;
+remoting.clientSession = null;
/**
- * Entry point for the 'connect' functionality. This function defers to the
- * WCS loader to call it back with an access token.
+ * Initiate an IT2Me connection.
*/
-remoting.connectIt2Me = function() {
- remoting.currentConnectionType = remoting.ClientSession.Mode.IT2ME;
- /** @param {string} token */
- var startWcsAndConnect = function(token) {
- remoting.wcsSandbox.setOnReady(
- connectIt2MeWithAccessToken_.bind(null, token));
- remoting.wcsSandbox.setOnError(remoting.showErrorMessage);
- remoting.wcsSandbox.setAccessToken(token);
- startAccessTokenRefreshTimer_();
- };
- remoting.identity.callWithToken(startWcsAndConnect,
- remoting.showErrorMessage);
-};
-
-/**
- * Cancel an incomplete connect operation.
- *
- * Note that this function is not currently used. It is here for reference
- * because we'll need to reinstate something very like it when we transition
- * to Apps v2 where we can no longer change the URL (which is what we do in
- * lieu of calling this function to ensure correct Reload behaviour).
- *
- * @return {void} Nothing.
-remoting.cancelConnect = function() {
- if (remoting.supportHostsXhr_) {
- remoting.supportHostsXhr_.abort();
- remoting.supportHostsXhr_ = null;
- }
- if (remoting.clientSession) {
- remoting.clientSession.removePlugin();
- remoting.clientSession = null;
- }
- if (remoting.currentConnectionType == remoting.ConnectionType.Me2Me) {
- remoting.initDaemonUi();
- } else {
- remoting.setMode(remoting.AppMode.HOME);
- document.getElementById('access-code-entry').value = '';
- }
+remoting.connectIT2Me = function() {
+ remoting.connector = new remoting.SessionConnector(
+ document.getElementById('session-mode'),
+ remoting.onConnected,
+ remoting.showErrorMessage);
+ var accessCode = document.getElementById('access-code-entry').value;
+ remoting.setMode(remoting.AppMode.CLIENT_CONNECTING);
+ remoting.connector.connectIT2Me(accessCode);
};
-*/
/**
* Update the remoting client layout in response to a resize event.
@@ -107,8 +43,9 @@ remoting.cancelConnect = function() {
* @return {void} Nothing.
*/
remoting.onResize = function() {
- if (remoting.clientSession)
+ if (remoting.clientSession) {
remoting.clientSession.onResize();
+ }
};
/**
@@ -117,8 +54,9 @@ remoting.onResize = function() {
* @return {void} Nothing.
*/
remoting.onVisibilityChanged = function() {
- if (remoting.clientSession)
+ if (remoting.clientSession) {
remoting.clientSession.pauseVideo(document.webkitHidden);
+ }
}
/**
@@ -127,16 +65,17 @@ remoting.onVisibilityChanged = function() {
* @return {void} Nothing.
*/
remoting.disconnect = function() {
- if (remoting.clientSession) {
- remoting.clientSession.disconnect(true);
- remoting.clientSession = null;
- console.log('Disconnected.');
- if (remoting.currentConnectionType == remoting.ClientSession.Mode.IT2ME) {
- remoting.setMode(remoting.AppMode.CLIENT_SESSION_FINISHED_IT2ME);
- } else {
- remoting.setMode(remoting.AppMode.CLIENT_SESSION_FINISHED_ME2ME);
- }
+ if (!remoting.clientSession) {
+ return;
}
+ if (remoting.clientSession.mode == remoting.ClientSession.Mode.IT2ME) {
+ remoting.setMode(remoting.AppMode.CLIENT_SESSION_FINISHED_IT2ME);
+ } else {
+ remoting.setMode(remoting.AppMode.CLIENT_SESSION_FINISHED_ME2ME);
+ }
+ remoting.clientSession.disconnect(true);
+ remoting.clientSession = null;
+ console.log('Disconnected.');
};
/**
@@ -164,178 +103,41 @@ remoting.sendPrintScreen = function() {
};
/**
- * If WCS was successfully loaded, proceed with the connection, otherwise
- * report an error.
- *
- * @param {string} token The OAuth2 access token.
- * @param {string} clientJid The full JID of the WCS client.
- * @return {void} Nothing.
- */
-function connectIt2MeWithAccessToken_(token, clientJid) {
- 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.
- var kSupportIdLen = 7;
- var kHostSecretLen = 5;
- var kAccessCodeLen = kSupportIdLen + kHostSecretLen;
- if (remoting.accessCode.length != kAccessCodeLen) {
- console.error('Bad access code length');
- showConnectError_(remoting.Error.INVALID_ACCESS_CODE);
- } else {
- var supportId = remoting.accessCode.substring(0, kSupportIdLen);
- remoting.setMode(remoting.AppMode.CLIENT_CONNECTING);
- resolveSupportId(clientJid, supportId, token);
- }
-}
-
-/**
* Callback function called when the state of the client plugin changes. The
* current state is available via the |state| member variable.
*
* @param {number} oldState The previous state of the plugin.
* @param {number} newState The current state of the plugin.
*/
-// TODO(jamiewalch): Make this pass both the current and old states to avoid
-// race conditions.
function onClientStateChange_(oldState, newState) {
- if (!remoting.clientSession) {
- // If the connection has been cancelled, then we no longer have a reference
- // to the session object and should ignore any state changes.
- return;
- }
-
- // Clear the PIN on successful connection, or on error if we're not going to
- // automatically retry.
- var clearPin = false;
-
- if (newState == remoting.ClientSession.State.CREATED) {
- console.log('Created plugin');
-
- } else if (newState == remoting.ClientSession.State.BAD_PLUGIN_VERSION) {
- showConnectError_(remoting.Error.BAD_PLUGIN_VERSION);
-
- } else if (newState == remoting.ClientSession.State.CONNECTING) {
- console.log('Connecting as ' + remoting.identity.getCachedEmail());
-
- } else if (newState == remoting.ClientSession.State.INITIALIZING) {
- console.log('Initializing connection');
-
- } else if (newState == remoting.ClientSession.State.CONNECTED) {
- if (remoting.clientSession) {
- clearPin = true;
- setConnectionInterruptedButtonsText_();
- remoting.retryIfOffline = false;
- remoting.setMode(remoting.AppMode.IN_SESSION);
- remoting.toolbar.center();
- remoting.toolbar.preview();
- remoting.clipboard.startSession();
- updateStatistics_();
- }
-
- } else if (newState == remoting.ClientSession.State.CLOSED) {
- if (oldState == remoting.ClientSession.State.CONNECTED) {
- remoting.clientSession.removePlugin();
- remoting.clientSession = null;
+ switch (newState) {
+ case remoting.ClientSession.State.CLOSED:
console.log('Connection closed by host');
- if (remoting.currentConnectionType == remoting.ClientSession.Mode.IT2ME) {
+ if (remoting.clientSession.mode == remoting.ClientSession.Mode.IT2ME) {
remoting.setMode(remoting.AppMode.CLIENT_SESSION_FINISHED_IT2ME);
} else {
remoting.setMode(remoting.AppMode.CLIENT_SESSION_FINISHED_ME2ME);
}
- } else {
- // A state transition from CONNECTING -> CLOSED can happen if the host
- // closes the connection without an error message instead of accepting it.
- // For example, it does this if it fails to activate curtain mode. Since
- // there's no way of knowing exactly what went wrong, we rely on server-
- // side logs in this case and show a generic error message.
- showConnectError_(remoting.Error.UNEXPECTED);
- }
-
- } else if (newState == remoting.ClientSession.State.FAILED) {
- console.error('Client plugin reported connection failed: ' +
- remoting.clientSession.error);
- clearPin = true;
- if (remoting.clientSession.error ==
- remoting.ClientSession.ConnectionError.HOST_IS_OFFLINE) {
- clearPin = false;
- retryConnectOrReportOffline_();
- } else if (remoting.clientSession.error ==
- remoting.ClientSession.ConnectionError.SESSION_REJECTED) {
- showConnectError_(remoting.Error.INVALID_ACCESS_CODE);
- } else if (remoting.clientSession.error ==
- remoting.ClientSession.ConnectionError.INCOMPATIBLE_PROTOCOL) {
- showConnectError_(remoting.Error.INCOMPATIBLE_PROTOCOL);
- } else if (remoting.clientSession.error ==
- remoting.ClientSession.ConnectionError.NETWORK_FAILURE) {
- showConnectError_(remoting.Error.NETWORK_FAILURE);
- } else if (remoting.clientSession.error ==
- remoting.ClientSession.ConnectionError.HOST_OVERLOAD) {
- showConnectError_(remoting.Error.HOST_OVERLOAD);
- } else {
- showConnectError_(remoting.Error.UNEXPECTED);
- }
-
- if (clearPin) {
- document.getElementById('pin-entry').value = '';
- }
+ break;
- } else {
- console.error('Unexpected client plugin state: ' + newState);
- // 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.Error.MISSING_PLUGIN);
- }
-}
-
-/**
- * If we have a hostId to retry, try refreshing it and connecting again. If not,
- * then show the 'host offline' error message.
- *
- * @return {void} Nothing.
- */
-function retryConnectOrReportOffline_() {
- if (remoting.clientSession) {
- remoting.clientSession.removePlugin();
- remoting.clientSession = null;
- }
- if (remoting.hostId && remoting.retryIfOffline) {
- console.warn('Connection failed. Retrying.');
- /** @param {boolean} success True if the refresh was successful. */
- var onDone = function(success) {
- if (success) {
- remoting.retryIfOffline = false;
- remoting.connectMe2MeWithPin();
- } else {
- showConnectError_(remoting.Error.HOST_IS_OFFLINE);
+ case remoting.ClientSession.State.FAILED:
+ var error = remoting.clientSession.getError();
+ console.error('Client plugin reported connection failed: ' + error);
+ if (error == null) {
+ error = remoting.Error.UNEXPECTED;
}
- };
- remoting.hostList.refresh(onDone);
- } else {
- console.error('Connection failed. Not retrying.');
- showConnectError_(remoting.Error.HOST_IS_OFFLINE);
- }
-}
-
-/**
- * Create the client session object and initiate the connection.
- *
- * @param {string} clientJid The full JID of the WCS client.
- * @return {void} Nothing.
- */
-function startSession_(clientJid) {
- console.log('Starting session...');
- var accessCode = document.getElementById('access-code-entry');
- accessCode.value = ''; // The code has been validated and won't work again.
- remoting.clientSession =
- new remoting.ClientSession(
- remoting.hostJid, clientJid,
- remoting.hostPublicKey,
- remoting.accessCode, 'spake2_plain', '',
- remoting.ClientSession.Mode.IT2ME,
- onClientStateChange_);
- remoting.clientSession.createPluginAndConnect(
- document.getElementById('session-mode'));
+ showConnectError_(error);
+ break;
+
+ default:
+ console.error('Unexpected client plugin state: ' + newState);
+ // This should only happen if the web-app and client plugin get out of
+ // sync, so MISSING_PLUGIN is a suitable error.
+ showConnectError_(remoting.Error.MISSING_PLUGIN);
+ break;
+ }
+ remoting.clientSession.removePlugin();
+ remoting.clientSession = null;
}
/**
@@ -350,15 +152,15 @@ function showConnectError_(errorTag) {
var errorDiv = document.getElementById('connect-error-message');
l10n.localizeElementFromTag(errorDiv, /** @type {string} */ (errorTag));
remoting.accessCode = '';
- if (remoting.clientSession) {
- remoting.clientSession.disconnect(false);
- remoting.clientSession = null;
- }
- if (remoting.currentConnectionType == remoting.ClientSession.Mode.IT2ME) {
+ if (remoting.clientSession.mode == remoting.ClientSession.Mode.IT2ME) {
remoting.setMode(remoting.AppMode.CLIENT_CONNECT_FAILED_IT2ME);
} else {
remoting.setMode(remoting.AppMode.CLIENT_CONNECT_FAILED_ME2ME);
}
+ if (remoting.clientSession) {
+ remoting.clientSession.disconnect(false);
+ remoting.clientSession = null;
+ }
}
/**
@@ -376,75 +178,6 @@ function setConnectionInterruptedButtonsText_() {
}
/**
- * Parse the response from the server to a request to resolve a support id.
- *
- * @param {string} clientJid The full JID of the WCS client.
- * @param {XMLHttpRequest} xhr The XMLHttpRequest object.
- * @return {void} Nothing.
- */
-function parseServerResponse_(clientJid, xhr) {
- remoting.supportHostsXhr_ = null;
- console.log('parseServerResponse: xhr =', xhr);
- if (xhr.status == 200) {
- var host = /** @type {{data: {jabberId: string, publicKey: string}}} */
- jsonParseSafe(xhr.responseText);
- if (host && 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_(clientJid);
- return;
- } else {
- console.error('Invalid "support-hosts" response from server.');
- }
- }
- var errorMsg = remoting.Error.UNEXPECTED;
- if (xhr.status == 404) {
- errorMsg = remoting.Error.INVALID_ACCESS_CODE;
- } else if (xhr.status == 0) {
- errorMsg = remoting.Error.NO_RESPONSE;
- } else if (xhr.status == 502 || xhr.status == 503) {
- errorMsg = remoting.Error.SERVICE_UNAVAILABLE;
- } else {
- console.error('The server responded: ' + xhr.responseText);
- }
- showConnectError_(errorMsg);
-}
-
-/**
- * Normalize the access code entered by the user.
- *
- * @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, '');
-}
-
-/**
- * Initiate a request to the server to resolve a support ID.
- *
- * @param {string} clientJid The full JID of the WCS client.
- * @param {string} supportId The canonicalized support ID.
- * @param {string} token The OAuth access token.
- */
-function resolveSupportId(clientJid, supportId, token) {
- var headers = {
- 'Authorization': 'OAuth ' + token
- };
-
- remoting.supportHostsXhr_ = remoting.xhr.get(
- remoting.settings.DIRECTORY_API_BASE_URL + '/support-hosts/' +
- encodeURIComponent(supportId),
- parseServerResponse_.bind(null, clientJid),
- '',
- headers);
-}
-
-/**
* Timer callback to update the statistics panel.
*/
function updateStatistics_() {
@@ -460,114 +193,49 @@ function updateStatistics_() {
}
/**
- * Shows PIN entry screen.
+ * Shows PIN entry screen localized to include the host name, and registers
+ * a host-specific one-shot event handler for the form submission.
*
* @param {string} hostId The unique id of the host.
- * @param {boolean} retryIfOffline If true and the host can't be contacted,
- * refresh the host list and try again. This allows bookmarked hosts to
- * work even if they reregister with Talk and get a different Jid.
* @return {void} Nothing.
*/
-remoting.connectMe2Me = function(hostId, retryIfOffline) {
- remoting.currentConnectionType = remoting.ClientSession.Mode.ME2ME;
- remoting.hostId = hostId;
- remoting.retryIfOffline = retryIfOffline;
-
- var host = remoting.hostList.getHostForId(remoting.hostId);
- // If we're re-loading a tab for a host that has since been unregistered
- // then the hostId may no longer resolve.
+remoting.connectMe2Me = function(hostId) {
+ var host = remoting.hostList.getHostForId(hostId);
if (!host) {
showConnectError_(remoting.Error.HOST_IS_OFFLINE);
return;
}
+
+ remoting.connector = new remoting.SessionConnector(
+ document.getElementById('session-mode'),
+ remoting.onConnected,
+ remoting.showErrorMessage);
+ /** @type {Element} */
+ var pinForm = document.getElementById('pin-form');
+ /** @param {Event} event */
+ var onSubmit = function(event) {
+ pinForm.removeEventListener('submit', onSubmit, false);
+ var pin = document.getElementById('pin-entry').value;
+ remoting.connector.connectMe2Me(host, pin);
+ remoting.setMode(remoting.AppMode.CLIENT_CONNECTING);
+ event.preventDefault();
+ };
+ pinForm.addEventListener('submit', onSubmit, false);
+
var message = document.getElementById('pin-message');
l10n.localizeElement(message, host.hostName);
remoting.setMode(remoting.AppMode.CLIENT_PIN_PROMPT);
};
-/**
- * Start a connection to the specified host, using the cached details
- * and the PIN entered by the user.
- *
- * @return {void} Nothing.
- */
-remoting.connectMe2MeWithPin = function() {
- console.log('Connecting to host...');
- remoting.setMode(remoting.AppMode.CLIENT_CONNECTING);
-
- var host = remoting.hostList.getHostForId(remoting.hostId);
- // If the user clicked on a cached host that has since been removed then we
- // won't find the hostId. If the user clicked on the entry for the local host
- // immediately after having enabled it then we won't know it's JID or public
- // key until the host heartbeats and we pull a fresh host list.
- if (!host || !host.jabberId || !host.publicKey) {
- retryConnectOrReportOffline_();
- return;
- }
- remoting.hostJid = host.jabberId;
- remoting.hostPublicKey = host.publicKey;
- document.getElementById('connected-to').innerText = host.hostName;
- document.title = host.hostName + ' - ' +
- chrome.i18n.getMessage('PRODUCT_NAME');
-
- /** @param {string} token */
- var startWcsAndConnect = function(token) {
- remoting.wcsSandbox.setOnReady(
- connectMe2MeWithAccessToken_.bind(null, token));
- remoting.wcsSandbox.setOnError(remoting.showErrorMessage);
- remoting.wcsSandbox.setAccessToken(token);
- startAccessTokenRefreshTimer_();
- };
- remoting.identity.callWithToken(startWcsAndConnect,
- remoting.showErrorMessage);
+/** @param {remoting.ClientSession} clientSession */
+remoting.onConnected = function(clientSession) {
+ remoting.connector = null;
+ remoting.clientSession = clientSession;
+ remoting.clientSession.setOnStateChange(onClientStateChange_);
+ setConnectionInterruptedButtonsText_();
+ remoting.setMode(remoting.AppMode.IN_SESSION);
+ remoting.toolbar.center();
+ remoting.toolbar.preview();
+ remoting.clipboard.startSession();
+ updateStatistics_();
};
-
-/**
- * Continue making the connection to a host, once WCS has initialized.
- *
- * @param {string} token The OAuth2 access token.
- * @param {string} clientJid The full JID of the WCS client.
- * @return {void} Nothing.
- */
-function connectMe2MeWithAccessToken_(token, clientJid) {
- /** @type {string} */
- var pin = document.getElementById('pin-entry').value;
-
- remoting.clientSession =
- new remoting.ClientSession(
- remoting.hostJid, clientJid, remoting.hostPublicKey,
- pin, 'spake2_hmac,spake2_plain', remoting.hostId,
- remoting.ClientSession.Mode.ME2ME, onClientStateChange_);
- // Don't log host offline errors for cached JIDs.
- remoting.clientSession.logHostOfflineErrors(!remoting.retryIfOffline);
- remoting.clientSession.createPluginAndConnect(
- document.getElementById('session-mode'));
-}
-
-/** @type {number} */
-remoting.wcsAccessTokenRefreshTimer = 0;
-
-function startAccessTokenRefreshTimer_() {
- if (remoting.wcsAccessTokenRefreshTimer != 0) {
- return;
- }
-
- /** @param {string} token */
- var updateAccessToken = function(token) {
- remoting.wcsSandbox.setAccessToken(token);
- };
- /** @param {remoting.Error} error */
- var logError = function(error) {
- console.error('updateAccessToken: Authentication failed: ' + error);
- };
- var refreshAccessToken = function() {
- remoting.identity.callWithToken(updateAccessToken, logError);
- };
- /**
- * A timer that polls for an updated access token.
- * @type {number}
- * @private
- */
- remoting.wcsAccessTokenRefreshTimer = setInterval(refreshAccessToken,
- 60 * 1000);
-}
diff --git a/remoting/webapp/client_session.js b/remoting/webapp/client_session.js
index 4fa0563..522bca8 100644
--- a/remoting/webapp/client_session.js
+++ b/remoting/webapp/client_session.js
@@ -34,15 +34,11 @@ var remoting = remoting || {};
* @param {string} hostId The host identifier for Me2Me, or empty for IT2Me.
* Mixed into authentication hashes for some authentication methods.
* @param {remoting.ClientSession.Mode} mode The mode of this connection.
- * @param {function(remoting.ClientSession.State,
- remoting.ClientSession.State):void} onStateChange
- * The callback to invoke when the session changes state.
* @constructor
*/
remoting.ClientSession = function(hostJid, clientJid,
hostPublicKey, sharedSecret,
- authenticationMethods, hostId,
- mode, onStateChange) {
+ authenticationMethods, hostId, mode) {
this.state = remoting.ClientSession.State.CREATED;
this.hostJid = hostJid;
@@ -51,6 +47,7 @@ remoting.ClientSession = function(hostJid, clientJid,
this.sharedSecret = sharedSecret;
this.authenticationMethods = authenticationMethods;
this.hostId = hostId;
+ /** @type {remoting.ClientSession.Mode} */
this.mode = mode;
this.sessionId = '';
/** @type {remoting.ClientPlugin} */
@@ -62,7 +59,9 @@ remoting.ClientSession = function(hostJid, clientJid,
/** @private */
this.hasReceivedFrame_ = false;
this.logToServer = new remoting.LogToServer();
- this.onStateChange = onStateChange;
+ /** @type {?function(remoting.ClientSession.State,
+ remoting.ClientSession.State):void} */
+ this.onStateChange_ = null;
/** @type {number?} @private */
this.notifyClientDimensionsTimer_ = null;
@@ -118,9 +117,18 @@ remoting.ClientSession = function(hostJid, clientJid,
'click', this.callToggleFullScreen_, false);
};
+/**
+ * @param {?function(remoting.ClientSession.State,
+ remoting.ClientSession.State):void} onStateChange
+ * The callback to invoke when the session changes state.
+ */
+remoting.ClientSession.prototype.setOnStateChange = function(onStateChange) {
+ this.onStateChange_ = onStateChange;
+};
+
// Note that the positive values in both of these enums are copied directly
// from chromoting_scriptable_object.h and must be kept in sync. The negative
-// values represent states transitions that occur within the web-app that have
+// values represent state transitions that occur within the web-app that have
// no corresponding plugin state transition.
/** @enum {number} */
remoting.ClientSession.State = {
@@ -197,8 +205,9 @@ remoting.ClientSession.prototype.state = remoting.ClientSession.State.UNKNOWN;
/**
* The last connection error. Set when state is set to FAILED.
* @type {remoting.ClientSession.ConnectionError}
+ * @private
*/
-remoting.ClientSession.prototype.error =
+remoting.ClientSession.prototype.error_ =
remoting.ClientSession.ConnectionError.NONE;
/**
@@ -209,15 +218,6 @@ remoting.ClientSession.prototype.error =
remoting.ClientSession.prototype.PLUGIN_ID = 'session-client-plugin';
/**
- * Callback to invoke when the state is changed.
- *
- * @param {remoting.ClientSession.State} oldState The previous state.
- * @param {remoting.ClientSession.State} newState The current state.
- */
-remoting.ClientSession.prototype.onStateChange =
- function(oldState, newState) { };
-
-/**
* @param {Element} container The element to add the plugin to.
* @param {string} id Id to use for the plugin element .
* @return {remoting.ClientPlugin} Create plugin object for the locally
@@ -411,6 +411,27 @@ remoting.ClientSession.prototype.disconnect = function(isUserInitiated) {
};
/**
+ * @return {?remoting.Error} The current error code, or null if the connection
+ * is not in an error state.
+ */
+remoting.ClientSession.prototype.getError = function() {
+ switch (this.error_) {
+ case remoting.ClientSession.ConnectionError.HOST_IS_OFFLINE:
+ return remoting.Error.HOST_IS_OFFLINE;
+ case remoting.ClientSession.ConnectionError.SESSION_REJECTED:
+ return remoting.Error.INVALID_ACCESS_CODE;
+ case remoting.ClientSession.ConnectionError.INCOMPATIBLE_PROTOCOL:
+ return remoting.Error.INCOMPATIBLE_PROTOCOL;
+ case remoting.ClientSession.ConnectionError.NETWORK_FAILURE:
+ return remoting.Error.NETWORK_FAILURE;
+ case remoting.ClientSession.ConnectionError.HOST_OVERLOAD:
+ return remoting.Error.HOST_OVERLOAD;
+ default:
+ return null;
+ }
+};
+
+/**
* Sends a key combination to the remoting client, by sending down events for
* the given keys, followed by up events in reverse order.
*
@@ -609,7 +630,7 @@ remoting.ClientSession.prototype.onConnectionStatusUpdate_ =
this.plugin.notifyClientDimensions(window.innerWidth, window.innerHeight);
}
} else if (status == remoting.ClientSession.State.FAILED) {
- this.error = /** @type {remoting.ClientSession.ConnectionError} */ (error);
+ this.error_ = /** @type {remoting.ClientSession.ConnectionError} */ (error);
}
this.setState_(/** @type {remoting.ClientSession.State} */ (status));
};
@@ -642,9 +663,9 @@ remoting.ClientSession.prototype.setState_ = function(newState) {
if (this.state == remoting.ClientSession.State.CLOSED) {
state = remoting.ClientSession.State.CONNECTION_CANCELED;
} else if (this.state == remoting.ClientSession.State.FAILED &&
- this.error == remoting.ClientSession.ConnectionError.HOST_IS_OFFLINE &&
+ this.error_ == remoting.ClientSession.ConnectionError.HOST_IS_OFFLINE &&
!this.logHostOfflineErrors_) {
- // The upper layer requested host-offline errors to be suppressed, for
+ // The application requested host-offline errors to be suppressed, for
// example, because this connection attempt is using a cached host JID.
console.log('Suppressing host-offline error.');
state = remoting.ClientSession.State.CONNECTION_CANCELED;
@@ -653,9 +674,9 @@ remoting.ClientSession.prototype.setState_ = function(newState) {
this.state == remoting.ClientSession.State.FAILED) {
state = remoting.ClientSession.State.CONNECTION_DROPPED;
}
- this.logToServer.logClientSessionStateChange(state, this.error, this.mode);
- if (this.onStateChange) {
- this.onStateChange(oldState, newState);
+ this.logToServer.logClientSessionStateChange(state, this.error_, this.mode);
+ if (this.onStateChange_) {
+ this.onStateChange_(oldState, newState);
}
};
diff --git a/remoting/webapp/event_handlers.js b/remoting/webapp/event_handlers.js
index f3a8c24..5dfc368 100644
--- a/remoting/webapp/event_handlers.js
+++ b/remoting/webapp/event_handlers.js
@@ -22,7 +22,7 @@ function onLoad() {
},
remoting.showErrorMessage);
};
- var goFinishedIt2Me = function() {
+ var goFinishedIT2Me = function() {
if (remoting.currentMode == remoting.AppMode.CLIENT_CONNECT_FAILED_IT2ME) {
remoting.setMode(remoting.AppMode.CLIENT_UNCONNECTED);
} else {
@@ -34,12 +34,7 @@ function onLoad() {
};
/** @param {Event} event The event. */
var sendAccessCode = function(event) {
- remoting.connectIt2Me();
- event.preventDefault();
- };
- /** @param {Event} event The event. */
- var connectHostWithPin = function(event) {
- remoting.connectMe2MeWithPin();
+ remoting.connectIT2Me();
event.preventDefault();
};
var doAuthRedirect = function() {
@@ -69,7 +64,7 @@ function onLoad() {
{ event: 'click', id: 'stop-sharing-button', fn: remoting.cancelShare },
{ event: 'click', id: 'host-finished-button', fn: restartWebapp },
{ event: 'click', id: 'client-finished-it2me-button',
- fn: goFinishedIt2Me },
+ fn: goFinishedIT2Me },
{ event: 'click', id: 'client-finished-me2me-button', fn: restartWebapp },
{ event: 'click', id: 'cancel-pin-entry-button', fn: restartWebapp },
{ event: 'click', id: 'client-reconnect-button', fn: reload },
@@ -83,9 +78,8 @@ function onLoad() {
fn: function() { remoting.hostSetupDialog.showForPin(); } },
{ event: 'click', id: 'stop-daemon', fn: stopDaemon },
{ event: 'submit', id: 'access-code-form', fn: sendAccessCode },
- { event: 'submit', id: 'pin-form', fn: connectHostWithPin },
{ event: 'click', id: 'get-started-it2me',
- fn: remoting.showIt2MeUiAndSave },
+ fn: remoting.showIT2MeUiAndSave },
{ event: 'click', id: 'get-started-me2me',
fn: remoting.showMe2MeUiAndSave },
{ event: 'click', id: 'daemon-pin-cancel',
diff --git a/remoting/webapp/main.html b/remoting/webapp/main.html
index cb64271..31a426f 100644
--- a/remoting/webapp/main.html
+++ b/remoting/webapp/main.html
@@ -39,6 +39,7 @@ found in the LICENSE file.
<script src="oauth2.js"></script>
<script src="plugin_settings.js"></script>
<script src="remoting.js"></script>
+ <script src="session_connector.js"></script>
<script src="server_log_entry.js"></script>
<script src="stats_accumulator.js"></script>
<script src="storage.js"></script>
diff --git a/remoting/webapp/remoting.js b/remoting/webapp/remoting.js
index 8da7e15..f89072a 100644
--- a/remoting/webapp/remoting.js
+++ b/remoting/webapp/remoting.js
@@ -64,7 +64,7 @@ remoting.init = function() {
remoting.identity.getEmail(remoting.onEmail, remoting.showErrorMessage);
- remoting.showOrHideIt2MeUi();
+ remoting.showOrHideIT2MeUi();
remoting.showOrHideMe2MeUi();
// The plugin's onFocus handler sends a paste command to |window|, because
@@ -88,7 +88,7 @@ remoting.init = function() {
if ('mode' in urlParams) {
if (urlParams['mode'] == 'me2me') {
var hostId = urlParams['hostId'];
- remoting.connectMe2Me(hostId, true);
+ remoting.connectMe2Me(hostId);
return;
}
}
@@ -166,14 +166,15 @@ remoting.logExtensionInfoAsync_ = function() {
};
/**
- * If an It2Me client or host is active then prompt the user before closing.
+ * If an IT2Me client or host is active then prompt the user before closing.
* If a Me2Me client is active then don't bother, since closing the window is
* the more intuitive way to end a Me2Me session, and re-connecting is easy.
*
* @return {?string} The prompt string if a connection is active.
*/
remoting.promptClose = function() {
- if (remoting.currentConnectionType == remoting.ClientSession.Mode.ME2ME) {
+ if (!remoting.clientSession ||
+ remoting.clientSession.mode == remoting.ClientSession.Mode.ME2ME) {
return null;
}
switch (remoting.currentMode) {
diff --git a/remoting/webapp/session_connector.js b/remoting/webapp/session_connector.js
new file mode 100644
index 0000000..0cb9105
--- /dev/null
+++ b/remoting/webapp/session_connector.js
@@ -0,0 +1,404 @@
+// Copyright 2013 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
+ * Connect set-up state machine for Me2Me and IT2Me
+ */
+
+'use strict';
+
+/** @suppress {duplicate} */
+var remoting = remoting || {};
+
+/**
+ * @param {Element} pluginParent The node under which to add the client plugin.
+ * @param {function(remoting.ClientSession):void} onOk Callback on success.
+ * @param {function(remoting.Error):void} onError Callback on error.
+ * @constructor
+ */
+remoting.SessionConnector = function(pluginParent, onOk, onError) {
+ /**
+ * @type {Element}
+ * @private
+ */
+ this.pluginParent_ = pluginParent;
+
+ /**
+ * @type {function(remoting.ClientSession):void}
+ * @private
+ */
+ this.onOk_ = onOk;
+
+ /**
+ * @type {function(remoting.Error):void}
+ * @private
+ */
+ this.onError_ = onError;
+
+ /**
+ * @type {remoting.ClientSession.Mode}
+ * @private
+ */
+ this.connectionMode_ = remoting.ClientSession.Mode.ME2ME;
+
+ /**
+ * String used to identify the host to which to connect. For IT2Me, this is
+ * the first 7 digits of the access code; for Me2Me it is the host identifier.
+ *
+ * @type {string}
+ * @private
+ */
+ this.hostId_ = '';
+
+ /**
+ * String used to authenticate to the host on connection. For IT2Me, this is
+ * the access code; for Me2Me it is the PIN.
+ *
+ * @type {string}
+ * @private
+ */
+ this.passPhrase_ = '';
+
+ /**
+ * @type {string}
+ * @private
+ */
+ this.hostJid_ = '';
+
+ /**
+ * @type {string}
+ * @private
+ */
+ this.hostPublicKey_ = '';
+
+ /**
+ * @type {string}
+ * @private
+ */
+ this.clientJid_ = '';
+
+ /**
+ * @type {boolean}
+ * @private
+ */
+ this.refreshHostJidIfOffline_ = true;
+
+ /**
+ * @type {remoting.ClientSession}
+ * @private
+ */
+ this.clientSession_ = null;
+
+ /**
+ * @type {XMLHttpRequest}
+ * @private
+ */
+ this.pendingXhr_ = null;
+
+ /**
+ * A timer that polls for an updated access token.
+ * @type {number}
+ * @private
+ */
+ this.wcsAccessTokenRefreshTimer_ = 0;
+
+ // Pre-load WCS to improve connection time.
+ remoting.identity.callWithToken(this.loadWcs_.bind(this), this.onError_);
+};
+
+/**
+ * Initiate a Me2Me connection.
+ *
+ * @param {remoting.Host} host The Me2Me host to which to connect.
+ * @param {string} pin The PIN as entered by the user.
+ * @return {void} Nothing.
+ */
+remoting.SessionConnector.prototype.connectMe2Me = function(host, pin) {
+ this.hostId_ = host.hostId;
+ this.hostJid_ = host.jabberId;
+ this.passPhrase_ = pin;
+ this.createSessionIfReady_();
+};
+
+/**
+ * Initiate an IT2Me connection.
+ *
+ * @param {string} accessCode The access code as entered by the user.
+ * @return {void} Nothing.
+ */
+remoting.SessionConnector.prototype.connectIT2Me = function(accessCode) {
+ var kSupportIdLen = 7;
+ var kHostSecretLen = 5;
+ var kAccessCodeLen = kSupportIdLen + kHostSecretLen;
+
+ var normalizedAccessCode = this.normalizeAccessCode_(accessCode);
+ if (normalizedAccessCode.length != kAccessCodeLen) {
+ this.onError_(remoting.Error.INVALID_ACCESS_CODE);
+ return;
+ }
+
+ this.hostId_ = normalizedAccessCode.substring(0, kSupportIdLen);
+ this.passPhrase_ = normalizedAccessCode;
+ this.connectionMode_ = remoting.ClientSession.Mode.IT2ME;
+ remoting.identity.callWithToken(this.connectIT2MeWithToken_.bind(this),
+ this.onError_);
+};
+
+/**
+ * Cancel a connection-in-progress.
+ */
+remoting.SessionConnector.prototype.cancel = function() {
+ if (this.clientSession_) {
+ this.clientSession_.removePlugin();
+ this.clientSession_ = null;
+ }
+ if (this.pendingXhr_) {
+ this.pendingXhr_.abort();
+ this.pendingXhr_ = null;
+ }
+ this.hostId_ = '';
+ this.hostJid_ = '';
+ this.passPhrase_ = '';
+ this.hostPublicKey_ = '';
+ this.refreshHostJidIfOffline_ = true;
+};
+
+/**
+ * Continue an IT2Me connection once an access token has been obtained.
+ *
+ * @param {string} token An OAuth2 access token.
+ * @return {void} Nothing.
+ * @private
+ */
+remoting.SessionConnector.prototype.connectIT2MeWithToken_ = function(token) {
+ // Resolve the host id to get the host JID.
+ this.pendingXhr_ = remoting.xhr.get(
+ remoting.settings.DIRECTORY_API_BASE_URL + '/support-hosts/' +
+ encodeURIComponent(this.hostId_),
+ this.onIT2MeHostInfo_.bind(this),
+ '',
+ { 'Authorization': 'OAuth ' + token });
+};
+
+/**
+ * Continue an IT2Me connection once the host JID has been looked up.
+ *
+ * @param {XMLHttpRequest} xhr The server response to the support-hosts query.
+ * @return {void} Nothing.
+ * @private
+ */
+remoting.SessionConnector.prototype.onIT2MeHostInfo_ = function(xhr) {
+ this.pendingXhr_ = null;
+ if (xhr.status == 200) {
+ var host = /** @type {{data: {jabberId: string, publicKey: string}}} */
+ jsonParseSafe(xhr.responseText);
+ if (host && host.data && host.data.jabberId && host.data.publicKey) {
+ this.hostJid_ = host.data.jabberId;
+ this.hostPublicKey_ = host.data.publicKey;
+ this.createSessionIfReady_();
+ return;
+ } else {
+ console.error('Invalid "support-hosts" response from server.');
+ }
+ } else {
+ this.onError_(this.translateSupportHostsError(xhr.status));
+ }
+};
+
+/**
+ * Load the WCS driver script.
+ *
+ * @param {string} token An OAuth2 access token.
+ * @return {void} Nothing.
+ * @private
+ */
+remoting.SessionConnector.prototype.loadWcs_ = function(token) {
+ remoting.wcsSandbox.setOnReady(this.onWcsLoaded_.bind(this));
+ remoting.wcsSandbox.setOnError(this.onError_);
+ remoting.wcsSandbox.setAccessToken(token);
+ this.startAccessTokenRefreshTimer_();
+};
+
+/**
+ * Continue an IT2Me or Me2Me connection once WCS has been loaded.
+ *
+ * @param {string} clientJid The full JID of the WCS client.
+ * @return {void} Nothing.
+ * @private
+ */
+remoting.SessionConnector.prototype.onWcsLoaded_ = function(clientJid) {
+ this.clientJid_ = clientJid;
+ this.createSessionIfReady_();
+};
+
+/**
+ * If both the client and host JIDs are available, create a session and connect.
+ *
+ * @return {void} Nothing.
+ * @private
+ */
+remoting.SessionConnector.prototype.createSessionIfReady_ = function() {
+ if (!this.clientJid_ || !this.hostJid_) {
+ return;
+ }
+
+ var securityTypes = 'spake2_hmac,spake2_plain';
+ this.clientSession_ = new remoting.ClientSession(
+ this.hostJid_, this.clientJid_, this.hostPublicKey_,
+ this.passPhrase_, securityTypes, this.hostId_,
+ this.connectionMode_);
+ this.clientSession_.logHostOfflineErrors(!this.refreshHostJidIfOffline_);
+ this.clientSession_.setOnStateChange(this.onStateChange_.bind(this));
+ this.clientSession_.createPluginAndConnect(this.pluginParent_);
+};
+
+/**
+ * Handle a change in the state of the client session prior to successful
+ * connection (after connection, this class no longer handles state change
+ * events). Errors that occur while connecting either trigger a reconnect
+ * or notify the onError handler.
+ *
+ * @param {number} oldState The previous state of the plugin.
+ * @param {number} newState The current state of the plugin.
+ * @return {void} Nothing.
+ * @private
+ */
+remoting.SessionConnector.prototype.onStateChange_ =
+ function(oldState, newState) {
+ switch (newState) {
+ case remoting.ClientSession.State.CONNECTED:
+ // When the connection succeeds, deregister for state-change callbacks
+ // and pass the session to the onOk callback. It is expected that it
+ // will register a new state-change callback to handle disconnect
+ // or error conditions.
+ this.clientSession_.setOnStateChange(null);
+ this.onOk_(this.clientSession_);
+ break;
+
+ case remoting.ClientSession.State.CREATED:
+ console.log('Created plugin');
+ break;
+
+ case remoting.ClientSession.State.BAD_PLUGIN_VERSION:
+ this.onError_(remoting.Error.BAD_PLUGIN_VERSION);
+ break;
+
+ case remoting.ClientSession.State.CONNECTING:
+ console.log('Connecting as ' + remoting.identity.getCachedEmail());
+ break;
+
+ case remoting.ClientSession.State.INITIALIZING:
+ console.log('Initializing connection');
+ break;
+
+ case remoting.ClientSession.State.CLOSED:
+ // This class deregisters for state-change callbacks when the CONNECTED
+ // state is reached, so it only sees the CLOSED state in exceptional
+ // circumstances. For example, a CONNECTING -> CLOSED transition happens
+ // if the host closes the connection without an error message instead of
+ // accepting it. Since there's no way of knowing exactly what went wrong,
+ // we rely on server-side logs in this case and report a generic error
+ // message.
+ this.onError_(remoting.Error.UNEXPECTED);
+ break;
+
+ case remoting.ClientSession.State.FAILED:
+ var error = this.clientSession_.getError();
+ console.error('Client plugin reported connection failed: ' + error);
+ if (error == null) {
+ error = remoting.Error.UNEXPECTED;
+ }
+ if (error == remoting.Error.HOST_IS_OFFLINE &&
+ this.refreshHostJidIfOffline_) {
+ this.refreshHostJidIfOffline_ = false;
+ this.clientSession_.removePlugin();
+ this.clientSession_ = null;
+ remoting.hostList.refresh(this.onHostListRefresh_.bind(this));
+ } else {
+ this.onError_(error);
+ }
+ break;
+
+ default:
+ console.error('Unexpected client plugin state: ' + newState);
+ // This should only happen if the web-app and client plugin get out of
+ // sync, and even then the version check should ensure compatibility.
+ this.onError_(remoting.Error.MISSING_PLUGIN);
+ }
+};
+
+/**
+ * @param {boolean} success True if the host list was successfully refreshed;
+ * false if an error occurred.
+ * @private
+ */
+remoting.SessionConnector.prototype.onHostListRefresh_ = function(success) {
+ if (success) {
+ var host = remoting.hostList.getHostForId(this.hostId_);
+ if (host) {
+ this.connectMe2Me(host, this.passPhrase_);
+ return;
+ }
+ }
+ this.onError_(remoting.Error.HOST_IS_OFFLINE);
+};
+
+/**
+ * Start a timer to periodically refresh the access token used by WCS. Access
+ * tokens have a limited lifespan, and since the WCS driver runs in a sandbox,
+ * it can't obtain a new one directly.
+ *
+ * @return {void} Nothing.
+ * @private
+ */
+remoting.SessionConnector.prototype.startAccessTokenRefreshTimer_ = function() {
+ if (this.wcsAccessTokenRefreshTimer_ != 0) {
+ return;
+ }
+
+ /** @type {remoting.SessionConnector} */
+ var that = this;
+ var refreshAccessToken = function() {
+ remoting.identity.callWithToken(
+ remoting.wcsSandbox.setAccessToken.bind(remoting.wcsSandbox),
+ that.onError_);
+ };
+ /**
+ * A timer that polls for an updated access token.
+ * @type {number}
+ * @private
+ */
+ this.wcsAccessTokenRefreshTimer_ = setInterval(refreshAccessToken,
+ 60 * 1000);
+}
+
+/**
+ * @param {number} error An HTTP error code returned by the support-hosts
+ * endpoint.
+ * @return {remoting.Error} The equivalent remoting.Error code.
+ * @private
+ */
+remoting.SessionConnector.prototype.translateSupportHostsError =
+ function(error) {
+ switch (error) {
+ case 0: return remoting.Error.NO_RESPONSE;
+ case 404: return remoting.Error.INVALID_ACCESS_CODE;
+ case 502: // No break
+ case 503: return remoting.Error.SERVICE_UNAVAILABLE;
+ default: return remoting.Error.UNEXPECTED;
+ }
+};
+
+/**
+ * Normalize the access code entered by the user.
+ *
+ * @param {string} accessCode The access code, as entered by the user.
+ * @return {string} The normalized form of the code (whitespace removed).
+ */
+remoting.SessionConnector.prototype.normalizeAccessCode_ =
+ function(accessCode) {
+ // Trim whitespace.
+ return accessCode.replace(/\s/g, '');
+};
diff --git a/remoting/webapp/ui_mode.js b/remoting/webapp/ui_mode.js
index fecc2b2..1b59c96 100644
--- a/remoting/webapp/ui_mode.js
+++ b/remoting/webapp/ui_mode.js
@@ -149,7 +149,7 @@ remoting.showOrHideCallback = function(mode, items) {
document.getElementById(mode + '-content').hidden = !visited;
};
-remoting.showOrHideIt2MeUi = function() {
+remoting.showOrHideIT2MeUi = function() {
chrome.storage.local.get('it2me-visited',
remoting.showOrHideCallback.bind(null, 'it2me'));
};
@@ -159,7 +159,7 @@ remoting.showOrHideMe2MeUi = function() {
remoting.showOrHideCallback.bind(null, 'me2me'));
};
-remoting.showIt2MeUiAndSave = function() {
+remoting.showIT2MeUiAndSave = function() {
var items = {};
items['it2me-visited'] = true;
chrome.storage.local.set(items);