Home | History | Annotate | Download | only in background
      1 // Copyright 2014 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 'use strict';
      6 
      7 /**
      8  * @constructor
      9  */
     10 function MessageWindowImpl() {
     11   /**
     12    * Used to prevent multiple responses due to the closeWindow handler.
     13    *
     14    * @type {boolean}
     15    * @private
     16    */
     17   this.sentReply_ = false;
     18 
     19   window.addEventListener('message', this.onMessage_.bind(this), false);
     20 };
     21 
     22 /**
     23  * @param {Window} parentWindow The id of the window that showed the message.
     24  * @param {string} messageId The identifier of the message, as supplied by the
     25  *     parent.
     26  * @param {number} result 0 if window was closed without pressing a button;
     27  *     otherwise the index of the button pressed (e.g., 1 = primary).
     28  * @private
     29  */
     30 MessageWindowImpl.prototype.sendReply_ = function(
     31     parentWindow, messageId, result) {
     32   // Only forward the first reply that we receive.
     33   if (!this.sentReply_) {
     34     var message = {
     35       command: 'messageWindowResult',
     36       id: messageId,
     37       result: result
     38     };
     39     parentWindow.postMessage(message, '*');
     40     this.sentReply_ = true;
     41   } else {
     42     // Make sure that the reply we're ignoring is from the window close.
     43     base.debug.assert(result == 0);
     44   }
     45 };
     46 
     47 /**
     48  * Size the window to its content vertically.
     49  * @private
     50  */
     51 MessageWindowImpl.prototype.updateSize_ = function() {
     52   var borderY = window.outerHeight - window.innerHeight;
     53   window.resizeTo(window.outerWidth, document.body.clientHeight + borderY);
     54 };
     55 
     56 /**
     57  * Initializes the button with the label and the click handler.
     58  * Hides the button if the label is null or undefined.
     59  *
     60  * @param{HTMLElement} button
     61  * @param{?string} label
     62  * @param{Function} clickHandler
     63  * @private
     64  */
     65 MessageWindowImpl.prototype.initButton_ =
     66     function(button, label, clickHandler) {
     67   if (label) {
     68     button.innerText = label;
     69     button.addEventListener('click', clickHandler, false);
     70   }
     71   button.hidden = !Boolean(label);
     72 };
     73 
     74 /**
     75  * Event-handler callback, invoked when the parent window supplies the
     76  * message content.
     77  *
     78  * @param{Event} event
     79  * @private
     80  */
     81 MessageWindowImpl.prototype.onMessage_ = function(event) {
     82   switch (event.data['command']) {
     83     case 'show':
     84       // Validate the message.
     85       var messageId = /** @type {number} */ (event.data['id']);
     86       var title = /** @type {string} */ (event.data['title']);
     87       var message = /** @type {string} */ (event.data['message']);
     88       var infobox = /** @type {string} */ (event.data['infobox']);
     89       var buttonLabel = /** @type {string} */ (event.data['buttonLabel']);
     90       /** @type {string} */
     91       var cancelButtonLabel = (event.data['cancelButtonLabel']);
     92       var showSpinner = /** @type {boolean} */ (event.data['showSpinner']);
     93       if (typeof(messageId) != 'number' ||
     94           typeof(title) != 'string' ||
     95           typeof(message) != 'string' ||
     96           typeof(infobox) != 'string' ||
     97           typeof(buttonLabel) != 'string' ||
     98           typeof(showSpinner) != 'boolean') {
     99         console.log('Bad show message:', event.data);
    100         break;
    101       }
    102 
    103       // Set the dialog text.
    104       var button = document.getElementById('button-primary');
    105       var cancelButton = document.getElementById('button-secondary');
    106       var messageDiv = document.getElementById('message');
    107       var infoboxDiv = document.getElementById('infobox');
    108 
    109       document.getElementById('title').innerText = title;
    110       document.querySelector('title').innerText = title;
    111       messageDiv.innerHTML = message;
    112 
    113       if (showSpinner) {
    114         messageDiv.classList.add('waiting');
    115         messageDiv.classList.add('prominent');
    116       }
    117       if (infobox != '') {
    118         infoboxDiv.innerText = infobox;
    119       } else {
    120         infoboxDiv.hidden = true;
    121       }
    122 
    123       this.initButton_(
    124           button,
    125           buttonLabel,
    126           this.sendReply_.bind(this, event.source, messageId, 1));
    127 
    128       this.initButton_(
    129           cancelButton,
    130           cancelButtonLabel,
    131           this.sendReply_.bind(this, event.source, messageId, 0));
    132 
    133       var buttonToFocus = (cancelButtonLabel) ? cancelButton : button;
    134       buttonToFocus.focus();
    135 
    136       // Add a close handler in case the window is closed without clicking one
    137       // of the buttons. This will send a 0 as the result.
    138       // Note that when a button is pressed, this will result in sendReply_
    139       // being called multiple times (once for the button, once for close).
    140       chrome.app.window.current().onClosed.addListener(
    141           this.sendReply_.bind(this, event.source, messageId, 0));
    142 
    143       this.updateSize_();
    144       chrome.app.window.current().show();
    145       break;
    146 
    147     case 'update_message':
    148       var message = /** @type {string} */ (event.data['message']);
    149       if (typeof(message) != 'string') {
    150         console.log('Bad update_message message:', event.data);
    151         break;
    152       }
    153 
    154       var messageDiv = document.getElementById('message');
    155       messageDiv.innerText = message;
    156 
    157       this.updateSize_();
    158       break;
    159 
    160     default:
    161       console.error('Unexpected message:', event.data);
    162   }
    163 };
    164 
    165 var messageWindow = new MessageWindowImpl();
    166