diff options
author | sergeyu@chromium.org <sergeyu@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-04-06 17:47:16 +0000 |
---|---|---|
committer | sergeyu@chromium.org <sergeyu@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-04-06 17:47:16 +0000 |
commit | 980060ce951f04ebc5722a077e203a8302c5d4dd (patch) | |
tree | ef6f5c0ab1da7ba2f87188179aaa9c1af7fa76b7 /remoting | |
parent | 2c75400ac98ab4d0caae109f6ea8b1dc979aa24a (diff) | |
download | chromium_src-980060ce951f04ebc5722a077e203a8302c5d4dd.zip chromium_src-980060ce951f04ebc5722a077e203a8302c5d4dd.tar.gz chromium_src-980060ce951f04ebc5722a077e203a8302c5d4dd.tar.bz2 |
Move host registration code to the HostController class.
Review URL: https://chromiumcodereview.appspot.com/10007028
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@131146 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'remoting')
-rw-r--r-- | remoting/host/plugin/daemon_controller.h | 3 | ||||
-rw-r--r-- | remoting/webapp/host_controller.js | 148 | ||||
-rw-r--r-- | remoting/webapp/host_setup_dialog.js | 164 |
3 files changed, 134 insertions, 181 deletions
diff --git a/remoting/host/plugin/daemon_controller.h b/remoting/host/plugin/daemon_controller.h index 454e194..e760bf6 100644 --- a/remoting/host/plugin/daemon_controller.h +++ b/remoting/host/plugin/daemon_controller.h @@ -58,6 +58,9 @@ class DaemonController { // TODO(sergeyu): Current implementations don't return this value. RESULT_CANCELLED = 2, + // Failed to access host directory. + RESULT_FAILED_DIRECTORY = 3 + // TODO(sergeyu): Add more error codes when we know how to handle // them in the webapp. }; diff --git a/remoting/webapp/host_controller.js b/remoting/webapp/host_controller.js index 0e6f912..e839802 100644 --- a/remoting/webapp/host_controller.js +++ b/remoting/webapp/host_controller.js @@ -36,7 +36,8 @@ remoting.HostController.State = { remoting.HostController.AsyncResult = { OK: 0, FAILED: 1, - CANCELLED: 2 + CANCELLED: 2, + FAILED_DIRECTORY: 3 }; /** @return {remoting.HostController.State} The current state of the daemon. */ @@ -100,40 +101,94 @@ remoting.HostController.prototype.setTooltips = function() { }; /** - * Generates new host key pair. - * @param {function(string,string):void} callback Callback for the - * generated key pair. + * Registers and starts the host. + * @param {string} hostPin Host PIN. + * @param {function(remoting.HostController.AsyncResult):void} + * callback Callback to be called when done. * @return {void} Nothing. */ -remoting.HostController.prototype.generateKeyPair = function(callback) { - this.plugin_.generateKeyPair(callback); -}; +remoting.HostController.prototype.start = function(hostPin, callback) { + /** @type {remoting.HostController} */ + var that = this; -/** - * @return {string} Local hostname - */ -remoting.HostController.prototype.getHostName = function() { - return this.plugin_.getHostName(); -}; + /** @return {string} */ + function generateUuid() { + var random = new Uint16Array(8); + window.crypto.getRandomValues(random); + /** @type {Array.<string>} */ + var e = new Array(); + for (var i = 0; i < 8; i++) { + e[i] = (/** @type {number} */random[i] + 0x10000). + toString(16).substring(1); + } + return e[0] + e[1] + '-' + e[2] + "-" + e[3] + '-' + + e[4] + '-' + e[5] + e[6] + e[7]; + }; -/** - * Read current host configuration. - * @param {function(string):void} callback Host config callback. - * @return {void} Nothing. - */ -remoting.HostController.prototype.getConfig = function(callback) { - this.plugin_.getDaemonConfig(callback); -}; + var newHostId = generateUuid(); + // TODO(jamiewalch): Create an unprivileged API to get the host id from the + // plugin instead of storing it locally (crbug.com/121518). + window.localStorage.setItem('me2me-host-id', newHostId); -/** - * Start the daemon process. - * @param {string} config Host config. - * @param {function(remoting.HostController.AsyncResult):void} callback - * Callback to be called when finished. - * @return {void} Nothing. - */ -remoting.HostController.prototype.start = function(config, callback) { - this.plugin_.startDaemon(config, callback); + /** @param {string} privateKey + * @param {XMLHttpRequest} xhr */ + function onRegistered(privateKey, xhr) { + var success = (xhr.status == 200); + + if (success) { + // TODO(sergeyu): Calculate HMAC of the PIN instead of storing it + // in plaintext. + var hostConfig = JSON.stringify({ + xmpp_login: remoting.oauth2.getCachedEmail(), + oauth_refresh_token: remoting.oauth2.getRefreshToken(), + host_id: newHostId, + host_name: that.plugin_.getHostName(), + host_secret_hash: 'plain:' + window.btoa(hostPin), + private_key: privateKey + }); + that.plugin_.startDaemon(hostConfig, callback); + } else { + console.log('Failed to register the host. Status: ' + xhr.status + + ' response: ' + xhr.responseText); + callback(remoting.HostController.AsyncResult.FAILED_DIRECTORY); + } + }; + + /** + * @param {string} privateKey + * @param {string} publicKey + * @param {string} oauthToken + */ + function doRegisterHost(privateKey, publicKey, oauthToken) { + var headers = { + 'Authorization': 'OAuth ' + oauthToken, + 'Content-type' : 'application/json; charset=UTF-8' + }; + + var newHostDetails = { data: { + hostId: newHostId, + hostName: that.plugin_.getHostName(), + publicKey: publicKey + } }; + remoting.xhr.post( + 'https://www.googleapis.com/chromoting/v1/@me/hosts/', + /** @param {XMLHttpRequest} xhr */ + function (xhr) { onRegistered(privateKey, xhr); }, + JSON.stringify(newHostDetails), + headers); + }; + + /** @param {string} privateKey + * @param {string} publicKey */ + function onKeyGenerated(privateKey, publicKey) { + remoting.oauth2.callWithToken( + /** @param {string} oauthToken */ + function(oauthToken) { + doRegisterHost(privateKey, publicKey, oauthToken); + }); + }; + + this.plugin_.generateKeyPair(onKeyGenerated); }; /** @@ -143,17 +198,32 @@ remoting.HostController.prototype.start = function(config, callback) { * @return {void} Nothing. */ remoting.HostController.prototype.stop = function(callback) { - this.plugin_.stopDaemon(callback); + /** @type {remoting.HostController} */ + var that = this; + + /** @param {remoting.HostController.AsyncResult} result */ + function onStopped(result) { + if (that.localHost && that.localHost.hostId) + remoting.HostList.unregisterHostById(that.localHost.hostId); + window.localStorage.removeItem('me2me-host-id'); + callback(result); + }; + this.plugin_.stopDaemon(onStopped); }; /** - * @param {string} config The new host config, JSON encoded. + * @param {string} newPin The new PIN to set * @param {function(remoting.HostController.AsyncResult):void} callback * Callback to be called when finished. * @return {void} Nothing. */ -remoting.HostController.prototype.updateConfig = function(config, callback) { - this.plugin_.updateDaemonConfig(config, callback); +remoting.HostController.prototype.updatePin = function(newPin, callback) { + // TODO(sergeyu): Calculate HMAC of the PIN instead of storing it + // in plaintext. + var newConfig = JSON.stringify({ + host_secret_hash: 'plain:' + window.btoa(newPin) + }); + this.plugin_.updateDaemonConfig(newConfig, callback); }; /** @@ -208,15 +278,5 @@ remoting.HostController.prototype.onHostListRefresh = onDone(); }; -/** - * Unregister the local host - * - * @return {void} Nothing. - */ -remoting.HostController.prototype.unregister = function() { - remoting.HostList.unregisterHostById(this.localHost.hostId); - window.localStorage.removeItem('me2me-host-id'); -}; - /** @type {remoting.HostController} */ remoting.hostController = null; diff --git a/remoting/webapp/host_setup_dialog.js b/remoting/webapp/host_setup_dialog.js index ad77b73..8edafa1 100644 --- a/remoting/webapp/host_setup_dialog.js +++ b/remoting/webapp/host_setup_dialog.js @@ -18,7 +18,6 @@ remoting.HostSetupFlow = function(sequence) { this.state_ = sequence[0]; this.pin = ''; - this.hostConfig = ''; }; /** @enum {number} */ @@ -32,21 +31,20 @@ remoting.HostSetupFlow.State = { INSTALL_HOST: 2, // Processing states. - REGISTERING_HOST: 3, - STARTING_HOST: 4, - UPDATING_PIN: 5, - STOPPING_HOST: 6, + STARTING_HOST: 3, + UPDATING_PIN: 4, + STOPPING_HOST: 5, // Done states. - HOST_STARTED: 7, - UPDATED_PIN: 8, - HOST_STOPPED: 9, + HOST_STARTED: 6, + UPDATED_PIN: 7, + HOST_STOPPED: 8, // Failure states. - REGISTRATION_FAILED: 10, - START_HOST_FAILED: 11, - UPDATE_PIN_FAILED: 12, - STOP_HOST_FAILED: 13 + REGISTRATION_FAILED: 9, + START_HOST_FAILED: 10, + UPDATE_PIN_FAILED: 11, + STOP_HOST_FAILED: 12 }; /** @return {remoting.HostSetupFlow.State} Current state of the flow. */ @@ -77,10 +75,12 @@ remoting.HostSetupFlow.prototype.switchToNextStep = function(result) { this.state_ = remoting.HostSetupFlow.State.NONE; } else { // Current step failed, so switch to corresponding error state. - if (this.state_ == remoting.HostSetupFlow.State.REGISTERING_HOST) { - this.state_ = remoting.HostSetupFlow.State.REGISTRATION_FAILED; - } else if (this.state_ == remoting.HostSetupFlow.State.STARTING_HOST) { - this.state_ = remoting.HostSetupFlow.State.START_HOST_FAILED; + if (this.state_ == remoting.HostSetupFlow.State.STARTING_HOST) { + if (result == remoting.HostController.AsyncResult.FAILED_DIRECTORY) { + this.state_ = remoting.HostSetupFlow.State.REGISTRATION_FAILED; + } else { + this.state_ = remoting.HostSetupFlow.State.START_HOST_FAILED; + } } else if (this.state_ == remoting.HostSetupFlow.State.UPDATING_PIN) { this.state_ = remoting.HostSetupFlow.State.UPDATE_PIN_FAILED; } else if (this.state_ == remoting.HostSetupFlow.State.STOPPING_HOST) { @@ -94,11 +94,12 @@ remoting.HostSetupFlow.prototype.switchToNextStep = function(result) { }; /** - * @param {remoting.HostController} daemon The parent daemon plugin instance. + * @param {remoting.HostController} hostController The HostController + * responsible for the host daemon. * @constructor */ -remoting.HostSetupDialog = function(daemon) { - this.daemon_ = daemon; +remoting.HostSetupDialog = function(hostController) { + this.hostController_ = hostController; this.pinEntry_ = document.getElementById('daemon-pin-entry'); this.pinConfirm_ = document.getElementById('daemon-pin-confirm'); this.pinErrorDiv_ = document.getElementById('daemon-pin-error-div'); @@ -143,12 +144,12 @@ remoting.HostSetupDialog = function(daemon) { remoting.HostSetupDialog.prototype.showForStart = function() { var flow = [ remoting.HostSetupFlow.State.ASK_PIN, - remoting.HostSetupFlow.State.REGISTERING_HOST, remoting.HostSetupFlow.State.STARTING_HOST, remoting.HostSetupFlow.State.HOST_STARTED]; if (navigator.platform.indexOf('Mac') != -1 && - this.daemon_.state() == remoting.HostController.State.NOT_INSTALLED) { + this.hostController_.state() == + remoting.HostController.State.NOT_INSTALLED) { flow.unshift(remoting.HostSetupFlow.State.INSTALL_HOST); } @@ -236,9 +237,6 @@ remoting.HostSetupDialog.prototype.updateState_ = function() { remoting.setMode(remoting.AppMode.HOST_SETUP_INSTALL); window.location = 'http://dl.google.com/chrome-remote-desktop/chromeremotedesktop.dmg'; - } else if (state == remoting.HostSetupFlow.State.REGISTERING_HOST) { - showProcessingMessage(/*i18n-content*/'HOST_SETUP_STARTING'); - this.registerHost_(); } else if (state == remoting.HostSetupFlow.State.STARTING_HOST) { showProcessingMessage(/*i18n-content*/'HOST_SETUP_STARTING'); this.startHost_(); @@ -266,111 +264,7 @@ remoting.HostSetupDialog.prototype.updateState_ = function() { }; /** - * Registers new host. - * TODO(jamiewalch): This doesn't feel like it belongs here. I think it would be - * better as a member of HostController, alongside unregister. - */ -remoting.HostSetupDialog.prototype.registerHost_ = function() { - /** @type {remoting.HostSetupDialog} */ - var that = this; - /** @type {remoting.HostSetupFlow} */ - var flow = this.flow_; - - /** @return {string} */ - function generateUuid() { - var random = new Uint16Array(8); - window.crypto.getRandomValues(random); - /** @type {Array.<string>} */ - var e = new Array(); - for (var i = 0; i < 8; i++) { - e[i] = (/** @type {number} */random[i] + 0x10000). - toString(16).substring(1); - } - return e[0] + e[1] + '-' + e[2] + "-" + e[3] + '-' + - e[4] + '-' + e[5] + e[6] + e[7]; - } - - var newHostId = generateUuid(); - // TODO(jamiewalch): Create an unprivileged API to get the host id from the - // plugin instead of storing it locally (crbug.com/121518). - window.localStorage.setItem('me2me-host-id', newHostId); - - /** @param {string} privateKey - * @param {XMLHttpRequest} xhr */ - function onRegistered(privateKey, xhr) { - if (flow !== that.flow_ || - flow.getState() != remoting.HostSetupFlow.State.REGISTERING_HOST) { - console.error('Host setup was interrupted when registering the host'); - return; - } - - var success = (xhr.status == 200); - - if (success) { - // TODO(sergeyu): Calculate HMAC of the PIN instead of storing it - // in plaintext. - flow.hostConfig = JSON.stringify({ - xmpp_login: remoting.oauth2.getCachedEmail(), - oauth_refresh_token: remoting.oauth2.getRefreshToken(), - host_id: newHostId, - host_name: that.daemon_.getHostName(), - host_secret_hash: 'plain:' + window.btoa(flow.pin), - private_key: privateKey - }); - } else { - console.log('Failed to register the host. Status: ' + xhr.status + - ' response: ' + xhr.responseText); - } - - flow.switchToNextStep(success ? remoting.HostController.AsyncResult.OK : - remoting.HostController.AsyncResult.FAILED); - that.updateState_(); - } - - /** - * @param {string} privateKey - * @param {string} publicKey - * @param {string} oauthToken - */ - function doRegisterHost(privateKey, publicKey, oauthToken) { - if (flow !== that.flow_ || - flow.getState() != remoting.HostSetupFlow.State.REGISTERING_HOST) { - console.error('Host setup was interrupted when generating key pair'); - return; - } - - var headers = { - 'Authorization': 'OAuth ' + oauthToken, - 'Content-type' : 'application/json; charset=UTF-8' - }; - - var newHostDetails = { data: { - hostId: newHostId, - hostName: that.daemon_.getHostName(), - publicKey: publicKey - } }; - remoting.xhr.post( - 'https://www.googleapis.com/chromoting/v1/@me/hosts/', - /** @param {XMLHttpRequest} xhr */ - function (xhr) { onRegistered(privateKey, xhr); }, - JSON.stringify(newHostDetails), - headers); - } - - this.daemon_.generateKeyPair( - /** @param {string} privateKey - * @param {string} publicKey */ - function(privateKey, publicKey) { - remoting.oauth2.callWithToken( - /** @param {string} oauthToken */ - function(oauthToken) { - doRegisterHost(privateKey, publicKey, oauthToken); - }); - }); -}; - -/** - * Starts the host process after it's registered. + * Registers and starts the host. */ remoting.HostSetupDialog.prototype.startHost_ = function() { /** @type {remoting.HostSetupDialog} */ @@ -389,7 +283,7 @@ remoting.HostSetupDialog.prototype.startHost_ = function() { flow.switchToNextStep(result); that.updateState_(); } - this.daemon_.start(this.flow_.hostConfig, onHostStarted); + this.hostController_.start(this.flow_.pin, onHostStarted); }; remoting.HostSetupDialog.prototype.updatePin_ = function() { @@ -410,10 +304,7 @@ remoting.HostSetupDialog.prototype.updatePin_ = function() { that.updateState_(); } - var newConfig = JSON.stringify({ - host_secret_hash: 'plain:' + window.btoa(flow.pin) - }); - this.daemon_.updateConfig(newConfig, onPinUpdated); + this.hostController_.updatePin(flow.pin, onPinUpdated); } /** @@ -433,11 +324,10 @@ remoting.HostSetupDialog.prototype.stopHost_ = function() { return; } - that.daemon_.unregister(); flow.switchToNextStep(result); that.updateState_(); } - this.daemon_.stop(onHostStopped); + this.hostController_.stop(onHostStopped); }; /** @private */ @@ -499,7 +389,7 @@ remoting.HostSetupDialog.validPin_ = function(pin) { * @return {void} Nothing. */ remoting.HostSetupDialog.prototype.onInstallDialogOk = function() { - var state = this.daemon_.state(); + var state = this.hostController_.state(); if (state == remoting.HostController.State.STOPPED) { this.flow_.switchToNextStep(remoting.HostController.AsyncResult.OK); this.updateState_(); |