1 /* This Source Code Form is subject to the terms of the Mozilla Public
2 * License, v. 2.0. If a copy of the MPL was not distributed with this file,
3 * You can obtain one at http://mozilla.org/MPL/2.0/. */
5 /* This module is imported at the startup of an application. It takes care of
6 * permissions installation, application url loading, security settings. Put
7 * stuff here that you want to happen once on startup before the webapp is
10 this.EXPORTED_SYMBOLS = ["startup"];
12 const Ci = Components.interfaces;
13 const Cu = Components.utils;
15 /* We load here modules that are needed to perform the application startup.
16 * We lazily load modules that aren't needed on every startup.
17 * We load modules that aren't used here but that need to perform some
18 * initialization steps later in the startup function. */
20 Cu.import("resource://gre/modules/XPCOMUtils.jsm");
21 Cu.import("resource://gre/modules/Services.jsm");
22 Cu.import("resource://gre/modules/Task.jsm");
23 Cu.import("resource://gre/modules/Promise.jsm");
24 Cu.import("resource://gre/modules/osfile.jsm");
26 Cu.import("resource://webapprt/modules/WebappRT.jsm");
28 // Lazily load these modules because we don't need them at every
29 // startup, but only during first run or runtime update.
31 XPCOMUtils.defineLazyModuleGetter(this, "PermissionsInstaller",
32 "resource://gre/modules/PermissionsInstaller.jsm");
34 const PROFILE_DIR = OS.Constants.Path.profileDir;
36 function isFirstRunOrUpdate() {
37 let savedBuildID = null;
39 savedBuildID = Services.prefs.getCharPref("webapprt.buildID");
42 let ourBuildID = Services.appinfo.platformBuildID;
44 if (ourBuildID != savedBuildID) {
45 Services.prefs.setCharPref("webapprt.buildID", ourBuildID);
52 function writeFile(aPath, aData) {
53 return Task.spawn(function() {
54 let data = new TextEncoder().encode(aData);
55 yield OS.File.writeAtomic(aPath, data, { tmpPath: aPath + ".tmp" });
59 function createBrandingFiles() {
60 return Task.spawn(function() {
61 let manifest = WebappRT.localeManifest;
62 let name = WebappRT.localeManifest.name;
64 if (WebappRT.localeManifest.developer) {
65 developer = WebappRT.localeManifest.developer.name;
68 let brandDTDContent = '<!ENTITY brandShortName "' + name + '">\n\
69 <!ENTITY brandFullName "' + name + '">\n\
70 <!ENTITY vendorShortName "' + developer + '">\n\
71 <!ENTITY trademarkInfo.part1 " ">';
73 yield writeFile(OS.Path.join(PROFILE_DIR, "brand.dtd"), brandDTDContent);
75 let brandPropertiesContent = 'brandShortName=' + name + '\n\
76 brandFullName=' + name + '\n\
77 vendorShortName=' + developer;
79 yield writeFile(OS.Path.join(PROFILE_DIR, "brand.properties"),
80 brandPropertiesContent);
84 // Observes all the events needed to actually launch an application.
85 // It waits for XUL window and webapps registry loading.
86 this.startup = function(window) {
87 return Task.spawn(function () {
88 // Observe XUL window loading.
89 // For tests, it could be already loaded.
90 let deferredWindowLoad = Promise.defer();
91 if (window.document && window.document.getElementById("content")) {
92 deferredWindowLoad.resolve();
94 window.addEventListener("DOMContentLoaded", function onLoad() {
95 window.removeEventListener("DOMContentLoaded", onLoad, false);
96 deferredWindowLoad.resolve();
100 let appUpdated = false;
101 let updatePending = yield WebappRT.isUpdatePending();
103 appUpdated = yield WebappRT.applyUpdate();
106 yield WebappRT.configPromise;
108 let appData = WebappRT.config.app;
110 // Initialize DOMApplicationRegistry by importing Webapps.jsm.
111 Cu.import("resource://gre/modules/Webapps.jsm");
112 // Initialize window-independent handling of webapps- notifications.
113 Cu.import("resource://webapprt/modules/WebappManager.jsm");
115 // Wait for webapps registry loading.
116 yield DOMApplicationRegistry.registryStarted;
117 // Add the currently running app to the registry.
118 yield DOMApplicationRegistry.addInstalledApp(appData, appData.manifest,
119 appData.updateManifest);
121 let manifestURL = appData.manifestURL;
123 // On firstrun, set permissions to their default values.
124 // When the webapp runtime is updated, update the permissions.
125 if (isFirstRunOrUpdate(Services.prefs) || appUpdated) {
126 PermissionsInstaller.installPermissions(appData, true);
127 yield createBrandingFiles();
131 // Branding substitution
132 let aliasFile = Components.classes["@mozilla.org/file/local;1"]
133 .createInstance(Ci.nsIFile);
134 aliasFile.initWithPath(PROFILE_DIR);
136 let aliasURI = Services.io.newFileURI(aliasFile);
138 Services.io.getProtocolHandler("resource")
139 .QueryInterface(Ci.nsIResProtocolHandler)
140 .setSubstitution("webappbranding", aliasURI);
142 // Wait for XUL window loading
143 yield deferredWindowLoad.promise;
145 // Override Toolkit's nsITransfer implementation with the one from the
146 // JavaScript API for downloads. This will eventually be removed when
147 // nsIDownloadManager will not be available anymore (bug 851471).
148 Components.manager.QueryInterface(Ci.nsIComponentRegistrar)
149 .registerFactory(Components.ID("{1b4c85df-cbdd-4bb6-b04e-613caece083c}"),
150 "", "@mozilla.org/transfer;1", null);
152 // Load these modules here because they aren't needed right at startup,
153 // but they need to be loaded to perform some initialization steps.
154 Cu.import("resource://gre/modules/Payment.jsm");
155 Cu.import("resource://gre/modules/AlarmService.jsm");
156 Cu.import("resource://webapprt/modules/WebRTCHandler.jsm");
157 Cu.import("resource://webapprt/modules/DownloadView.jsm");
159 // Get the <browser> element in the webapp.xul window.
160 let appBrowser = window.document.getElementById("content");
162 // Set the principal to the correct appID and launch the application.
163 appBrowser.docShell.setIsApp(WebappRT.appID);
164 appBrowser.setAttribute("src", WebappRT.launchURI);
166 if (appData.manifest.fullscreen) {
167 appBrowser.addEventListener("load", function onLoad() {
168 appBrowser.removeEventListener("load", onLoad, true);
169 appBrowser.contentDocument.
170 documentElement.mozRequestFullScreen();
174 WebappRT.startUpdateService();