author | Marco Castelluccio <mar.castelluccio@studenti.unina.it> |
Fri, 16 Aug 2013 15:17:52 -0400 | |
changeset 143012 | 4a6b9390ff5a2a8de95d91bbc1e8d44d75c91375 |
parent 143011 | 92b20164931fa8d38713af8d9a05c931bc020a17 |
child 143013 | 1cac9051df048e3cb65c5d4aee187c7871ecdea2 |
push id | 32605 |
push user | philringnalda@gmail.com |
push date | Mon, 19 Aug 2013 00:51:46 +0000 |
treeherder | mozilla-inbound@7f882e063eaf [default view] [failures only] |
perfherder | [talos] [build metrics] [platform microbench] (compared to previous push) |
reviewers | myk |
bugs | 892837 |
milestone | 26.0a1 |
first release with | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
last release without | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
--- a/webapprt/CommandLineHandler.js +++ b/webapprt/CommandLineHandler.js @@ -3,17 +3,16 @@ * You can obtain one at http://mozilla.org/MPL/2.0/. */ const Cc = Components.classes; const Ci = Components.interfaces; const Cu = Components.utils; Cu.import("resource://gre/modules/XPCOMUtils.jsm"); Cu.import("resource://gre/modules/Services.jsm"); -Cu.import("resource://webapprt/modules/WebappRT.jsm"); function CommandLineHandler() {} CommandLineHandler.prototype = { classID: Components.ID("{6d69c782-40a3-469b-8bfd-3ee366105a4a}"), QueryInterface: XPCOMUtils.generateQI([Ci.nsICommandLineHandler]), @@ -25,22 +24,25 @@ CommandLineHandler.prototype = { if (inTestMode) { // Open the mochitest shim window, which configures the runtime for tests. Services.ww.openWindow(null, "chrome://webapprt/content/mochitest.xul", "_blank", "chrome,dialog=no", args); } else { - args.setProperty("url", WebappRT.launchURI); - Services.ww.openWindow(null, - "chrome://webapprt/content/webapp.xul", - "_blank", - "chrome,dialog=no,resizable,scrollbars,centerscreen", - args); + // We're opening the window here in order to show it as soon as possible. + let window = Services.ww.openWindow(null, + "chrome://webapprt/content/webapp.xul", + "_blank", + "chrome,dialog=no,resizable,scrollbars,centerscreen", + null); + // Load the module to start up the app + Cu.import("resource://webapprt/modules/Startup.jsm"); + startup(window); } }, _handleTestMode: function _handleTestMode(cmdLine, args) { // -test-mode [url] let idx = cmdLine.findFlag("test-mode", true); if (idx < 0) return false;
--- a/webapprt/Startup.jsm +++ b/webapprt/Startup.jsm @@ -1,32 +1,94 @@ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this file, * You can obtain one at http://mozilla.org/MPL/2.0/. */ -/* This is imported by each new webapp window but is only evaluated the first - * time it is imported. Put stuff here that you want to happen once on startup - * before the webapp is loaded. But note that the "stuff" happens immediately - * the first time this module is imported. So only put stuff here that must - * happen before the webapp is loaded. */ +/* This module is imported at the startup of an application. It takes care of + * permissions installation, application url loading, security settings. Put + * stuff here that you want to happen once on startup before the webapp is + * loaded. */ -this.EXPORTED_SYMBOLS = []; +this.EXPORTED_SYMBOLS = ["startup"]; const Ci = Components.interfaces; const Cu = Components.utils; Cu.import("resource://gre/modules/Services.jsm"); - // Initialize DOMApplicationRegistry by importing Webapps.jsm. Cu.import("resource://gre/modules/Webapps.jsm"); +Cu.import("resource://gre/modules/AppsUtils.jsm"); +Cu.import("resource://gre/modules/PermissionsInstaller.jsm"); +Cu.import("resource://gre/modules/Task.jsm"); +Cu.import("resource://gre/modules/Promise.jsm"); // Initialize window-independent handling of webapps- notifications. Cu.import("resource://webapprt/modules/WebappsHandler.jsm"); -WebappsHandler.init(); +Cu.import("resource://webapprt/modules/WebappRT.jsm"); + +function isFirstRunOrUpdate() { + let savedBuildID = null; + try { + savedBuildID = Services.prefs.getCharPref("webapprt.buildID"); + } catch (e) {} + + let ourBuildID = Services.appinfo.platformBuildID; + + if (ourBuildID != savedBuildID) { + Services.prefs.setCharPref("webapprt.buildID", ourBuildID); + return true; + } + + return false; +} + +// Observes all the events needed to actually launch an application. +// It waits for XUL window and webapps registry loading. +this.startup = function(window) { + return Task.spawn(function () { + // Observe registry loading. + let deferredRegistry = Promise.defer(); + function observeRegistryLoading() { + Services.obs.removeObserver(observeRegistryLoading, "webapps-registry-start"); + deferredRegistry.resolve(); + } + Services.obs.addObserver(observeRegistryLoading, "webapps-registry-start", false); -// On firstrun, set permissions to their default values. -if (!Services.prefs.getBoolPref("webapprt.firstrun")) { - // Once we support packaged apps, set their permissions here on firstrun. + // Observe XUL window loading. + // For tests, it could be already loaded. + let deferredWindowLoad = Promise.defer(); + if (window.document && window.document.getElementById("content")) { + deferredWindowLoad.resolve(); + } else { + window.addEventListener("load", function onLoad() { + window.removeEventListener("load", onLoad, false); + deferredWindowLoad.resolve(); + }); + } + + // Wait for webapps registry loading. + yield deferredRegistry.promise; - // Now that we've set the appropriate permissions, twiddle the firstrun - // flag so we don't try to do so again. - Services.prefs.setBoolPref("webapprt.firstrun", true); + // Install/update permissions and get the appID from the webapps registry. + let appID = Ci.nsIScriptSecurityManager.NO_APP_ID; + let manifestURL = WebappRT.config.app.manifestURL; + if (manifestURL) { + appID = DOMApplicationRegistry.getAppLocalIdByManifestURL(manifestURL); + + // On firstrun, set permissions to their default values. + // When the webapp runtime is updated, update the permissions. + // TODO: Update the permissions when the application is updated. + if (isFirstRunOrUpdate(Services.prefs)) { + PermissionsInstaller.installPermissions(WebappRT.config.app, true); + } + } + + // Wait for XUL window loading + yield deferredWindowLoad.promise; + + // Get the <browser> element in the webapp.xul window. + let appBrowser = window.document.getElementById("content"); + + // Set the principal to the correct appID and launch the application. + appBrowser.docShell.setIsApp(appID); + appBrowser.setAttribute("src", WebappRT.launchURI); + }).then(null, Cu.reportError.bind(Cu)); }
--- a/webapprt/WebappRT.jsm +++ b/webapprt/WebappRT.jsm @@ -19,24 +19,23 @@ XPCOMUtils.defineLazyGetter(this, "FileU this.WebappRT = { _config: null, get config() { if (this._config) return this._config; - let config; let webappFile = FileUtils.getFile("AppRegD", ["webapp.json"]); let inputStream = Cc["@mozilla.org/network/file-input-stream;1"]. createInstance(Ci.nsIFileInputStream); inputStream.init(webappFile, -1, 0, 0); let json = Cc["@mozilla.org/dom/json;1"].createInstance(Ci.nsIJSON); - config = json.decodeFromStream(inputStream, webappFile.fileSize); + let config = json.decodeFromStream(inputStream, webappFile.fileSize); return this._config = config; }, // This exists to support test mode, which installs webapps after startup. // Ideally we wouldn't have to have a setter, as tests can just delete // the getter and then set the property. But the object to which they set it // will have a reference to its global object, so our reference to it
--- a/webapprt/WebappsHandler.jsm +++ b/webapprt/WebappsHandler.jsm @@ -5,29 +5,24 @@ "use strict"; this.EXPORTED_SYMBOLS = ["WebappsHandler"]; let Cc = Components.classes; let Ci = Components.interfaces; let Cu = Components.utils; +Cu.import("resource://gre/modules/XPCOMUtils.jsm"); Cu.import("resource://gre/modules/Services.jsm"); Cu.import("resource://gre/modules/Webapps.jsm"); Cu.import("resource://gre/modules/AppsUtils.jsm"); Cu.import("resource://gre/modules/WebappsInstaller.jsm"); Cu.import("resource://gre/modules/WebappOSUtils.jsm"); this.WebappsHandler = { - init: function() { - Services.obs.addObserver(this, "webapps-ask-install", false); - Services.obs.addObserver(this, "webapps-launch", false); - Services.obs.addObserver(this, "webapps-uninstall", false); - }, - observe: function(subject, topic, data) { data = JSON.parse(data); data.mm = subject; switch (topic) { case "webapps-ask-install": let chromeWin = Services.wm.getOuterWindowWithId(data.oid); if (chromeWin) @@ -78,10 +73,17 @@ this.WebappsHandler = { } ); } else { DOMApplicationRegistry.denyInstall(data); } } else { DOMApplicationRegistry.denyInstall(data); } - } + }, + + QueryInterface: XPCOMUtils.generateQI([Ci.nsIObserver, + Ci.nsISupportsWeakReference]) }; + +Services.obs.addObserver(WebappsHandler, "webapps-ask-install", false); +Services.obs.addObserver(WebappsHandler, "webapps-launch", false); +Services.obs.addObserver(WebappsHandler, "webapps-uninstall", false);
copy from webapprt/content/mochitest.js copy to webapprt/content/mochitest-shared.js --- a/webapprt/content/mochitest.js +++ b/webapprt/content/mochitest-shared.js @@ -1,19 +1,15 @@ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this file, * You can obtain one at http://mozilla.org/MPL/2.0/. */ -/* Note: this script is loaded by both mochitest.xul and head.js, so make sure +/* Note: this script is loaded by both mochitest.js and head.js, so make sure * the code you put here can be evaluated by both! */ -const Ci = Components.interfaces; -const Cu = Components.utils; - -Cu.import("resource://gre/modules/Services.jsm"); Cu.import("resource://webapprt/modules/WebappRT.jsm"); // When WebappsHandler opens an install confirmation dialog for apps we install, // close it, which will be seen as the equivalent of cancelling the install. // This doesn't prevent us from installing those apps, as we listen for the same // notification as WebappsHandler and do the install ourselves. It just // prevents the modal installation confirmation dialogs from hanging tests. Services.ww.registerNotification({ @@ -50,23 +46,45 @@ function becomeWebapp(manifestURL, param Services.obs.removeObserver(observeInstall, "webapps-ask-install"); // Step 2: Configure the runtime session to represent the app. // We load DOMApplicationRegistry into a local scope to avoid appearing // to leak it. let scope = {}; Cu.import("resource://gre/modules/Webapps.jsm", scope); + Cu.import("resource://webapprt/modules/Startup.jsm", scope); scope.DOMApplicationRegistry.confirmInstall(JSON.parse(data)); let installRecord = JSON.parse(data); installRecord.mm = subj; installRecord.registryDir = Services.dirsvc.get("ProfD", Ci.nsIFile).path; WebappRT.config = installRecord; - onBecome(); + let win = Services.wm.getMostRecentWindow("webapprt:webapp"); + if (!win) { + win = Services.ww.openWindow(null, + "chrome://webapprt/content/webapp.xul", + "_blank", + "chrome,dialog=no,resizable,scrollbars,centerscreen", + null); + } + + let promise = scope.startup(win); + + // During chrome tests, we use the same window to load all the tests. We + // need to change the buildID so that the permissions for the currently + // tested application get installed. + Services.prefs.setCharPref("webapprt.buildID", WebappRT.config.app.manifestURL); + + // During tests, the webapps registry is already loaded. + // The Startup module needs to be notified when the webapps registry + // gets loaded, so we do that now. + Services.obs.notifyObservers(this, "webapps-registry-start", null); + + promise.then(onBecome); } Services.obs.addObserver(observeInstall, "webapps-ask-install", false); // Step 1: Install the app at the URL specified by the manifest. let url = Services.io.newURI(manifestURL, null, null); navigator.mozApps.install(url.spec, parameters); }
--- a/webapprt/content/mochitest.js +++ b/webapprt/content/mochitest.js @@ -1,72 +1,38 @@ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this file, * You can obtain one at http://mozilla.org/MPL/2.0/. */ -/* Note: this script is loaded by both mochitest.xul and head.js, so make sure - * the code you put here can be evaluated by both! */ - const Ci = Components.interfaces; const Cu = Components.utils; Cu.import("resource://gre/modules/Services.jsm"); -Cu.import("resource://webapprt/modules/WebappRT.jsm"); + +Services.scriptloader + .loadSubScript("chrome://webapprt/content/mochitest-shared.js", this); + +// In test mode, the runtime isn't configured until we tell it to become +// an app, which requires us to use DOMApplicationRegistry to install one. +// But DOMApplicationRegistry needs to know the location of its registry dir, +// so we need to configure the runtime with at least that information. +WebappRT.config = { + registryDir: Services.dirsvc.get("ProfD", Ci.nsIFile).path, +}; + -// When WebappsHandler opens an install confirmation dialog for apps we install, -// close it, which will be seen as the equivalent of cancelling the install. -// This doesn't prevent us from installing those apps, as we listen for the same -// notification as WebappsHandler and do the install ourselves. It just -// prevents the modal installation confirmation dialogs from hanging tests. -Services.ww.registerNotification({ - observe: function(win, topic) { - if (topic == "domwindowopened") { - // Wait for load because the window is not yet sufficiently initialized. - win.addEventListener("load", function onLoadWindow() { - win.removeEventListener("load", onLoadWindow, false); - if (win.location == "chrome://global/content/commonDialog.xul" && - win.opener == window) { - win.close(); - } - }, false); +Cu.import("resource://gre/modules/Webapps.jsm"); + +DOMApplicationRegistry.allAppsLaunchable = true; + +becomeWebapp("http://mochi.test:8888/tests/webapprt/test/content/test.webapp", + undefined, function onBecome() { + if (window.arguments && window.arguments[0]) { + let testUrl = window.arguments[0].QueryInterface(Ci.nsIPropertyBag2).get("url"); + + if (testUrl) { + let win = Services.wm.getMostRecentWindow("webapprt:webapp"); + win.document.getElementById("content").setAttribute("src", testUrl); } } + + window.close(); }); - -/** - * Transmogrify the runtime session into one for the given webapp. - * - * @param {String} manifestURL - * The URL of the webapp's manifest, relative to the base URL. - * Note that the base URL points to the *chrome* WebappRT mochitests, - * so you must supply an absolute URL to manifests elsewhere. - * @param {Object} parameters - * The value to pass as the "parameters" argument to - * mozIDOMApplicationRegistry.install, e.g., { receipts: ... }. - * Use undefined to pass nothing. - * @param {Function} onBecome - * The callback to call once the transmogrification is complete. - */ -function becomeWebapp(manifestURL, parameters, onBecome) { - function observeInstall(subj, topic, data) { - Services.obs.removeObserver(observeInstall, "webapps-ask-install"); - - // Step 2: Configure the runtime session to represent the app. - // We load DOMApplicationRegistry into a local scope to avoid appearing - // to leak it. - - let scope = {}; - Cu.import("resource://gre/modules/Webapps.jsm", scope); - scope.DOMApplicationRegistry.confirmInstall(JSON.parse(data)); - - let installRecord = JSON.parse(data); - installRecord.mm = subj; - installRecord.registryDir = Services.dirsvc.get("ProfD", Ci.nsIFile).path; - WebappRT.config = installRecord; - - onBecome(); - } - Services.obs.addObserver(observeInstall, "webapps-ask-install", false); - - // Step 1: Install the app at the URL specified by the manifest. - let url = Services.io.newURI(manifestURL, null, null); - navigator.mozApps.install(url.spec, parameters); -}
--- a/webapprt/content/mochitest.xul +++ b/webapprt/content/mochitest.xul @@ -6,39 +6,11 @@ <?xml-stylesheet href="chrome://global/skin/" type="text/css"?> <window windowtype="webapprt:mochitest" xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"> <script type="application/javascript" src="chrome://webapprt/content/mochitest.js"/> -<script type="application/javascript"> - Cu.import("resource://webapprt/modules/WebappRT.jsm"); - - // In test mode, the runtime isn't configured until we tell it to become - // an app, which requires us to use DOMApplicationRegistry to install one. - // But DOMApplicationRegistry needs to know the location of its registry dir, - // so we need to configure the runtime with at least that information. - WebappRT.config = { - registryDir: Services.dirsvc.get("ProfD", Ci.nsIFile).path, - }; - - Cu.import("resource://gre/modules/Webapps.jsm"); - - DOMApplicationRegistry.allAppsLaunchable = true; - - becomeWebapp("http://mochi.test:8888/tests/webapprt/test/content/test.webapp", - undefined, function onBecome() { - Services.ww.openWindow( - null, - "chrome://webapprt/content/webapp.xul", - "_blank", - "chrome,dialog=no,resizable,scrollbars,centerscreen", - window.arguments[0] - ); - window.close(); - }); -</script> - <description value="WebappRT Test Shim"/> </window>
--- a/webapprt/content/webapp.js +++ b/webapprt/content/webapp.js @@ -1,17 +1,16 @@ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this file, * You can obtain one at http://mozilla.org/MPL/2.0/. */ const Cc = Components.classes; const Ci = Components.interfaces; const Cu = Components.utils; -Cu.import("resource://webapprt/modules/Startup.jsm"); Cu.import("resource://webapprt/modules/WebappRT.jsm"); Cu.import("resource://gre/modules/Services.jsm"); Cu.import("resource://gre/modules/XPCOMUtils.jsm"); XPCOMUtils.defineLazyGetter(this, "gAppBrowser", function() document.getElementById("content")); #ifdef MOZ_CRASHREPORTER @@ -44,38 +43,26 @@ let progressListener = { updateCrashReportURL(aRequest.URI); } } }; function onLoad() { window.removeEventListener("load", onLoad, false); - let args = window.arguments && window.arguments[0] ? - window.arguments[0].QueryInterface(Ci.nsIPropertyBag2) : - null; - gAppBrowser.addProgressListener(progressListener, Ci.nsIWebProgress.NOTIFY_LOCATION | Ci.nsIWebProgress.NOTIFY_STATE_DOCUMENT); updateMenuItems(); // Listen for clicks to redirect <a target="_blank"> to the browser. // This doesn't capture clicks so content can capture them itself and do // something different if it doesn't want the default behavior. gAppBrowser.addEventListener("click", onContentClick, false, true); - - // This is not the only way that a URL gets loaded in the app browser. - // When content calls openWindow(), there are no window.arguments, - // but something in the platform loads the URL specified by the content. - if (args && args.hasKey("url")) { - gAppBrowser.setAttribute("src", args.get("url")); - } - } window.addEventListener("load", onLoad, false); function onUnload() { gAppBrowser.removeProgressListener(progressListener); } window.addEventListener("unload", onUnload, false);
--- a/webapprt/jar.mn +++ b/webapprt/jar.mn @@ -1,10 +1,11 @@ # This Source Code Form is subject to the terms of the Mozilla Public # License, v. 2.0. If a copy of the MPL was not distributed with this # file, You can obtain one at http://mozilla.org/MPL/2.0/. webapprt.jar: % content webapprt %content/ * content/webapp.js (content/webapp.js) * content/webapp.xul (content/webapp.xul) + content/mochitest-shared.js (content/mochitest-shared.js) content/mochitest.js (content/mochitest.js) content/mochitest.xul (content/mochitest.xul)
--- a/webapprt/prefs.js +++ b/webapprt/prefs.js @@ -11,19 +11,16 @@ pref("extensions.enabledScopes", 1); pref("extensions.autoDisableScopes", 1); // Disable add-on installation via the web-exposed APIs pref("xpinstall.enabled", false); // Disable installation of distribution add-ons pref("extensions.installDistroAddons", false); // Disable the add-on compatibility dialog pref("extensions.showMismatchUI", false); -// Whether or not we've ever run. We use this to set permissions on firstrun. -pref("webapprt.firstrun", false); - // Set reportURL for crashes pref("breakpad.reportURL", "https://crash-stats.mozilla.com/report/index/"); // Blocklist preferences pref("extensions.blocklist.enabled", true); pref("extensions.blocklist.interval", 86400); // Controls what level the blocklist switches from warning about items to forcibly // blocking them.
--- a/webapprt/test/chrome/head.js +++ b/webapprt/test/chrome/head.js @@ -1,18 +1,18 @@ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this file, * You can obtain one at http://mozilla.org/MPL/2.0/. */ Cu.import("resource://gre/modules/Services.jsm"); // Some of the code we want to provide to chrome mochitests is in another file // so we can share it with the mochitest shim window, thus we need to load it. -Services.scriptloader.loadSubScript("chrome://webapprt/content/mochitest.js", - this); +Services.scriptloader + .loadSubScript("chrome://webapprt/content/mochitest-shared.js", this); const MANIFEST_URL_BASE = Services.io.newURI( "http://test/webapprtChrome/webapprt/test/chrome/", null, null); /** * Load the webapp in the app browser. * * @param {String} manifestURL