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