michael@0: var Cc = Components.classes; michael@0: var Ci = Components.interfaces; michael@0: var Cu = Components.utils; michael@0: michael@0: Cu.import("resource://gre/modules/Services.jsm"); michael@0: Cu.import("resource://gre/modules/NetUtil.jsm"); michael@0: michael@0: function handleRequest(aRequest, aResponse) { michael@0: aResponse.setHeader("Access-Control-Allow-Origin", "*", false); michael@0: michael@0: var query = getQuery(aRequest); michael@0: michael@0: if ("setVersion" in query) { michael@0: setState("version", query.setVersion); michael@0: aResponse.write("OK"); michael@0: return; michael@0: } michael@0: var version = Number(getState("version")); michael@0: michael@0: // setPrecompile sets the "precompile" field in the app manifest michael@0: if ("setPrecompile" in query) { michael@0: setState("precompile", query.setPrecompile); michael@0: aResponse.write("OK"); michael@0: return; michael@0: } michael@0: var precompile = getState("precompile"); michael@0: michael@0: if ("getPackage" in query) { michael@0: aResponse.setHeader("Content-Type", "application/zip", false); michael@0: aResponse.write(buildAppPackage(version, precompile)); michael@0: return; michael@0: } michael@0: michael@0: if ("getManifest" in query) { michael@0: aResponse.setHeader("Content-Type", "application/x-web-app-manifest+json", false); michael@0: aResponse.write(getManifest(version, precompile)); michael@0: return; michael@0: } michael@0: } michael@0: michael@0: function getQuery(aRequest) { michael@0: var query = {}; michael@0: aRequest.queryString.split('&').forEach(function(val) { michael@0: var [name, value] = val.split('='); michael@0: query[decodeURIComponent(name)] = decodeURIComponent(value); michael@0: }); michael@0: return query; michael@0: } michael@0: michael@0: function getTestFile(aName) { michael@0: var file = Services.dirsvc.get("CurWorkD", Ci.nsIFile); michael@0: michael@0: var path = "chrome/dom/apps/tests/asmjs/" + aName; michael@0: michael@0: path.split("/").forEach(function(component) { michael@0: file.append(component); michael@0: }); michael@0: michael@0: return file; michael@0: } michael@0: michael@0: function readFile(aFile) { michael@0: var fstream = Cc["@mozilla.org/network/file-input-stream;1"]. michael@0: createInstance(Ci.nsIFileInputStream); michael@0: fstream.init(aFile, -1, 0, 0); michael@0: var data = NetUtil.readInputStreamToString(fstream, fstream.available()); michael@0: fstream.close(); michael@0: return data; michael@0: } michael@0: michael@0: function getManifest(aVersion, aPrecompile) { michael@0: return readFile(getTestFile("manifest.webapp")). michael@0: replace(/VERSIONTOKEN/g, aVersion). michael@0: replace(/PRECOMPILETOKEN/g, aPrecompile); michael@0: } michael@0: michael@0: function buildAppPackage(aVersion, aPrecompile) { michael@0: const PR_RDWR = 0x04; michael@0: const PR_CREATE_FILE = 0x08; michael@0: const PR_TRUNCATE = 0x20; michael@0: michael@0: let zipFile = Services.dirsvc.get("TmpD", Ci.nsIFile); michael@0: zipFile.append("application.zip"); michael@0: michael@0: let zipWriter = Cc["@mozilla.org/zipwriter;1"].createInstance(Ci.nsIZipWriter); michael@0: zipWriter.open(zipFile, PR_RDWR | PR_CREATE_FILE | PR_TRUNCATE); michael@0: michael@0: // Add index.html file to the zip file michael@0: zipWriter.addEntryFile("index.html", michael@0: Ci.nsIZipWriter.COMPRESSION_NONE, michael@0: getTestFile("index.html"), michael@0: false); michael@0: michael@0: // Add manifest to the zip file michael@0: var manStream = Cc["@mozilla.org/io/string-input-stream;1"]. michael@0: createInstance(Ci.nsIStringInputStream); michael@0: var manifest = getManifest(aVersion, aPrecompile); michael@0: manStream.setData(manifest, manifest.length); michael@0: zipWriter.addEntryStream("manifest.webapp", Date.now(), michael@0: Ci.nsIZipWriter.COMPRESSION_NONE, michael@0: manStream, false); michael@0: michael@0: // Add an asm.js module to the zip file michael@0: // The module also contains some code to perform tests michael@0: michael@0: // Creates a module big enough to be cached michael@0: // The module is different according to the app version, this way michael@0: // we can test that on update the new module is compiled michael@0: var code = "function f() { 'use asm';\n"; michael@0: for (var i = 0; i < 5000; i++) { michael@0: code += "function g" + i + "() { return " + i + "}\n"; michael@0: } michael@0: code += "return g" + aVersion + " }\n\ michael@0: var jsFuns = SpecialPowers.Cu.getJSTestingFunctions();\n\ michael@0: ok(jsFuns.isAsmJSCompilationAvailable(), 'asm.js compilation is available');\n\ michael@0: ok(jsFuns.isAsmJSModule(f), 'f is an asm.js module');\n\ michael@0: var g" + aVersion + " = f();\n\ michael@0: ok(jsFuns.isAsmJSFunction(g" + aVersion + "), 'g" + aVersion + " is an asm.js function');\n\ michael@0: ok(g" + aVersion + "() === " + aVersion + ", 'g" + aVersion + " returns the correct result');"; michael@0: michael@0: // If the "precompile" field contains this module, we test that it is loaded michael@0: // from the cache. michael@0: // If the "precompile" field doesn't contain the module or is incorrect, we michael@0: // test that the module is not loaded from the cache. michael@0: if (aPrecompile == '["asmjsmodule.js"]') { michael@0: code += "ok(jsFuns.isAsmJSModuleLoadedFromCache(f), 'module loaded from cache');\n"; michael@0: } else { michael@0: code += "ok(!jsFuns.isAsmJSModuleLoadedFromCache(f), 'module not loaded from cache');\n"; michael@0: } michael@0: michael@0: code += "alert('DONE');"; michael@0: michael@0: var jsStream = Cc["@mozilla.org/io/string-input-stream;1"]. michael@0: createInstance(Ci.nsIStringInputStream); michael@0: jsStream.setData(code, code.length); michael@0: zipWriter.addEntryStream("asmjsmodule.js", Date.now(), michael@0: Ci.nsIZipWriter.COMPRESSION_NONE, michael@0: jsStream, false); michael@0: michael@0: zipWriter.close(); michael@0: michael@0: return readFile(zipFile); michael@0: }