diff options
author | sergeyu@chromium.org <sergeyu@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-03-29 21:20:47 +0000 |
---|---|---|
committer | sergeyu@chromium.org <sergeyu@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-03-29 21:20:47 +0000 |
commit | 99f344d9b8b2231d96f865e2cfb227dafe68b71c (patch) | |
tree | 423834119d20609991910b22448aaa2e052c0969 /remoting/webapp | |
parent | 23341b263ef7449b6248adad82642d06dc89cb0d (diff) | |
download | chromium_src-99f344d9b8b2231d96f865e2cfb227dafe68b71c.zip chromium_src-99f344d9b8b2231d96f865e2cfb227dafe68b71c.tar.gz chromium_src-99f344d9b8b2231d96f865e2cfb227dafe68b71c.tar.bz2 |
Implement Me2Me setup flow.
Review URL: https://chromiumcodereview.appspot.com/9921001
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@129692 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'remoting/webapp')
-rw-r--r-- | remoting/webapp/_locales/en/messages.json | 28 | ||||
-rw-r--r-- | remoting/webapp/ask_pin_dialog.js | 111 | ||||
-rw-r--r-- | remoting/webapp/daemon_plugin.js | 43 | ||||
-rw-r--r-- | remoting/webapp/event_handlers.js | 4 | ||||
-rw-r--r-- | remoting/webapp/host_plugin_proto.js | 16 | ||||
-rw-r--r-- | remoting/webapp/host_setup_dialog.js | 351 | ||||
-rw-r--r-- | remoting/webapp/main.css | 2 | ||||
-rw-r--r-- | remoting/webapp/main.html | 26 | ||||
-rw-r--r-- | remoting/webapp/remoting.js | 3 | ||||
-rw-r--r-- | remoting/webapp/ui_mode.js | 6 | ||||
-rw-r--r-- | remoting/webapp/xhr.js | 4 |
11 files changed, 452 insertions, 142 deletions
diff --git a/remoting/webapp/_locales/en/messages.json b/remoting/webapp/_locales/en/messages.json index ee8791b..a0a41c3 100644 --- a/remoting/webapp/_locales/en/messages.json +++ b/remoting/webapp/_locales/en/messages.json @@ -17,10 +17,6 @@ "message": "All connections", "description": "In the connection history dialog, clicking this button shows all recent connections unfiltered." }, - "ASK_PIN_DIALOG_DESCRIPTION": { - "message": "To protect access to this computer, please choose a PIN. This PIN will be required when connecting from another location.", - "description": "Explanatory text displayed when the user enables remote access or changes the PIN." - }, "ASK_PIN_DIALOG_LABEL": { "message": "PIN", "description": "Label next to the PIN entry edit box. The user must enter a PIN before enabling remote access to their computer." @@ -222,6 +218,30 @@ "message": "To securely access this computer from anywhere you sign in to Chromoting, you must first enable remote connections.", "description": "Message displayed when the current computer is not accepting remote connections, instructing the user how to enable them." }, + "HOST_SETUP_DIALOG_DESCRIPTION": { + "message": "To protect access to this computer, please choose a PIN. This PIN will be required when connecting from another location.", + "description": "Explanatory text displayed when the user enables remote access or changes the PIN." + }, + "HOST_SETUP_HOST_FAILED": { + "message": "Failed to start remote access service.", + "description": "Message shown when host service fails to start when enabling the host on local computer." + }, + "HOST_SETUP_REGISTRATION_FAILED": { + "message": "Failed to register this computer.", + "description": "Message shown when host registration fails when enabling the host on local computer." + }, + "HOST_SETUP_STARTED": { + "message": "Remote connections for this computer have been enabled.", + "description": "Message shown after access to local computer has been enabled successfully." + }, + "HOST_SETUP_STARTING": { + "message": "Enabling remote connections for this computer.", + "description": "Message shown when local machine is being registered in the directory and when starting the host." + }, + "HOST_SETUP_UPDATING_PIN": { + "message": "PIN for this computer is being updated.", + "description": "Message shown while changing PIN for the local computer." + }, "HOME_SHARE_BUTTON": { "message": "Share", "description": "Clicking this button starts the desktop sharing process." diff --git a/remoting/webapp/ask_pin_dialog.js b/remoting/webapp/ask_pin_dialog.js deleted file mode 100644 index 176fdf4..0000000 --- a/remoting/webapp/ask_pin_dialog.js +++ /dev/null @@ -1,111 +0,0 @@ -// Copyright (c) 2012 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. - -'use strict'; - -/** @suppress {duplicate} */ -var remoting = remoting || {}; - -/** - * @param {remoting.DaemonPlugin} daemon The parent daemon plugin instance. - * @constructor - */ -remoting.AskPinDialog = function(daemon) { - this.startDaemon_ = false; - this.daemon_ = daemon; - this.okButton_ = document.getElementById('daemon-pin-ok'); - this.spinner_ = document.getElementById('start-daemon-spinner'); - this.pinEntry_ = document.getElementById('daemon-pin-entry'); - this.pinConfirm_ = document.getElementById('daemon-pin-confirm'); - /** @type {remoting.AskPinDialog} */ - var that = this; - /** @param {Event} event The event. */ - var onSubmit = function(event) { - event.preventDefault(); - that.onSubmit_(); - }; - var form = document.getElementById('ask-pin-form'); - form.addEventListener('submit', onSubmit, false); -}; - -/** - * Show the dialog in order to get a PIN prior to starting the daemon. When the - * user clicks OK, the dialog shows a spinner until the daemon has started. - * - * @return {void} Nothing. - */ -remoting.AskPinDialog.prototype.showForStart = function() { - remoting.setMode(remoting.AppMode.ASK_PIN); - this.startDaemon_ = true; -}; - -/** - * Show the dialog in order to change the PIN associated with a running daemon. - * - * @return {void} Nothing. - */ -remoting.AskPinDialog.prototype.showForPin = function() { - remoting.setMode(remoting.AppMode.ASK_PIN); - this.startDaemon_ = false; -}; - -/** - * @return {void} Nothing. - */ -remoting.AskPinDialog.prototype.hide = function() { - remoting.setMode(remoting.AppMode.HOME); -}; - -/** @private */ -remoting.AskPinDialog.prototype.onSubmit_ = function() { - // TODO(jamiewalch): Add validation and error checks when we improve the UI. - var pin = this.pinEntry_.value; - this.daemon_.setPin(pin); - if (this.startDaemon_) { - this.daemon_.start(); - this.pollDaemonState_(); - } else { - this.hide(); - } -}; - -/** - * @return {void} Nothing. - * @private - */ -remoting.AskPinDialog.prototype.pollDaemonState_ = function() { - var state = this.daemon_.state(); - var retry = false; // Set to true if we haven't finished yet. - switch (state) { - case remoting.DaemonPlugin.State.STOPPED: - case remoting.DaemonPlugin.State.NOT_INSTALLED: - retry = true; - break; - case remoting.DaemonPlugin.State.STARTED: - this.hide(); - this.daemon_.updateDom(); - break; - case remoting.DaemonPlugin.State.START_FAILED: - // TODO(jamiewalch): Show an error message. - break; - default: - // TODO(jamiewalch): Show an error message. - console.error('Unexpected daemon state', state); - break; - } - if (retry) { - this.okButton_.hidden = true; - this.spinner_.hidden = false; - /** @type {remoting.AskPinDialog} */ - var that = this; - var pollDaemonState = function() { that.pollDaemonState_(); } - window.setTimeout(pollDaemonState, 1000); - } else { - this.okButton_.hidden = false; - this.spinner_.hidden = true; - } -}; - -/** @type {remoting.AskPinDialog} */ -remoting.askPinDialog = null; diff --git a/remoting/webapp/daemon_plugin.js b/remoting/webapp/daemon_plugin.js index cec5a8f..2f16fda 100644 --- a/remoting/webapp/daemon_plugin.js +++ b/remoting/webapp/daemon_plugin.js @@ -44,6 +44,8 @@ remoting.DaemonPlugin.prototype.state = function() { * @return {void} Nothing. */ remoting.DaemonPlugin.prototype.updateDom = function() { + // TODO(sergeyu): This code updates UI state. Does it belong here, + // or should it moved somewhere else? var match = ''; switch (this.state()) { case remoting.DaemonPlugin.State.STARTED: @@ -59,27 +61,54 @@ remoting.DaemonPlugin.prototype.updateDom = function() { }; /** + * Generates new host key pair. + * @param {function(string,string):void} callback Callback for the + * generated key pair. + * @return {void} Nothing. + */ +remoting.DaemonPlugin.prototype.generateKeyPair = function(callback) { + this.plugin_.generateKeyPair(callback); +}; + +/** + * @return {string} Local hostname + */ +remoting.DaemonPlugin.prototype.getHostName = function() { + return this.plugin_.getHostName(); +}; + +/** + * Read current host configuration. + * @param {function(string):void} callback Host config callback. + * @return {void} Nothing. + */ +remoting.DaemonPlugin.prototype.getConfig = function(callback) { + this.plugin_.getDaemonConfig(callback); +}; + +/** * Start the daemon process. - * @return {boolean} False if insufficient state has been set. + * @param {string} config Host config. + * @return {void} Nothing. */ -remoting.DaemonPlugin.prototype.start = function() { - return this.plugin_.startDaemon(); +remoting.DaemonPlugin.prototype.start = function(config) { + this.plugin_.startDaemon(config); }; /** * Stop the daemon process. - * @return {boolean} False if insufficient state has been set. + * @return {void} Nothing. */ remoting.DaemonPlugin.prototype.stop = function() { - return this.plugin_.stopDaemon(); + this.plugin_.stopDaemon(); }; /** * @param {string} pin The new PIN for the daemon process. - * @return {boolean} True if the PIN was set successfully. + * @return {void} Nothing. */ remoting.DaemonPlugin.prototype.setPin = function(pin) { - return this.plugin_.setDaemonPin(pin); + this.plugin_.setDaemonPin(pin); }; /** @type {remoting.DaemonPlugin} */ diff --git a/remoting/webapp/event_handlers.js b/remoting/webapp/event_handlers.js index a245908..c36787a 100644 --- a/remoting/webapp/event_handlers.js +++ b/remoting/webapp/event_handlers.js @@ -66,9 +66,9 @@ function onLoad() { { event: 'click', id: 'toolbar-stub', fn: function() { remoting.toolbar.toggle(); } }, { event: 'click', id: 'start-daemon', - fn: function() { remoting.askPinDialog.showForStart(); } }, + fn: function() { remoting.hostSetupDialog.showForStart(); } }, { event: 'click', id: 'change-daemon-pin', - fn: function() { remoting.askPinDialog.showForPin(); } }, + 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 }, diff --git a/remoting/webapp/host_plugin_proto.js b/remoting/webapp/host_plugin_proto.js index f555d10..6760fe4 100644 --- a/remoting/webapp/host_plugin_proto.js +++ b/remoting/webapp/host_plugin_proto.js @@ -25,11 +25,20 @@ remoting.HostPlugin.prototype.disconnect = function() {}; * @return {void} Nothing. */ remoting.HostPlugin.prototype.localize = function(callback) {}; +/** @return {string} Local hostname. */ +remoting.HostPlugin.prototype.getHostName = function() {}; + +/** @param {function(string, string):void} callback Callback to be called + * after new key is generated. + * @return {void} Nothing. */ +remoting.HostPlugin.prototype.generateKeyPair = function(callback) {}; + /** @param {string} pin The new PIN. * @return {void} Nothing. */ remoting.HostPlugin.prototype.setDaemonPin = function(pin) {}; -/** @param {string} callback Callback to be called for the config. +/** @param {function(string):void} callback Callback to be called for + * the config. * @return {void} Nothing. */ remoting.HostPlugin.prototype.getDaemonConfig = function(callback) {}; @@ -40,11 +49,6 @@ remoting.HostPlugin.prototype.startDaemon = function(config) {}; /** @return {void} Nothing. */ remoting.HostPlugin.prototype.stopDaemon = function() {}; -/** @param {function(string):void} callback Callback to be called - * after new key is generated. - * @return {void} Nothing. */ -remoting.HostPlugin.prototype.generateKeyPair = function(callback) {}; - /** @type {number} */ remoting.HostPlugin.prototype.state; /** @type {number} */ remoting.HostPlugin.prototype.STARTING; diff --git a/remoting/webapp/host_setup_dialog.js b/remoting/webapp/host_setup_dialog.js new file mode 100644 index 0000000..1e9e66c --- /dev/null +++ b/remoting/webapp/host_setup_dialog.js @@ -0,0 +1,351 @@ +// Copyright (c) 2012 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. + +'use strict'; + +/** @suppress {duplicate} */ +var remoting = remoting || {}; + +/** + * @param {Array.<remoting.HostSetupFlow.State>} sequence Sequence of + * steps for the flow. + * @constructor + */ +remoting.HostSetupFlow = function(sequence) { + this.sequence_ = sequence; + this.currentStep_ = 0; + this.state_ = sequence[0]; + + this.pin = ''; + this.hostConfig = ''; +}; + +/** @enum {number} */ +remoting.HostSetupFlow.State = { + NONE: 0, + ASK_PIN: 1, + REGISTER_HOST: 2, + START_HOST: 3, + HOST_STARTED: 4, + UPDATE_PIN: 5, + REGISTRATION_FAILED: 6, + HOST_START_FAILED: 7 +}; + +/** @return {remoting.HostSetupFlow.State} Current state of the flow. */ +remoting.HostSetupFlow.prototype.getState = function() { + return this.state_; +}; + +/** + * @param {boolean} success + * @return {remoting.HostSetupFlow.State} New state. + */ +remoting.HostSetupFlow.prototype.switchToNextStep = function(success) { + if (this.state_ == remoting.HostSetupFlow.State.NONE) { + return this.state_; + } + if (success) { + // If the current step was successful then switch to the next + // step in the sequence. + if (this.currentStep_ < this.sequence_.length - 1) { + this.currentStep_ += 1; + this.state_ = this.sequence_[this.currentStep_]; + } else { + this.state_ = remoting.HostSetupFlow.State.NONE; + } + } else { + // Current step failed, so switch to corresponding error state. + if (this.state_ == remoting.HostSetupFlow.State.REGISTER_HOST) { + this.state_ = remoting.HostSetupFlow.State.REGISTRATION_FAILED; + } else { + // TODO(sergeyu): Add other error states and use them here. + this.state_ = remoting.HostSetupFlow.State.HOST_START_FAILED; + } + } + return this.state_; +}; + +/** + * @param {remoting.DaemonPlugin} daemon The parent daemon plugin instance. + * @constructor + */ +remoting.HostSetupDialog = function(daemon) { + this.daemon_ = daemon; + this.pinEntry_ = document.getElementById('daemon-pin-entry'); + this.pinConfirm_ = document.getElementById('daemon-pin-confirm'); + + /** @type {remoting.HostSetupFlow} */ + this.flow_ = new remoting.HostSetupFlow([remoting.HostSetupFlow.State.NONE]); + + /** @type {remoting.HostSetupDialog} */ + var that = this; + /** @param {Event} event The event. */ + var onPinSubmit = function(event) { + event.preventDefault(); + that.onPinSubmit_(); + }; + var form = document.getElementById('ask-pin-form'); + form.addEventListener('submit', onPinSubmit, false); +}; + +/** + * Show the dialog in order to get a PIN prior to starting the daemon. When the + * user clicks OK, the dialog shows a spinner until the daemon has started. + * + * @return {void} Nothing. + */ +remoting.HostSetupDialog.prototype.showForStart = function() { + this.startNewFlow_( + [remoting.HostSetupFlow.State.ASK_PIN, + remoting.HostSetupFlow.State.REGISTER_HOST, + remoting.HostSetupFlow.State.START_HOST, + remoting.HostSetupFlow.State.HOST_STARTED]); +}; + +/** + * Show the dialog in order to change the PIN associated with a running daemon. + * + * @return {void} Nothing. + */ +remoting.HostSetupDialog.prototype.showForPin = function() { + this.startNewFlow_( + [remoting.HostSetupFlow.State.ASK_PIN, + remoting.HostSetupFlow.State.UPDATE_PIN]); +}; + +/** + * @return {void} Nothing. + */ +remoting.HostSetupDialog.prototype.hide = function() { + remoting.setMode(remoting.AppMode.HOME); +}; + +/** + * Starts new flow with the specified sequence of steps. + * @param {Array.<remoting.HostSetupFlow.State>} sequence Sequence of steps. + * @private + */ +remoting.HostSetupDialog.prototype.startNewFlow_ = function(sequence) { + this.flow_ = new remoting.HostSetupFlow(sequence); + this.pinEntry_.text = ''; + this.pinConfirm_.text = ''; + this.updateState_(); +}; + +/** + * Updates current UI mode according to the current state of the setup + * flow and start the action corresponding to the current step (if + * any). + * @private + */ +remoting.HostSetupDialog.prototype.updateState_ = function() { + /** @param {string} tag */ + function showProcessingMessage(tag) { + var errorDiv = document.getElementById('host-setup-processing-message'); + l10n.localizeElementFromTag(errorDiv, tag); + remoting.setMode(remoting.AppMode.HOST_SETUP_PROCESSING); + } + /** @param {string} tag */ + function showDoneMessage(tag) { + var errorDiv = document.getElementById('host-setup-done-message'); + l10n.localizeElementFromTag(errorDiv, tag); + remoting.setMode(remoting.AppMode.HOST_SETUP_DONE); + } + /** @param {string} tag */ + function showErrorMessage(tag) { + var errorDiv = document.getElementById('host-setup-error-message'); + l10n.localizeElementFromTag(errorDiv, tag); + remoting.setMode(remoting.AppMode.HOST_SETUP_ERROR); + } + + var state = this.flow_.getState(); + if (state == remoting.HostSetupFlow.State.NONE) { + this.hide(); + } else if (state == remoting.HostSetupFlow.State.ASK_PIN) { + remoting.setMode(remoting.AppMode.HOST_SETUP_ASK_PIN); + } else if (state == remoting.HostSetupFlow.State.REGISTER_HOST) { + showProcessingMessage(/*i18n-content*/'HOST_SETUP_STARTING'); + this.registerHost_(); + } else if (state == remoting.HostSetupFlow.State.START_HOST) { + showProcessingMessage(/*i18n-content*/'HOST_SETUP_STARTING'); + this.startHost_(); + } else if (state == remoting.HostSetupFlow.State.UPDATE_PIN) { + showProcessingMessage(/*i18n-content*/'HOST_SETUP_UPDATING_PIN'); + this.updatePin_(); + } else if (state == remoting.HostSetupFlow.State.HOST_STARTED) { + showDoneMessage(/*i18n-content*/'HOST_SETUP_STARTED'); + } else if (state == remoting.HostSetupFlow.State.REGISTRATION_FAILED) { + showErrorMessage(/*i18n-content*/'HOST_SETUP_REGISTRATION_FAILED'); + } else if (state == remoting.HostSetupFlow.State.HOST_START_FAILED) { + showErrorMessage(/*i18n-content*/'HOST_SETUP_HOST_FAILED'); + } +}; + +/** + * Registers new host. + */ +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(); + + /** @param {string} privateKey + * @param {XMLHttpRequest} xhr */ + function onRegistered(privateKey, xhr) { + if (flow !== that.flow_ || + flow.getState() != remoting.HostSetupFlow.State.REGISTER_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:' + flow.pin, + private_key: privateKey + }); + } else { + console.log('Failed to register the host. Status: ' + xhr.status + + ' response: ' + xhr.responseText); + } + + flow.switchToNextStep(success); + 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.REGISTER_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. + */ +remoting.HostSetupDialog.prototype.startHost_ = function() { + this.daemon_.start(this.flow_.hostConfig); + this.pollDaemonState_(); +}; + +remoting.HostSetupDialog.prototype.updatePin_ = function() { + this.daemon_.setPin(this.flow_.pin); + this.pollDaemonState_(); +} + +/** @private */ +remoting.HostSetupDialog.prototype.onPinSubmit_ = function() { + if (this.flow_.getState() != remoting.HostSetupFlow.State.ASK_PIN) { + console.error('PIN submitted in an invalid state', this.flow_.getState()); + return; + } + // TODO(jamiewalch): Add validation and error checks when we improve the UI. + var pin = this.pinEntry_.value; + this.flow_.pin = pin; + this.flow_.switchToNextStep(true); + this.updateState_(); +}; + +/** + * @return {void} Nothing. + * @private + */ +remoting.HostSetupDialog.prototype.pollDaemonState_ = function() { + var state = this.daemon_.state(); + var retry = false; // Set to true if we haven't finished yet. + switch (state) { + case remoting.DaemonPlugin.State.STOPPED: + case remoting.DaemonPlugin.State.NOT_INSTALLED: + retry = true; + break; + case remoting.DaemonPlugin.State.STARTED: + if (this.flow_.getState() == remoting.HostSetupFlow.State.START_HOST || + this.flow_.getState() == remoting.HostSetupFlow.State.UPDATE_PIN) { + this.flow_.switchToNextStep(true); + this.updateState_(); + } + this.daemon_.updateDom(); + break; + case remoting.DaemonPlugin.State.START_FAILED: + if (this.flow_.getState() == remoting.HostSetupFlow.State.START_HOST || + this.flow_.getState() == remoting.HostSetupFlow.State.UPDATE_PIN) { + this.flow_.switchToNextStep(false); + this.updateState_(); + } + break; + default: + // TODO(jamiewalch): Show an error message. + console.error('Unexpected daemon state', state); + break; + } + if (retry) { + /** @type {remoting.HostSetupDialog} */ + var that = this; + var pollDaemonState = function() { that.pollDaemonState_(); } + window.setTimeout(pollDaemonState, 1000); + } +}; + +/** @type {remoting.HostSetupDialog} */ +remoting.hostSetupDialog = null; diff --git a/remoting/webapp/main.css b/remoting/webapp/main.css index 8c2b153..26f0132 100644 --- a/remoting/webapp/main.css +++ b/remoting/webapp/main.css @@ -438,7 +438,7 @@ button { margin-top: 24px; } -#ask-pin-dialog { +#host-setup-dialog { position: absolute; top: 50%; left: 50%; diff --git a/remoting/webapp/main.html b/remoting/webapp/main.html index 9a3826a..7722ff5 100644 --- a/remoting/webapp/main.html +++ b/remoting/webapp/main.html @@ -16,7 +16,7 @@ found in the LICENSE file. <link rel="stylesheet" href="main.css"> <link rel="stylesheet" href="menu_button.css"> <link rel="stylesheet" href="toolbar.css"> - <script src="ask_pin_dialog.js"></script> + <script src="host_setup_dialog.js"></script> <script src="client_plugin_async.js"></script> <script src="client_plugin_v1.js"></script> <script src="client_screen.js"></script> @@ -185,18 +185,19 @@ found in the LICENSE file. </div> <!-- home --> <div id="dialog-screen" - data-ui-mode="home.host home.client home.auth home.history home.confirm-host-delete home.ask-pin" + data-ui-mode="home.host home.client home.auth home.history home.confirm-host-delete home.host-setup" hidden></div> <div id="dialog-container" - data-ui-mode="home.host home.client home.auth home.history home.confirm-host-delete home.ask-pin" + data-ui-mode="home.host home.client home.auth home.history home.confirm-host-delete home.host-setup" hidden> <div class="box-spacer"></div> - <div id="ask-pin-dialog" data-ui-mode="home.ask-pin" hidden> - <p i18n-content="ASK_PIN_DIALOG_DESCRIPTION"></p> - <form id="ask-pin-form" action=""> + <div id="host-setup-dialog" data-ui-mode="home.host-setup" hidden> + <p i18n-content="HOST_SETUP_DIALOG_DESCRIPTION"></p> + <form id="ask-pin-form" data-ui-mode="home.host-setup.ask-pin" + action="" hidden> <label for="daemon-pin-input" i18n-content="ASK_PIN_DIALOG_LABEL"></label> <input id="daemon-pin-entry" type="password"> @@ -205,9 +206,18 @@ found in the LICENSE file. i18n-content="ASK_PIN_DIALOG_CONFIRM_LABEL"></label> <input id="daemon-pin-confirm" type="password"> <button id="daemon-pin-ok" type="submit" i18n-content="OK"></button> - <img id="start-daemon-spinner" src="spinner.gif" hidden> </form> - </div> <!-- ask-pin-dialog --> + <div data-ui-mode="home.host-setup.processing" hidden> + <img src="spinner.gif"> + <span id="host-setup-processing-message" class="message"></span> + </div> + <div data-ui-mode="home.host-setup.done" hidden> + <span id="host-setup-done-message" class="message"></span> + </div> + <div data-ui-mode="home.host-setup.error" hidden> + <span id="host-setup-error-message" class="error-state"></span> + </div> + </div> <!-- host-setup-dialog --> <div id="auth-dialog" data-ui-mode="home.auth" diff --git a/remoting/webapp/remoting.js b/remoting/webapp/remoting.js index 6ec9694..4266e0b 100644 --- a/remoting/webapp/remoting.js +++ b/remoting/webapp/remoting.js @@ -86,7 +86,8 @@ remoting.initDaemonUi = function () { remoting.daemonPlugin = new remoting.DaemonPlugin(); remoting.daemonPlugin.updateDom(); remoting.setMode(getAppStartupMode_()); - remoting.askPinDialog = new remoting.AskPinDialog(remoting.daemonPlugin); + remoting.hostSetupDialog = + new remoting.HostSetupDialog(remoting.daemonPlugin); }; /** diff --git a/remoting/webapp/ui_mode.js b/remoting/webapp/ui_mode.js index ecb5d57..f8ee589 100644 --- a/remoting/webapp/ui_mode.js +++ b/remoting/webapp/ui_mode.js @@ -38,7 +38,11 @@ remoting.AppMode = { CLIENT_SESSION_FINISHED_ME2ME: 'home.client.session-finished.me2me', HISTORY: 'home.history', CONFIRM_HOST_DELETE: 'home.confirm-host-delete', - ASK_PIN: 'home.ask-pin', + HOST_SETUP: 'home.host-setup', + HOST_SETUP_ASK_PIN: 'home.host-setup.ask-pin', + HOST_SETUP_PROCESSING: 'home.host-setup.processing', + HOST_SETUP_DONE: 'home.host-setup.done', + HOST_SETUP_ERROR: 'home.host-setup.error', IN_SESSION: 'in-session' }; diff --git a/remoting/webapp/xhr.js b/remoting/webapp/xhr.js index 2a48077..b0c2056 100644 --- a/remoting/webapp/xhr.js +++ b/remoting/webapp/xhr.js @@ -164,7 +164,9 @@ remoting.xhr.doMethod = function(methodName, url, onDone, } xhr.open(methodName, url, true); - if (methodName == 'POST') { + if (methodName == 'POST' && + (typeof opt_headers !== 'object' || + typeof opt_headers['Content-type'] !== 'string')) { xhr.setRequestHeader('Content-type', 'application/x-www-form-urlencoded'); } // Add in request headers. |