michael@0: /* This Source Code Form is subject to the terms of the Mozilla Public michael@0: * License, v. 2.0. If a copy of the MPL was not distributed with this file, michael@0: * You can obtain one at http://mozilla.org/MPL/2.0/. */ michael@0: michael@0: /* This module is imported at the startup of an application. It takes care of michael@0: * permissions installation, application url loading, security settings. Put michael@0: * stuff here that you want to happen once on startup before the webapp is michael@0: * loaded. */ michael@0: michael@0: this.EXPORTED_SYMBOLS = ["startup"]; michael@0: michael@0: const Ci = Components.interfaces; michael@0: const Cu = Components.utils; michael@0: michael@0: Cu.import("resource://gre/modules/Services.jsm"); michael@0: Cu.import("resource://gre/modules/AppsUtils.jsm"); michael@0: Cu.import("resource://gre/modules/PermissionsInstaller.jsm"); michael@0: Cu.import('resource://gre/modules/Payment.jsm'); michael@0: Cu.import('resource://gre/modules/AlarmService.jsm'); michael@0: Cu.import("resource://gre/modules/Task.jsm"); michael@0: Cu.import("resource://gre/modules/Promise.jsm"); michael@0: Cu.import("resource://gre/modules/osfile.jsm"); michael@0: michael@0: Cu.import("resource://webapprt/modules/WebappRT.jsm"); michael@0: Cu.import("resource://webapprt/modules/WebRTCHandler.jsm"); michael@0: michael@0: const PROFILE_DIR = OS.Constants.Path.profileDir; michael@0: michael@0: function isFirstRunOrUpdate() { michael@0: let savedBuildID = null; michael@0: try { michael@0: savedBuildID = Services.prefs.getCharPref("webapprt.buildID"); michael@0: } catch (e) {} michael@0: michael@0: let ourBuildID = Services.appinfo.platformBuildID; michael@0: michael@0: if (ourBuildID != savedBuildID) { michael@0: Services.prefs.setCharPref("webapprt.buildID", ourBuildID); michael@0: return true; michael@0: } michael@0: michael@0: return false; michael@0: } michael@0: michael@0: function writeFile(aPath, aData) { michael@0: return Task.spawn(function() { michael@0: let data = new TextEncoder().encode(aData); michael@0: yield OS.File.writeAtomic(aPath, data, { tmpPath: aPath + ".tmp" }); michael@0: }); michael@0: } michael@0: michael@0: function createBrandingFiles() { michael@0: return Task.spawn(function() { michael@0: let manifest = WebappRT.localeManifest; michael@0: let name = WebappRT.localeManifest.name; michael@0: let developer = " "; michael@0: if (WebappRT.localeManifest.developer) { michael@0: developer = WebappRT.localeManifest.developer.name; michael@0: } michael@0: michael@0: let brandDTDContent = '\n\ michael@0: \n\ michael@0: \n\ michael@0: '; michael@0: michael@0: yield writeFile(OS.Path.join(PROFILE_DIR, "brand.dtd"), brandDTDContent); michael@0: michael@0: let brandPropertiesContent = 'brandShortName=' + name + '\n\ michael@0: brandFullName=' + name + '\n\ michael@0: vendorShortName=' + developer; michael@0: michael@0: yield writeFile(OS.Path.join(PROFILE_DIR, "brand.properties"), michael@0: brandPropertiesContent); michael@0: }); michael@0: } michael@0: michael@0: // Observes all the events needed to actually launch an application. michael@0: // It waits for XUL window and webapps registry loading. michael@0: this.startup = function(window) { michael@0: return Task.spawn(function () { michael@0: // Observe XUL window loading. michael@0: // For tests, it could be already loaded. michael@0: let deferredWindowLoad = Promise.defer(); michael@0: if (window.document && window.document.getElementById("content")) { michael@0: deferredWindowLoad.resolve(); michael@0: } else { michael@0: window.addEventListener("DOMContentLoaded", function onLoad() { michael@0: window.removeEventListener("DOMContentLoaded", onLoad, false); michael@0: deferredWindowLoad.resolve(); michael@0: }); michael@0: } michael@0: michael@0: let appUpdated = false; michael@0: let updatePending = yield WebappRT.isUpdatePending(); michael@0: if (updatePending) { michael@0: appUpdated = yield WebappRT.applyUpdate(); michael@0: } michael@0: michael@0: yield WebappRT.loadConfig(); michael@0: michael@0: let appData = WebappRT.config.app; michael@0: michael@0: // Initialize DOMApplicationRegistry by importing Webapps.jsm. michael@0: Cu.import("resource://gre/modules/Webapps.jsm"); michael@0: // Initialize window-independent handling of webapps- notifications. michael@0: Cu.import("resource://webapprt/modules/WebappManager.jsm"); michael@0: michael@0: // Wait for webapps registry loading. michael@0: yield DOMApplicationRegistry.registryStarted; michael@0: // Add the currently running app to the registry. michael@0: yield DOMApplicationRegistry.addInstalledApp(appData, appData.manifest, michael@0: appData.updateManifest); michael@0: michael@0: let manifestURL = appData.manifestURL; michael@0: if (manifestURL) { michael@0: // On firstrun, set permissions to their default values. michael@0: // When the webapp runtime is updated, update the permissions. michael@0: if (isFirstRunOrUpdate(Services.prefs) || appUpdated) { michael@0: PermissionsInstaller.installPermissions(appData, true); michael@0: yield createBrandingFiles(); michael@0: } michael@0: } michael@0: michael@0: // Branding substitution michael@0: let aliasFile = Components.classes["@mozilla.org/file/local;1"] michael@0: .createInstance(Ci.nsIFile); michael@0: aliasFile.initWithPath(PROFILE_DIR); michael@0: michael@0: let aliasURI = Services.io.newFileURI(aliasFile); michael@0: michael@0: Services.io.getProtocolHandler("resource") michael@0: .QueryInterface(Ci.nsIResProtocolHandler) michael@0: .setSubstitution("webappbranding", aliasURI); michael@0: michael@0: // Wait for XUL window loading michael@0: yield deferredWindowLoad.promise; michael@0: michael@0: // Get the element in the webapp.xul window. michael@0: let appBrowser = window.document.getElementById("content"); michael@0: michael@0: // Set the principal to the correct appID and launch the application. michael@0: appBrowser.docShell.setIsApp(WebappRT.appID); michael@0: appBrowser.setAttribute("src", WebappRT.launchURI); michael@0: michael@0: if (appData.manifest.fullscreen) { michael@0: appBrowser.addEventListener("load", function onLoad() { michael@0: appBrowser.removeEventListener("load", onLoad, true); michael@0: appBrowser.contentDocument. michael@0: documentElement.mozRequestFullScreen(); michael@0: }, true); michael@0: } michael@0: michael@0: WebappRT.startUpdateService(); michael@0: }); michael@0: }