11320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// Copyright 2014 The Chromium Authors. All rights reserved.
21320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// Use of this source code is governed by a BSD-style license that can be
31320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// found in the LICENSE file.
41320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
51320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci'use strict';
61320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
71320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci/**
81320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci * @constructor
91320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci */
101320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccifunction MessageWindowImpl() {
111320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  /**
121320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci   * Used to prevent multiple responses due to the closeWindow handler.
131320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci   *
141320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci   * @type {boolean}
151320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci   * @private
161320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci   */
171320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  this.sentReply_ = false;
181320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
191320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  window.addEventListener('message', this.onMessage_.bind(this), false);
201320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci};
211320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
221320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci/**
231320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci * @param {Window} parentWindow The id of the window that showed the message.
241320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci * @param {string} messageId The identifier of the message, as supplied by the
251320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci *     parent.
261320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci * @param {number} result 0 if window was closed without pressing a button;
271320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci *     otherwise the index of the button pressed (e.g., 1 = primary).
281320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci * @private
291320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci */
301320f92c476a1ad9d19dba2a48c72b75566198e9Primiano TucciMessageWindowImpl.prototype.sendReply_ = function(
311320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    parentWindow, messageId, result) {
321320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // Only forward the first reply that we receive.
331320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if (!this.sentReply_) {
341320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    var message = {
351320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      command: 'messageWindowResult',
361320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      id: messageId,
371320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      result: result
381320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    };
391320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    parentWindow.postMessage(message, '*');
401320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    this.sentReply_ = true;
411320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  } else {
421320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    // Make sure that the reply we're ignoring is from the window close.
431320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    base.debug.assert(result == 0);
441320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  }
451320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci};
461320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
471320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci/**
481320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci * Size the window to its content vertically.
491320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci * @private
501320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci */
511320f92c476a1ad9d19dba2a48c72b75566198e9Primiano TucciMessageWindowImpl.prototype.updateSize_ = function() {
521320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  var borderY = window.outerHeight - window.innerHeight;
531320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  window.resizeTo(window.outerWidth, document.body.clientHeight + borderY);
541320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci};
551320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
561320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci/**
571320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci * Initializes the button with the label and the click handler.
581320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci * Hides the button if the label is null or undefined.
591320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci *
601320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci * @param{HTMLElement} button
611320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci * @param{?string} label
621320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci * @param{Function} clickHandler
631320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci * @private
641320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci */
651320f92c476a1ad9d19dba2a48c72b75566198e9Primiano TucciMessageWindowImpl.prototype.initButton_ =
661320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    function(button, label, clickHandler) {
671320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if (label) {
681320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    button.innerText = label;
691320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    button.addEventListener('click', clickHandler, false);
701320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  }
711320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  button.hidden = !Boolean(label);
721320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci};
731320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
741320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci/**
751320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci * Event-handler callback, invoked when the parent window supplies the
761320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci * message content.
771320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci *
781320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci * @param{Event} event
791320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci * @private
801320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci */
811320f92c476a1ad9d19dba2a48c72b75566198e9Primiano TucciMessageWindowImpl.prototype.onMessage_ = function(event) {
821320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  switch (event.data['command']) {
831320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    case 'show':
841320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      // Validate the message.
851320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      var messageId = /** @type {number} */ (event.data['id']);
861320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      var title = /** @type {string} */ (event.data['title']);
871320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      var message = /** @type {string} */ (event.data['message']);
881320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      var infobox = /** @type {string} */ (event.data['infobox']);
891320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      var buttonLabel = /** @type {string} */ (event.data['buttonLabel']);
901320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      /** @type {string} */
911320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      var cancelButtonLabel = (event.data['cancelButtonLabel']);
921320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      var showSpinner = /** @type {boolean} */ (event.data['showSpinner']);
931320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      if (typeof(messageId) != 'number' ||
941320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci          typeof(title) != 'string' ||
951320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci          typeof(message) != 'string' ||
961320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci          typeof(infobox) != 'string' ||
971320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci          typeof(buttonLabel) != 'string' ||
981320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci          typeof(showSpinner) != 'boolean') {
991320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        console.log('Bad show message:', event.data);
1001320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        break;
1011320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      }
1021320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
1031320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      // Set the dialog text.
1041320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      var button = document.getElementById('button-primary');
1051320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      var cancelButton = document.getElementById('button-secondary');
1061320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      var messageDiv = document.getElementById('message');
1071320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      var infoboxDiv = document.getElementById('infobox');
1081320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
1091320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      document.getElementById('title').innerText = title;
1101320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      document.querySelector('title').innerText = title;
1111320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      messageDiv.innerHTML = message;
1121320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
1131320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      if (showSpinner) {
1141320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        messageDiv.classList.add('waiting');
1151320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        messageDiv.classList.add('prominent');
1161320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      }
1171320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      if (infobox != '') {
1181320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        infoboxDiv.innerText = infobox;
1191320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      } else {
1201320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        infoboxDiv.hidden = true;
1211320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      }
1221320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
1231320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      this.initButton_(
1241320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci          button,
1251320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci          buttonLabel,
1261320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci          this.sendReply_.bind(this, event.source, messageId, 1));
1271320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
1281320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      this.initButton_(
1291320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci          cancelButton,
1301320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci          cancelButtonLabel,
1311320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci          this.sendReply_.bind(this, event.source, messageId, 0));
1321320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
1331320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      var buttonToFocus = (cancelButtonLabel) ? cancelButton : button;
1341320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      buttonToFocus.focus();
1351320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
1361320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      // Add a close handler in case the window is closed without clicking one
1371320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      // of the buttons. This will send a 0 as the result.
1381320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      // Note that when a button is pressed, this will result in sendReply_
1391320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      // being called multiple times (once for the button, once for close).
1401320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      chrome.app.window.current().onClosed.addListener(
1411320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci          this.sendReply_.bind(this, event.source, messageId, 0));
1421320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
1431320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      this.updateSize_();
1441320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      chrome.app.window.current().show();
1451320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      break;
1461320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
1471320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    case 'update_message':
1481320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      var message = /** @type {string} */ (event.data['message']);
1491320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      if (typeof(message) != 'string') {
1501320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        console.log('Bad update_message message:', event.data);
1511320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        break;
1521320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      }
1531320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
1541320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      var messageDiv = document.getElementById('message');
1551320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      messageDiv.innerText = message;
1561320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
1571320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      this.updateSize_();
1581320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      break;
1591320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
1601320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    default:
1611320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      console.error('Unexpected message:', event.data);
1621320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  }
1631320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci};
1641320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
1651320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivar messageWindow = new MessageWindowImpl();
166