blob: 7441cc6716c9f378f1d9208344bc9db3ebfeea8c [file] [log] [blame]
// 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<string>} 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<string>} 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;
}
})();