summaryrefslogtreecommitdiffstats
path: root/remoting/webapp
diff options
context:
space:
mode:
authorsergeyu@chromium.org <sergeyu@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-03-29 21:20:47 +0000
committersergeyu@chromium.org <sergeyu@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-03-29 21:20:47 +0000
commit99f344d9b8b2231d96f865e2cfb227dafe68b71c (patch)
tree423834119d20609991910b22448aaa2e052c0969 /remoting/webapp
parent23341b263ef7449b6248adad82642d06dc89cb0d (diff)
downloadchromium_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.json28
-rw-r--r--remoting/webapp/ask_pin_dialog.js111
-rw-r--r--remoting/webapp/daemon_plugin.js43
-rw-r--r--remoting/webapp/event_handlers.js4
-rw-r--r--remoting/webapp/host_plugin_proto.js16
-rw-r--r--remoting/webapp/host_setup_dialog.js351
-rw-r--r--remoting/webapp/main.css2
-rw-r--r--remoting/webapp/main.html26
-rw-r--r--remoting/webapp/remoting.js3
-rw-r--r--remoting/webapp/ui_mode.js6
-rw-r--r--remoting/webapp/xhr.js4
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.