Wed, 31 Dec 2014 13:27:57 +0100
Ignore runtime configuration files generated during quality assurance.
michael@0 | 1 | /* This Source Code Form is subject to the terms of the Mozilla Public |
michael@0 | 2 | * License, v. 2.0. If a copy of the MPL was not distributed with this file, |
michael@0 | 3 | * You can obtain one at http://mozilla.org/MPL/2.0/. */ |
michael@0 | 4 | |
michael@0 | 5 | /* This module is imported at the startup of an application. It takes care of |
michael@0 | 6 | * permissions installation, application url loading, security settings. Put |
michael@0 | 7 | * stuff here that you want to happen once on startup before the webapp is |
michael@0 | 8 | * loaded. */ |
michael@0 | 9 | |
michael@0 | 10 | this.EXPORTED_SYMBOLS = ["startup"]; |
michael@0 | 11 | |
michael@0 | 12 | const Ci = Components.interfaces; |
michael@0 | 13 | const Cu = Components.utils; |
michael@0 | 14 | |
michael@0 | 15 | Cu.import("resource://gre/modules/Services.jsm"); |
michael@0 | 16 | Cu.import("resource://gre/modules/AppsUtils.jsm"); |
michael@0 | 17 | Cu.import("resource://gre/modules/PermissionsInstaller.jsm"); |
michael@0 | 18 | Cu.import('resource://gre/modules/Payment.jsm'); |
michael@0 | 19 | Cu.import('resource://gre/modules/AlarmService.jsm'); |
michael@0 | 20 | Cu.import("resource://gre/modules/Task.jsm"); |
michael@0 | 21 | Cu.import("resource://gre/modules/Promise.jsm"); |
michael@0 | 22 | Cu.import("resource://gre/modules/osfile.jsm"); |
michael@0 | 23 | |
michael@0 | 24 | Cu.import("resource://webapprt/modules/WebappRT.jsm"); |
michael@0 | 25 | Cu.import("resource://webapprt/modules/WebRTCHandler.jsm"); |
michael@0 | 26 | |
michael@0 | 27 | const PROFILE_DIR = OS.Constants.Path.profileDir; |
michael@0 | 28 | |
michael@0 | 29 | function isFirstRunOrUpdate() { |
michael@0 | 30 | let savedBuildID = null; |
michael@0 | 31 | try { |
michael@0 | 32 | savedBuildID = Services.prefs.getCharPref("webapprt.buildID"); |
michael@0 | 33 | } catch (e) {} |
michael@0 | 34 | |
michael@0 | 35 | let ourBuildID = Services.appinfo.platformBuildID; |
michael@0 | 36 | |
michael@0 | 37 | if (ourBuildID != savedBuildID) { |
michael@0 | 38 | Services.prefs.setCharPref("webapprt.buildID", ourBuildID); |
michael@0 | 39 | return true; |
michael@0 | 40 | } |
michael@0 | 41 | |
michael@0 | 42 | return false; |
michael@0 | 43 | } |
michael@0 | 44 | |
michael@0 | 45 | function writeFile(aPath, aData) { |
michael@0 | 46 | return Task.spawn(function() { |
michael@0 | 47 | let data = new TextEncoder().encode(aData); |
michael@0 | 48 | yield OS.File.writeAtomic(aPath, data, { tmpPath: aPath + ".tmp" }); |
michael@0 | 49 | }); |
michael@0 | 50 | } |
michael@0 | 51 | |
michael@0 | 52 | function createBrandingFiles() { |
michael@0 | 53 | return Task.spawn(function() { |
michael@0 | 54 | let manifest = WebappRT.localeManifest; |
michael@0 | 55 | let name = WebappRT.localeManifest.name; |
michael@0 | 56 | let developer = " "; |
michael@0 | 57 | if (WebappRT.localeManifest.developer) { |
michael@0 | 58 | developer = WebappRT.localeManifest.developer.name; |
michael@0 | 59 | } |
michael@0 | 60 | |
michael@0 | 61 | let brandDTDContent = '<!ENTITY brandShortName "' + name + '">\n\ |
michael@0 | 62 | <!ENTITY brandFullName "' + name + '">\n\ |
michael@0 | 63 | <!ENTITY vendorShortName "' + developer + '">\n\ |
michael@0 | 64 | <!ENTITY trademarkInfo.part1 " ">'; |
michael@0 | 65 | |
michael@0 | 66 | yield writeFile(OS.Path.join(PROFILE_DIR, "brand.dtd"), brandDTDContent); |
michael@0 | 67 | |
michael@0 | 68 | let brandPropertiesContent = 'brandShortName=' + name + '\n\ |
michael@0 | 69 | brandFullName=' + name + '\n\ |
michael@0 | 70 | vendorShortName=' + developer; |
michael@0 | 71 | |
michael@0 | 72 | yield writeFile(OS.Path.join(PROFILE_DIR, "brand.properties"), |
michael@0 | 73 | brandPropertiesContent); |
michael@0 | 74 | }); |
michael@0 | 75 | } |
michael@0 | 76 | |
michael@0 | 77 | // Observes all the events needed to actually launch an application. |
michael@0 | 78 | // It waits for XUL window and webapps registry loading. |
michael@0 | 79 | this.startup = function(window) { |
michael@0 | 80 | return Task.spawn(function () { |
michael@0 | 81 | // Observe XUL window loading. |
michael@0 | 82 | // For tests, it could be already loaded. |
michael@0 | 83 | let deferredWindowLoad = Promise.defer(); |
michael@0 | 84 | if (window.document && window.document.getElementById("content")) { |
michael@0 | 85 | deferredWindowLoad.resolve(); |
michael@0 | 86 | } else { |
michael@0 | 87 | window.addEventListener("DOMContentLoaded", function onLoad() { |
michael@0 | 88 | window.removeEventListener("DOMContentLoaded", onLoad, false); |
michael@0 | 89 | deferredWindowLoad.resolve(); |
michael@0 | 90 | }); |
michael@0 | 91 | } |
michael@0 | 92 | |
michael@0 | 93 | let appUpdated = false; |
michael@0 | 94 | let updatePending = yield WebappRT.isUpdatePending(); |
michael@0 | 95 | if (updatePending) { |
michael@0 | 96 | appUpdated = yield WebappRT.applyUpdate(); |
michael@0 | 97 | } |
michael@0 | 98 | |
michael@0 | 99 | yield WebappRT.loadConfig(); |
michael@0 | 100 | |
michael@0 | 101 | let appData = WebappRT.config.app; |
michael@0 | 102 | |
michael@0 | 103 | // Initialize DOMApplicationRegistry by importing Webapps.jsm. |
michael@0 | 104 | Cu.import("resource://gre/modules/Webapps.jsm"); |
michael@0 | 105 | // Initialize window-independent handling of webapps- notifications. |
michael@0 | 106 | Cu.import("resource://webapprt/modules/WebappManager.jsm"); |
michael@0 | 107 | |
michael@0 | 108 | // Wait for webapps registry loading. |
michael@0 | 109 | yield DOMApplicationRegistry.registryStarted; |
michael@0 | 110 | // Add the currently running app to the registry. |
michael@0 | 111 | yield DOMApplicationRegistry.addInstalledApp(appData, appData.manifest, |
michael@0 | 112 | appData.updateManifest); |
michael@0 | 113 | |
michael@0 | 114 | let manifestURL = appData.manifestURL; |
michael@0 | 115 | if (manifestURL) { |
michael@0 | 116 | // On firstrun, set permissions to their default values. |
michael@0 | 117 | // When the webapp runtime is updated, update the permissions. |
michael@0 | 118 | if (isFirstRunOrUpdate(Services.prefs) || appUpdated) { |
michael@0 | 119 | PermissionsInstaller.installPermissions(appData, true); |
michael@0 | 120 | yield createBrandingFiles(); |
michael@0 | 121 | } |
michael@0 | 122 | } |
michael@0 | 123 | |
michael@0 | 124 | // Branding substitution |
michael@0 | 125 | let aliasFile = Components.classes["@mozilla.org/file/local;1"] |
michael@0 | 126 | .createInstance(Ci.nsIFile); |
michael@0 | 127 | aliasFile.initWithPath(PROFILE_DIR); |
michael@0 | 128 | |
michael@0 | 129 | let aliasURI = Services.io.newFileURI(aliasFile); |
michael@0 | 130 | |
michael@0 | 131 | Services.io.getProtocolHandler("resource") |
michael@0 | 132 | .QueryInterface(Ci.nsIResProtocolHandler) |
michael@0 | 133 | .setSubstitution("webappbranding", aliasURI); |
michael@0 | 134 | |
michael@0 | 135 | // Wait for XUL window loading |
michael@0 | 136 | yield deferredWindowLoad.promise; |
michael@0 | 137 | |
michael@0 | 138 | // Get the <browser> element in the webapp.xul window. |
michael@0 | 139 | let appBrowser = window.document.getElementById("content"); |
michael@0 | 140 | |
michael@0 | 141 | // Set the principal to the correct appID and launch the application. |
michael@0 | 142 | appBrowser.docShell.setIsApp(WebappRT.appID); |
michael@0 | 143 | appBrowser.setAttribute("src", WebappRT.launchURI); |
michael@0 | 144 | |
michael@0 | 145 | if (appData.manifest.fullscreen) { |
michael@0 | 146 | appBrowser.addEventListener("load", function onLoad() { |
michael@0 | 147 | appBrowser.removeEventListener("load", onLoad, true); |
michael@0 | 148 | appBrowser.contentDocument. |
michael@0 | 149 | documentElement.mozRequestFullScreen(); |
michael@0 | 150 | }, true); |
michael@0 | 151 | } |
michael@0 | 152 | |
michael@0 | 153 | WebappRT.startUpdateService(); |
michael@0 | 154 | }); |
michael@0 | 155 | } |