Commit d44e8a77 authored by garykac's avatar garykac Committed by Commit bot

[Chromoting] Show any startup errors in the LoadingWindow.

Show any connection errors during startup in the LoadingWindow rather
than creating a new error window for the error.

This cl also adds a new updateErrorMessage method to the MessageWindow
to update the message and reset the message window as appropriate for
an error message (disabling the spinner, updating the button label).

BUG=

Review URL: https://codereview.chromium.org/1139543002

Cr-Commit-Position: refs/heads/master@{#330022}
parent 319828dc
......@@ -189,8 +189,8 @@ remoting.AppRemotingActivity.prototype.onDisconnected = function(error) {
* @param {!remoting.Error} error
*/
remoting.AppRemotingActivity.prototype.onConnectionFailed = function(error) {
remoting.LoadingWindow.close();
this.showErrorMessage_(error);
remoting.loadingWindow_.updateErrorMessage(
chrome.i18n.getMessage(error.getTag()));
this.cleanup_();
};
......@@ -199,7 +199,7 @@ remoting.AppRemotingActivity.prototype.onConnectionFailed = function(error) {
* @private
*/
remoting.AppRemotingActivity.prototype.showErrorMessage_ = function(error) {
console.error('Connection failed: ' + error.toString());
console.error('Error: ' + error.toString());
remoting.MessageWindow.showErrorMessage(
remoting.app.getApplicationName(),
chrome.i18n.getMessage(error.getTag()));
......
......@@ -44,19 +44,16 @@ MessageWindowImpl.prototype.sendReply_ = function(
};
/**
* Initializes the button with the label and the click handler.
* Updates the button label text.
* Hides the button if the label is null or undefined.
*
* @param{HTMLElement} button
* @param{?string} label
* @param{Function} clickHandler
* @private
*/
MessageWindowImpl.prototype.initButton_ =
function(button, label, clickHandler) {
MessageWindowImpl.prototype.updateButton_ = function(button, label) {
if (label) {
button.innerText = label;
button.addEventListener('click', clickHandler, false);
}
button.hidden = !Boolean(label);
};
......@@ -69,86 +66,89 @@ MessageWindowImpl.prototype.initButton_ =
* @private
*/
MessageWindowImpl.prototype.onMessage_ = function(event) {
switch (event.data['command']) {
case 'show':
// Validate the message.
var messageId = /** @type {number} */ (event.data['id']);
var title = /** @type {string} */ (event.data['title']);
var message = /** @type {string} */ (event.data['message']);
var infobox = /** @type {string} */ (event.data['infobox']);
var buttonLabel = /** @type {string} */ (event.data['buttonLabel']);
/** @type {string} */
var cancelButtonLabel = (event.data['cancelButtonLabel']);
var showSpinner = /** @type {boolean} */ (event.data['showSpinner']);
if (typeof(messageId) != 'number' ||
typeof(title) != 'string' ||
typeof(message) != 'string' ||
typeof(infobox) != 'string' ||
typeof(buttonLabel) != 'string' ||
typeof(showSpinner) != 'boolean') {
console.log('Bad show message:', event.data);
break;
}
// Set the dialog text.
var button = document.getElementById('button-primary');
var cancelButton = document.getElementById('button-secondary');
var messageDiv = document.getElementById('message');
var infoboxDiv = document.getElementById('infobox');
document.getElementById('title').innerText = title;
document.querySelector('title').innerText = title;
messageDiv.innerHTML = message;
if (showSpinner) {
messageDiv.classList.add('waiting');
messageDiv.classList.add('prominent');
}
if (infobox != '') {
infoboxDiv.innerText = infobox;
} else {
infoboxDiv.hidden = true;
}
this.initButton_(
button,
buttonLabel,
this.sendReply_.bind(this, event.source, messageId, 1));
this.initButton_(
cancelButton,
cancelButtonLabel,
this.sendReply_.bind(this, event.source, messageId, 0));
var buttonToFocus = (cancelButtonLabel) ? cancelButton : button;
buttonToFocus.focus();
// Add a close handler in case the window is closed without clicking one
// of the buttons. This will send a 0 as the result.
// Note that when a button is pressed, this will result in sendReply_
// being called multiple times (once for the button, once for close).
chrome.app.window.current().onClosed.addListener(
this.sendReply_.bind(this, event.source, messageId, 0));
base.resizeWindowToContent(true);
chrome.app.window.current().show();
break;
case 'update_message':
var message = /** @type {string} */ (event.data['message']);
if (typeof(message) != 'string') {
console.log('Bad update_message message:', event.data);
break;
}
var messageDiv = document.getElementById('message');
messageDiv.innerText = message;
base.resizeWindowToContent(true);
break;
default:
console.error('Unexpected message:', event.data);
var command = /** @type {string} */ (event.data['command']);
if (command !== 'show' && command !== 'update') {
console.error('Unexpected message: ' + command);
return;
}
// Validate the message.
var messageId = /** @type {number} */ (event.data['id']);
var title = /** @type {string} */ (event.data['title']);
var message = /** @type {string} */ (event.data['message']);
var infobox = /** @type {string} */ (event.data['infobox']);
var buttonLabel = /** @type {string} */ (event.data['buttonLabel']);
var cancelButtonLabel = /** @type {string} */
(event.data['cancelButtonLabel']);
var showSpinner = /** @type {boolean} */ (event.data['showSpinner']);
// Many of these fields are optional for either the 'show' or 'update'
// message. These vars are used to mark the optional fields to allow
// them to be undefined.
var optionalFieldShow = command === 'show';
var optionalFieldUpdate = command === 'update';
if (isNumber(messageId) ||
isString(title, optionalFieldUpdate) ||
isString(message, optionalFieldUpdate) ||
isString(infobox, optionalFieldUpdate) ||
isString(buttonLabel, optionalFieldUpdate) ||
isString(cancelButtonLabel, optionalFieldShow || optionalFieldUpdate) ||
isBoolean(showSpinner, optionalFieldUpdate) {
console.log('Bad ' + command + ' message: ' + event.data);
return;
}
var button = document.getElementById('button-primary');
var cancelButton = document.getElementById('button-secondary');
var messageDiv = document.getElementById('message');
var infoboxDiv = document.getElementById('infobox');
if (isString(title)) {
document.getElementById('title').innerText = title;
document.querySelector('title').innerText = title;
}
if (isString(message) {
messageDiv.innerText = message;
}
if (isString(infobox)) {
if (infobox != '') {
infoboxDiv.innerText = infobox;
} else {
infoboxDiv.hidden = true;
}
}
if (isBoolean(showSpinner)) {
if (showSpinner) {
messageDiv.classList.add('waiting');
messageDiv.classList.add('prominent');
} else {
messageDiv.classList.remove('waiting');
messageDiv.classList.remove('prominent');
}
}
this.updateButton_(button, buttonLabel);
this.updateButton_(cancelButton, cancelButtonLabel);
base.resizeWindowToContent(true);
if (command === 'show') {
// Set up click-handlers for the buttons.
button.addEventListener(
'click', this.sendReply_.bind(this, event.source, messageId, 1), false);
cancelButton.addEventListener(
'click', this.sendReply_.bind(this, event.source, messageId, 0), false);
var buttonToFocus = (cancelButtonLabel) ? cancelButton : button;
buttonToFocus.focus();
// Add a close handler in case the window is closed without clicking one
// of the buttons. This will send a 0 as the result.
// Note that when a button is pressed, this will result in sendReply_
// being called multiple times (once for the button, once for close).
chrome.app.window.current().onClosed.addListener(
this.sendReply_.bind(this, event.source, messageId, 0));
chrome.app.window.current().show();
}
};
......
......@@ -41,6 +41,9 @@ remoting.MessageWindowOptions = function() {
/** @type {number} */
this.minimumWidth = 0;
/** @type {boolean} */
this.showSpinner = false;
};
/**
......@@ -151,12 +154,36 @@ remoting.MessageWindow.prototype.updateMessage = function(message) {
}
var message_struct = {
command: 'update_message',
command: 'update',
message: message
};
this.window_.postMessage(message_struct, '*');
};
/**
* Update the message being shown in the window to the given error message.
* In addition to updating the message, any spinner is disabled and the
* button text is changed to 'OK'.
* This should only be called after the window has been shown.
*
* @param {string} message The message.
*/
remoting.MessageWindow.prototype.updateErrorMessage = function(message) {
if (!this.window_) {
this.pendingWindowOperations_.push(this.updateMessage.bind(this, message));
return;
}
var message_struct = {
command: 'update',
message: message,
buttonLabel: chrome.i18n.getMessage(/*i18n-content*/'OK'),
cancelButtonLabel: '',
showSpinner: false
};
this.window_.postMessage(message_struct, '*');
};
/**
* Close the message box and unregister it with the window manager.
*/
......
......@@ -19,17 +19,25 @@ var isArray = function(value) {
/**
* @param {*} value
* @param {boolean=} opt_allowUndefined True to accept undefined.
* @return {boolean}
*/
var isBoolean = function(value) {
var isBoolean = function(value, opt_allowUndefined) {
if (opt_allowUndefined && value === 'undefined') {
return true;
}
return typeof value == 'boolean';
};
/**
* @param {*} value
* @param {boolean=} opt_allowUndefined True to accept undefined.
* @return {boolean}
*/
var isNumber = function(value) {
var isNumber = function(value, opt_allowUndefined) {
if (opt_allowUndefined && value === 'undefined') {
return true;
}
return typeof value == 'number';
};
......@@ -43,9 +51,13 @@ var isObject = function(value) {
/**
* @param {*} value
* @param {boolean=} opt_allowUndefined True to accept undefined.
* @return {boolean}
*/
var isString = function(value) {
var isString = function(value, opt_allowUndefined) {
if (opt_allowUndefined && value === 'undefined') {
return true;
}
return typeof value == 'string';
};
......@@ -246,4 +258,4 @@ base.getJsonObjectFromString = function(jsonString) {
return base.assertObject(base.jsonParseSafe(jsonString));
};
})();
\ No newline at end of file
})();
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment