author | Marco Castelluccio <mar.castelluccio@studenti.unina.it> |
Sat, 12 Jul 2014 02:09:50 +0200 | |
changeset 215633 | 89076de4e3c3e10ec5f22cdc85a9f737b65888f8 |
parent 215632 | 9f869623bd08d47db2f246c52ab05964642fadc6 |
child 215634 | 44776990ebd01fada385c16d9944337828032f54 |
push id | 515 |
push user | raliiev@mozilla.com |
push date | Mon, 06 Oct 2014 12:51:51 +0000 |
treeherder | mozilla-release@267c7a481bef [default view] [failures only] |
perfherder | [talos] [build metrics] [platform microbench] (compared to previous push) |
reviewers | myk |
bugs | 1036717 |
milestone | 33.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/toolkit/webapps/tests/app.sjs +++ b/toolkit/webapps/tests/app.sjs @@ -1,19 +1,88 @@ +var Cc = Components.classes; +var Ci = Components.interfaces; +var Cu = Components.utils; + +Cu.import("resource://gre/modules/Services.jsm"); +Cu.import("resource://gre/modules/NetUtil.jsm"); + function getQuery(request) { let query = {}; request.queryString.split('&').forEach(function(val) { let [name, value] = val.split('='); query[name] = unescape(value); }); return query; } +function getTestFile(aName) { + var file = Services.dirsvc.get("CurWorkD", Ci.nsIFile); + + var path = "chrome/toolkit/webapps/tests/data/app/" + aName; + + path.split("/").forEach(function(component) { + file.append(component); + }); + + return file; +} + +function readFile(aFile) { + var fstream = Cc["@mozilla.org/network/file-input-stream;1"]. + createInstance(Ci.nsIFileInputStream); + fstream.init(aFile, -1, 0, 0); + var data = NetUtil.readInputStreamToString(fstream, fstream.available()); + fstream.close(); + return data; +} + +function getHostedManifest(aVersion) { + return readFile(getTestFile("hosted_manifest.webapp")). + replace(/VERSION_TOKEN/g, aVersion); +} + +function getManifest(aVersion) { + return readFile(getTestFile("manifest.webapp")). + replace(/VERSION_TOKEN/g, aVersion); +} + +function buildAppPackage(aVersion) { + const PR_RDWR = 0x04; + const PR_CREATE_FILE = 0x08; + const PR_TRUNCATE = 0x20; + + let zipFile = Services.dirsvc.get("TmpD", Ci.nsIFile); + zipFile.append("application.zip"); + + let zipWriter = Cc["@mozilla.org/zipwriter;1"].createInstance(Ci.nsIZipWriter); + zipWriter.open(zipFile, PR_RDWR | PR_CREATE_FILE | PR_TRUNCATE); + + // Add index.html file to the zip file + zipWriter.addEntryFile("index.html", + Ci.nsIZipWriter.COMPRESSION_NONE, + getTestFile("index.html"), + false); + + // Add manifest to the zip file + var manStream = Cc["@mozilla.org/io/string-input-stream;1"]. + createInstance(Ci.nsIStringInputStream); + var manifest = getManifest(aVersion); + manStream.setData(manifest, manifest.length); + zipWriter.addEntryStream("manifest.webapp", Date.now(), + Ci.nsIZipWriter.COMPRESSION_NONE, + manStream, false); + + zipWriter.close(); + + return readFile(zipFile); +} + function handleRequest(request, response) { response.setHeader("Cache-Control", "no-cache", false); let query = getQuery(request); if ("appreq" in query) { response.setHeader("Content-Type", "text/plain", false); response.write("Hello world!"); @@ -25,9 +94,58 @@ function handleRequest(request, response if ("testreq" in query) { response.setHeader("Content-Type", "text/plain", false); response.write(getState("appreq")); return; } + + if ("setVersion" in query) { + setState("version", query.setVersion); + response.write("OK"); + return; + } + var version = Number(getState("version")); + + if ("getPackage" in query) { + response.setHeader("Content-Type", "application/zip", false); + response.write(buildAppPackage(version)); + + var getPackageQueries = Number(getState("getPackageQueries")); + setState("getPackageQueries", String(++getPackageQueries)); + + return; + } + + if ("getPackageQueries" in query) { + response.setHeader("Content-Type", "text/plain", false); + response.write(String(Number(getState("getPackageQueries")))); + return; + } + + if ("getManifest" in query) { + response.setHeader("Content-Type", "application/x-web-app-manifest+json", false); + response.write(getManifest(version)); + + var getManifestQueries = Number(getState("getManifestQueries")); + setState("getManifestQueries", String(++getManifestQueries)); + + return; + } + + if ("getHostedManifest" in query) { + response.setHeader("Content-Type", "application/x-web-app-manifest+json", false); + response.write(getHostedManifest(version)); + + var getManifestQueries = Number(getState("getManifestQueries")); + setState("getManifestQueries", String(++getManifestQueries)); + + return; + } + + if ("getManifestQueries" in query) { + response.setHeader("Content-Type", "text/plain", false); + response.write(String(Number(getState("getManifestQueries")))); + return; + } }
--- a/toolkit/webapps/tests/chrome.ini +++ b/toolkit/webapps/tests/chrome.ini @@ -23,10 +23,14 @@ skip-if = asan skip-if = os == "win" && os_version == "5.1" # see bug 981251 [test_packaged_uninstall.xul] skip-if = os == "win" && os_version == "5.1" # see bug 981251 [test_hosted_update_from_webapp_runtime.xul] skip-if = asan [test_packaged_update_from_webapp_runtime.xul] skip-if = asan [test_hosted_icons.xul] +[test_hosted_checkforupdates_from_webapp_runtime.xul] +skip-if = asan [test_packaged_icons.xul] +[test_packaged_checkforupdates_from_webapp_runtime.xul] +skip-if = asan [test_webapp_runtime_executable_update.xul]
new file mode 100644 --- /dev/null +++ b/toolkit/webapps/tests/data/app/hosted_manifest.webapp @@ -0,0 +1,11 @@ +{ + "name" : "Test app", + "version" : "VERSION_TOKEN", + "description": "Test app", + "launch_path": "/chrome/toolkit/webapps/tests/app.sjs?appreq", + "developer": { + "name": "marco", + "url": "http://www.example.com/" + }, + "default_locale": "en-US" +}
new file mode 100644 --- /dev/null +++ b/toolkit/webapps/tests/data/app/manifest.webapp @@ -0,0 +1,12 @@ +{ + "name" : "Test app", + "version" : "VERSION_TOKEN", + "package_path": "app.sjs?getPackage=true", + "description": "Test app", + "launch_path": "/index.html", + "developer": { + "name": "marco", + "url": "http://www.example.com/" + }, + "default_locale": "en-US" +}
--- a/toolkit/webapps/tests/head.js +++ b/toolkit/webapps/tests/head.js @@ -445,35 +445,50 @@ function buildAppPackage(aManifest, aIco false); } zipWriter.close(); return zipFile.path; } -function wasAppSJSAccessed() { +function xhrRequest(aQueryString) { let deferred = Promise.defer(); var xhr = new XMLHttpRequest(); xhr.addEventListener("load", function() { - let ret = (xhr.responseText == "done") ? true : false; - deferred.resolve(ret); + deferred.resolve(xhr.responseText); }); xhr.addEventListener("error", aError => deferred.reject(aError)); xhr.addEventListener("abort", aError => deferred.reject(aError)); - xhr.open('GET', 'http://test/chrome/toolkit/webapps/tests/app.sjs?testreq', true); + xhr.open('GET', 'http://test/chrome/toolkit/webapps/tests/app.sjs' + aQueryString, true); xhr.send(); return deferred.promise; } +function wasAppSJSAccessed() { + return xhrRequest('?testreq').then((aResponseText) => { + return (aResponseText == 'done') ? true : false; + }); +} + +function setState(aVar, aState) { + return xhrRequest('?set' + aVar + '=' + aState).then((aResponseText) => { + is(aResponseText, "OK", "set" + aVar + " OK"); + }); +} + +function getState(aVar) { + return xhrRequest('?get' + aVar); +} + function generateDataURI(aFile) { var contentType = Cc["@mozilla.org/mime;1"]. getService(Ci.nsIMIMEService). getTypeFromFile(aFile); var inputStream = Cc["@mozilla.org/network/file-input-stream;1"]. createInstance(Ci.nsIFileInputStream); inputStream.init(aFile, -1, -1, Ci.nsIFileInputStream.CLOSE_ON_EOF); @@ -512,8 +527,20 @@ let setMacRootInstallDir = Task.async(fu "Applications"); yield OS.File.makeDir(NativeApp.prototype._rootInstallDir, { ignoreExisting: true }); SimpleTest.registerCleanupFunction(function() { NativeApp.prototype._rootInstallDir = oldRootInstallDir; }); }); + +let writeToFile = Task.async(function*(aPath, aData) { + let data = new TextEncoder().encode(aData); + + let file; + try { + file = yield OS.File.open(aPath, { truncate: true, write: true }, { unixMode: 0o777 }); + yield file.write(data); + } finally { + yield file.close(); + } +});
copy from toolkit/webapps/tests/test_custom_origin.xul copy to toolkit/webapps/tests/test_hosted_checkforupdates_from_webapp_runtime.xul --- a/toolkit/webapps/tests/test_custom_origin.xul +++ b/toolkit/webapps/tests/test_hosted_checkforupdates_from_webapp_runtime.xul @@ -1,129 +1,111 @@ <?xml version="1.0"?> <?xml-stylesheet type="text/css" href="chrome://global/skin"?> <?xml-stylesheet type="text/css" href="/tests/SimpleTest/test.css"?> <!-- -https://bugzilla.mozilla.org/show_bug.cgi?id=1029674 +https://bugzilla.mozilla.org/show_bug.cgi?id=1036717 --> -<window title="Mozilla Bug 1029674" +<window title="Mozilla Bug 1036717" xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"> <script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script> <script type="application/javascript" src="chrome://mochikit/content/chrome-harness.js"></script> <script type="application/javascript" src="head.js"/> <!-- test results are displayed in the html:body --> <body xmlns="http://www.w3.org/1999/xhtml"> - <a href="https://bugzilla.mozilla.org/show_bug.cgi?id=1029674" - target="_blank">Mozilla Bug 1029674</a> + <a href="https://bugzilla.mozilla.org/show_bug.cgi?id=1036717" + target="_blank">Mozilla Bug 1036717</a> </body> <script type="application/javascript"> <![CDATA[ -/** Test for Bug 1029674 **/ +/** Test for Bug 1036717 **/ "use strict"; SimpleTest.waitForExplicitFinish(); Cu.import("resource://gre/modules/Services.jsm"); Cu.import("resource://gre/modules/NativeApp.jsm"); Cu.import("resource://gre/modules/WebappOSUtils.jsm"); Cu.import("resource://gre/modules/Promise.jsm"); let runTest = Task.async(function*() { - let manifest = yield readJSON(getTestFilePath("data/custom_origin.webapp")); + let manifest = yield readJSON(getTestFilePath("data/app/hosted_manifest.webapp")); let app = { name: manifest.name, - manifestURL: "http://test/chrome/toolkit/webapps/tests/data/custom_origin.webapp", - origin: "app://test.origin.privileged.app", + manifestURL: "http://127.0.0.1:8888/chrome/toolkit/webapps/tests/app.sjs?getHostedManifest=true", + origin: "http://127.0.0.1:8888", }; let testAppInfo = new TestAppInfo(app, true); // Get to a clean state before the test yield testAppInfo.cleanup(); SimpleTest.registerCleanupFunction(() => testAppInfo.cleanup()); setDryRunPref(); - // Use the test root certificate for the test - Cu.import("resource://gre/modules/StoreTrustAnchor.jsm"); - let oldIndex = TrustedRootCertificate.index; - TrustedRootCertificate.index = Ci.nsIX509CertDB.AppXPCShellRoot; - - SimpleTest.registerCleanupFunction(function() { - TrustedRootCertificate.index = oldIndex; - }); - - // Allow signed apps to be installed from the test origin - let oldSignedAppOrigins; - try { - oldSignedAppOrigins = Services.prefs.getCharPref("dom.mozApps.signed_apps_installable_from"); - } catch (ex) {} - - let newSignedAppOrigins = oldSignedAppOrigins.concat(",chrome://mochitests"); - Services.prefs.setCharPref("dom.mozApps.signed_apps_installable_from", newSignedAppOrigins); - - SimpleTest.registerCleanupFunction(function() { - Services.prefs.setCharPref("dom.mozApps.signed_apps_installable_from", oldSignedAppOrigins); - }); - // On Mac build servers, we don't have enough privileges to write to /Applications, // so we install apps in a user-owned directory. if (MAC) { yield setMacRootInstallDir(OS.Path.join(OS.Constants.Path.homeDir, "Applications")); } confirmNextInstall(); - let request = navigator.mozApps.installPackage("http://test/chrome/toolkit/webapps/tests/data/custom_origin.webapp"); + yield setState("Version", 1); + + let request = navigator.mozApps.install(app.manifestURL); let (deferred = Promise.defer()) { request.onerror = function() { deferred.reject(this.error.name); }; request.onsuccess = deferred.resolve; yield deferred.promise; } let appObject = request.result; ok(appObject, "app is non-null"); - let (deferred = Promise.defer()) { - appObject.ondownloaderror = function() { - deferred.reject(this.error.name); - }; - appObject.ondownloadapplied = deferred.resolve; - yield deferred.promise; - }; - while (!WebappOSUtils.isLaunchable(app)) { yield wait(1000); } ok(true, "App launchable"); - let exeFile = getFile(testAppInfo.exePath); + // Force the update timer to fire in 1 second + let prefsFile = OS.Path.join(testAppInfo.profileDir.path, "prefs.js"); + yield writeToFile(prefsFile, "user_pref(\"webapprt.app_update_interval\", 1);"); - ok(exeFile.isExecutable(), "webapprt executable is executable"); + // Update app version + yield setState("Version", 2); + + // Launch the webapprt executable that will verify the presence of an update + let exeFile = getFile(testAppInfo.exePath); let appClosed = false; testAppInfo.appProcess.init(exeFile) testAppInfo.appProcess.runAsync([], 0, () => appClosed = true); - while (!(yield wasAppSJSAccessed()) && !appClosed) { + // If there was a second request to get the manifest, then the webapprt + // has searched for an update. + while (Number(yield getState("ManifestQueries")) < 2 && + !appClosed) { yield wait(1000); } ok(!appClosed, "App was launched and is still running"); + ok(Number(yield getState("ManifestQueries")) >= 2, "Two manifest requests"); SimpleTest.finish(); }); runTest().catch((e) => { ok(false, "Error during test: " + e); SimpleTest.finish(); });
copy from toolkit/webapps/tests/test_custom_origin.xul copy to toolkit/webapps/tests/test_packaged_checkforupdates_from_webapp_runtime.xul --- a/toolkit/webapps/tests/test_custom_origin.xul +++ b/toolkit/webapps/tests/test_packaged_checkforupdates_from_webapp_runtime.xul @@ -1,129 +1,122 @@ <?xml version="1.0"?> <?xml-stylesheet type="text/css" href="chrome://global/skin"?> <?xml-stylesheet type="text/css" href="/tests/SimpleTest/test.css"?> <!-- -https://bugzilla.mozilla.org/show_bug.cgi?id=1029674 +https://bugzilla.mozilla.org/show_bug.cgi?id=1036717 --> -<window title="Mozilla Bug 1029674" +<window title="Mozilla Bug 1036717" xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"> <script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script> <script type="application/javascript" src="chrome://mochikit/content/chrome-harness.js"></script> <script type="application/javascript" src="head.js"/> <!-- test results are displayed in the html:body --> <body xmlns="http://www.w3.org/1999/xhtml"> - <a href="https://bugzilla.mozilla.org/show_bug.cgi?id=1029674" - target="_blank">Mozilla Bug 1029674</a> + <a href="https://bugzilla.mozilla.org/show_bug.cgi?id=1036717" + target="_blank">Mozilla Bug 1036717</a> </body> <script type="application/javascript"> <![CDATA[ -/** Test for Bug 1029674 **/ +/** Test for Bug 1036717 **/ "use strict"; SimpleTest.waitForExplicitFinish(); Cu.import("resource://gre/modules/Services.jsm"); Cu.import("resource://gre/modules/NativeApp.jsm"); Cu.import("resource://gre/modules/WebappOSUtils.jsm"); Cu.import("resource://gre/modules/Promise.jsm"); let runTest = Task.async(function*() { - let manifest = yield readJSON(getTestFilePath("data/custom_origin.webapp")); + let manifest = yield readJSON(getTestFilePath("data/app/manifest.webapp")); let app = { name: manifest.name, - manifestURL: "http://test/chrome/toolkit/webapps/tests/data/custom_origin.webapp", - origin: "app://test.origin.privileged.app", + manifestURL: "http://127.0.0.1:8888/chrome/toolkit/webapps/tests/app.sjs?getManifest=true", + origin: "app://test.app", }; let testAppInfo = new TestAppInfo(app, true); // Get to a clean state before the test yield testAppInfo.cleanup(); SimpleTest.registerCleanupFunction(() => testAppInfo.cleanup()); setDryRunPref(); - // Use the test root certificate for the test - Cu.import("resource://gre/modules/StoreTrustAnchor.jsm"); - let oldIndex = TrustedRootCertificate.index; - TrustedRootCertificate.index = Ci.nsIX509CertDB.AppXPCShellRoot; - - SimpleTest.registerCleanupFunction(function() { - TrustedRootCertificate.index = oldIndex; - }); - - // Allow signed apps to be installed from the test origin - let oldSignedAppOrigins; - try { - oldSignedAppOrigins = Services.prefs.getCharPref("dom.mozApps.signed_apps_installable_from"); - } catch (ex) {} - - let newSignedAppOrigins = oldSignedAppOrigins.concat(",chrome://mochitests"); - Services.prefs.setCharPref("dom.mozApps.signed_apps_installable_from", newSignedAppOrigins); - - SimpleTest.registerCleanupFunction(function() { - Services.prefs.setCharPref("dom.mozApps.signed_apps_installable_from", oldSignedAppOrigins); - }); - // On Mac build servers, we don't have enough privileges to write to /Applications, // so we install apps in a user-owned directory. if (MAC) { yield setMacRootInstallDir(OS.Path.join(OS.Constants.Path.homeDir, "Applications")); } confirmNextInstall(); - let request = navigator.mozApps.installPackage("http://test/chrome/toolkit/webapps/tests/data/custom_origin.webapp"); + yield setState("Version", 1); + + let request = navigator.mozApps.installPackage(app.manifestURL); let (deferred = Promise.defer()) { request.onerror = function() { deferred.reject(this.error.name); }; request.onsuccess = deferred.resolve; yield deferred.promise; } let appObject = request.result; ok(appObject, "app is non-null"); let (deferred = Promise.defer()) { appObject.ondownloaderror = function() { - deferred.reject(this.error.name); + deferred.reject(appObject.downloadError.name); }; appObject.ondownloadapplied = deferred.resolve; yield deferred.promise; }; while (!WebappOSUtils.isLaunchable(app)) { yield wait(1000); } ok(true, "App launchable"); - let exeFile = getFile(testAppInfo.exePath); + // Force the update timer to fire in 1 second + let prefsFile = OS.Path.join(testAppInfo.profileDir.path, "prefs.js"); + yield writeToFile(prefsFile, "user_pref(\"webapprt.app_update_interval\", 1);"); - ok(exeFile.isExecutable(), "webapprt executable is executable"); + // Update app version + yield setState("Version", 2); + + // Launch the webapprt executable that will verify the presence of an update + let exeFile = getFile(testAppInfo.exePath); let appClosed = false; testAppInfo.appProcess.init(exeFile) testAppInfo.appProcess.runAsync([], 0, () => appClosed = true); - while (!(yield wasAppSJSAccessed()) && !appClosed) { + // If there was a second request to get the manifest and the package, + // then the webapprt has searched for an update and has started to + // download it. + while ((Number(yield getState("PackageQueries")) < 2 || + Number(yield getState("ManifestQueries")) < 2) && + !appClosed) { yield wait(1000); } ok(!appClosed, "App was launched and is still running"); + ok(Number(yield getState("ManifestQueries")) >= 2, "Two manifest requests"); + ok(Number(yield getState("PackageQueries")) >= 2, "Two package requests"); SimpleTest.finish(); }); runTest().catch((e) => { ok(false, "Error during test: " + e); SimpleTest.finish(); });
--- a/webapprt/WebappRT.jsm +++ b/webapprt/WebappRT.jsm @@ -128,11 +128,11 @@ this.WebappRT = { }; thisApp.ondownloadapplied = () => { // Application updated, nothing to do. }; thisApp.checkForUpdate(); } - }, 24 * 60 * 60); + }, Services.prefs.getIntPref("webapprt.app_update_interval")); }, };
--- a/webapprt/prefs.js +++ b/webapprt/prefs.js @@ -1,12 +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/. */ +// Check for updates once a day. +pref("webapprt.app_update_interval", 86400); + pref("browser.chromeURL", "chrome://webapprt/content/webapp.xul"); pref("browser.download.folderList", 1); // Disable all add-on locations other than the profile (which can't be disabled this way) pref("extensions.enabledScopes", 1); // Auto-disable any add-ons that are "dropped in" to the profile pref("extensions.autoDisableScopes", 1); // Disable add-on installation via the web-exposed APIs