// 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. /** * @fileoverview * AppLauncher is an interface that allows the client code to launch and close * the app without knowing the implementation difference between a v1 app and * a v2 app. * * To launch an app: * var appLauncher = new remoting.V1AppLauncher(); * var appId = ""; * appLauncher.launch({arg1:'someValue'}).then(function(id){ * appId = id; * }); * * To close an app: * appLauncher.close(appId); */ /** @suppress {duplicate} */ var remoting = remoting || {}; (function() { 'use strict'; /** @interface */ remoting.AppLauncher = function() {}; /** * @param {Object=} opt_launchArgs * @return {Promise} The promise will resolve when the app is launched. It will * provide the caller with the appId (which is either the id of the hosting tab * or window). The caller can use the appId to close the app. */ remoting.AppLauncher.prototype.launch = function(opt_launchArgs) { }; /** * @param {string} id The id of the app to close. * @return {Promise} The promise will resolve when the app is closed. */ remoting.AppLauncher.prototype.close = function(id) {}; /** * @constructor * @implements {remoting.AppLauncher} */ remoting.V1AppLauncher = function() {}; remoting.V1AppLauncher.prototype.launch = function(opt_launchArgs) { var url = base.urlJoin('main.html', opt_launchArgs); return new Promise(function(resolve, reject) { chrome.tabs.create({ url: url, selected: true }, function(/**Tab*/ tab){ if (!tab) { reject(new Error(chrome.runtime.lastError.message)); } else { resolve(String(tab.id)); } }); }); }; remoting.V1AppLauncher.prototype.close = function(id) { return new Promise(function(resolve, reject) { chrome.tabs.get(parseInt(id, 10), function(/** Tab */ tab) { if (!tab) { reject(new Error(chrome.runtime.lastError.message)); } else { chrome.tabs.remove(tab.id, resolve); } }); }); }; /** * @constructor * @implements {remoting.AppLauncher} */ remoting.V2AppLauncher = function() {}; var APP_MAIN_URL = 'main.html'; /** * @param {string} id * @return {Promise} A promise that resolves with the id of the created * window, which is guaranteed to be the same as the current window id. */ remoting.V2AppLauncher.prototype.restart = function(id) { return this.close(id).then(function() { return createWindow_({'id' : id, 'frame': 'none'}); }).then(function (/** string */ newId) { console.assert(newId === id, 'restart() should preserve the window id.'); return newId; }); }; /** * @param {!chrome.app.window.CreateWindowOptions=} opt_options * @param {Object=} opt_launchArgs * @return {Promise} A promise that resolves with the id of the created * window. */ function createWindow_(opt_options, opt_launchArgs) { var url = base.urlJoin(APP_MAIN_URL, opt_launchArgs); var deferred = new base.Deferred(); chrome.app.window.create(url, opt_options, function(/** chrome.app.window.AppWindow= */ appWindow) { if (!appWindow) { deferred.reject(new Error(chrome.runtime.lastError.message)); } else { deferred.resolve(appWindow.id); } }); return deferred.promise(); } remoting.V2AppLauncher.prototype.launch = function(opt_launchArgs) { var deferred = new base.Deferred(); var START_FULLSCREEN = 'start-fullscreen'; /** @param {Object} values */ var onValues = function(values) { /** @type {string} */ var state = values[START_FULLSCREEN] ? 'fullscreen' : 'normal'; createWindow_({ 'width': 800, 'height': 634, 'frame': 'none', 'id': String(getNextWindowId()), 'state': state }, opt_launchArgs).then( deferred.resolve.bind(deferred), deferred.reject.bind(deferred) ); }; chrome.storage.local.get(START_FULLSCREEN, onValues); return deferred.promise(); }; remoting.V2AppLauncher.prototype.close = function(id) { return new Promise( /** * @param {function(*=):void} resolve * @param {function(*=):void} reject */ function(resolve, reject) { var appWindow = chrome.app.window.get(id); if (!appWindow) { return Promise.reject(new Error(chrome.runtime.lastError.message)); } appWindow.onClosed.addListener(resolve); appWindow.close(); }); }; /** * @return {number} The first available window id. Since Chrome remembers * properties such as size and position for app windows, it is better * to reuse window ids rather than allocating new ones. */ function getNextWindowId() { var appWindows = chrome.app.window.getAll(); var result = 1; for (; result <= appWindows.length; ++result) { if (!chrome.app.window.get(String(result))) { break; } } return result; } })();