Index: remoting/webapp/background/message_window.js |
diff --git a/remoting/webapp/background/message_window.js b/remoting/webapp/background/message_window.js |
new file mode 100644 |
index 0000000000000000000000000000000000000000..fee4c9b09b3f974f50a6a7637a7bc0b79460f1da |
--- /dev/null |
+++ b/remoting/webapp/background/message_window.js |
@@ -0,0 +1,163 @@ |
+// Copyright 2014 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'; |
+ |
+/** |
+ * @constructor |
+ */ |
+function MessageWindowImpl() { |
+ /** |
+ * Used to prevent multiple responses due to the closeWindow handler. |
+ * |
+ * @type {boolean} |
+ * @private |
+ */ |
+ this.sentReply_ = false; |
+ |
+ window.addEventListener('message', this.onMessage_.bind(this), false); |
+}; |
+ |
+/** |
+ * @param {Window} parentWindow The id of the window that showed the message. |
+ * @param {string} messageId The identifier of the message, as supplied by the |
+ * parent. |
+ * @param {number} result 0 if window was closed without pressing a button; |
+ * otherwise the index of the button pressed (e.g., 1 = primary). |
+ * @private |
+ */ |
+MessageWindowImpl.prototype.sendReply_ = function( |
+ parentWindow, messageId, result) { |
+ // Only forward the first reply that we receive. |
+ if (!this.sentReply_) { |
+ var message = { |
+ command: 'messageWindowResult', |
+ id: messageId, |
+ result: result |
+ }; |
+ parentWindow.postMessage(message, '*'); |
+ this.sentReply_ = true; |
+ } else { |
+ // Make sure that the reply we're ignoring is from the window close. |
+ base.debug.assert(result == 0); |
+ } |
+}; |
+ |
+/** |
+ * Size the window to its content vertically. |
+ * @private |
+ */ |
+MessageWindowImpl.prototype.updateSize_ = function() { |
+ var borderY = window.outerHeight - window.innerHeight; |
+ window.resizeTo(window.outerWidth, document.body.clientHeight + borderY); |
+}; |
+ |
+/** |
+ * Initializes the button with the label and the click handler. |
+ * 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) { |
+ if (label) { |
+ button.innerText = label; |
+ button.addEventListener('click', clickHandler, false); |
+ } |
+ button.hidden = !Boolean(label); |
+}; |
+ |
+/** |
+ * Event-handler callback, invoked when the parent window supplies the |
+ * message content. |
+ * |
+ * @param{Event} event |
+ * @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.innerText = 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)); |
+ |
+ this.updateSize_(); |
+ 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; |
+ |
+ this.updateSize_(); |
+ break; |
+ |
+ default: |
+ console.error('Unexpected message:', event.data); |
+ } |
+}; |
+ |
+var messageWindow = new MessageWindowImpl(); |