1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/dom/apps/tests/file_packaged_app.sjs Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,169 @@ 1.4 +var Cc = Components.classes; 1.5 +var Ci = Components.interfaces; 1.6 +var Cu = Components.utils; 1.7 + 1.8 +// From prio.h 1.9 +const PR_RDWR = 0x04; 1.10 +const PR_CREATE_FILE = 0x08; 1.11 +const PR_TRUNCATE = 0x20; 1.12 + 1.13 +Cu.import("resource://gre/modules/FileUtils.jsm"); 1.14 +Cu.import("resource://gre/modules/NetUtil.jsm"); 1.15 + 1.16 +var gBasePath = "tests/dom/apps/tests/"; 1.17 +var gMiniManifestTemplate = "file_packaged_app.template.webapp"; 1.18 +var gAppTemplate = "file_packaged_app.template.html"; 1.19 +var gAppName = "appname"; 1.20 +var gDevName = "devname"; 1.21 +var gDevUrl = "http://dev.url"; 1.22 + 1.23 +function handleRequest(request, response) { 1.24 + var query = getQuery(request); 1.25 + 1.26 + response.setHeader("Access-Control-Allow-Origin", "*", false); 1.27 + 1.28 + var packageSize = ("packageSize" in query) ? query.packageSize : 0; 1.29 + var appName = ("appName" in query) ? query.appName : gAppName; 1.30 + var devName = ("devName" in query) ? query.devName : gDevName; 1.31 + var devUrl = ("devUrl" in query) ? query.devUrl : gDevUrl; 1.32 + 1.33 + // If this is a version update, update state, prepare the manifest, 1.34 + // the application package and return. 1.35 + if ("setVersion" in query) { 1.36 + var version = query.setVersion; 1.37 + setState("version", version); 1.38 + var packageVersion = ("dontUpdatePackage" in query) ? version - 1 : version; 1.39 + var packageName = "test_packaged_app_" + packageVersion + ".zip"; 1.40 + 1.41 + setState("packageName", packageName); 1.42 + var packagePath = "/" + gBasePath + "file_packaged_app.sjs?getPackage=" + 1.43 + packageName; 1.44 + setState("packagePath", packagePath); 1.45 + 1.46 + if (version == packageVersion) { 1.47 + // Create the application package. 1.48 + var zipWriter = Cc["@mozilla.org/zipwriter;1"] 1.49 + .createInstance(Ci.nsIZipWriter); 1.50 + var zipFile = FileUtils.getFile("TmpD", [packageName]); 1.51 + zipWriter.open(zipFile, PR_RDWR | PR_CREATE_FILE | PR_TRUNCATE); 1.52 + 1.53 + // We want to run some tests without the manifest included in the zip. 1.54 + if (version != "0") { 1.55 + var manifestTemplate = gBasePath + gMiniManifestTemplate; 1.56 + var manifest = makeResource(manifestTemplate, version, packagePath, 1.57 + packageSize, appName, devName, devUrl); 1.58 + addZipEntry(zipWriter, manifest, "manifest.webapp"); 1.59 + } 1.60 + 1.61 + var appTemplate = gBasePath + gAppTemplate; 1.62 + var app = makeResource(appTemplate, version, packagePath, packageSize, 1.63 + appName, devName, devUrl); 1.64 + addZipEntry(zipWriter, app, "index.html"); 1.65 + 1.66 + zipWriter.close(); 1.67 + } 1.68 + 1.69 + response.setHeader("Content-Type", "text/html", false); 1.70 + response.write("OK"); 1.71 + return; 1.72 + } 1.73 + 1.74 + // Get the version from server state 1.75 + var version = Number(getState("version")); 1.76 + var packageName = String(getState("packageName")); 1.77 + var packagePath = String(getState("packagePath")); 1.78 + 1.79 + var etag = getEtag(request, version); 1.80 + 1.81 + if (etagMatches(request, etag)) { 1.82 + dump("Etags Match. Sending 304\n"); 1.83 + response.setStatusLine(request.httpVersion, "304", "Not modified"); 1.84 + return; 1.85 + } 1.86 + 1.87 + response.setHeader("Etag", etag, false); 1.88 + 1.89 + // Serve the application package corresponding to the requested app version. 1.90 + if ("getPackage" in query) { 1.91 + var resource = readFile(packageName, true); 1.92 + response.setHeader("Content-Type", 1.93 + "Content-Type: application/java-archive", false); 1.94 + response.write(resource); 1.95 + return; 1.96 + } 1.97 + 1.98 + // Serve the mini-manifest corresponding to the requested app version. 1.99 + if ("getManifest" in query) { 1.100 + var template = gBasePath + gMiniManifestTemplate; 1.101 + if (!("noManifestContentType" in query)) { 1.102 + response.setHeader("Content-Type", 1.103 + "application/x-web-app-manifest+json", false); 1.104 + } 1.105 + packagePath = "wrongPackagePath" in query ? "" : packagePath; 1.106 + var manifest = makeResource(template, version, packagePath, packageSize, 1.107 + appName, devName, devUrl); 1.108 + response.write(manifest); 1.109 + return; 1.110 + } 1.111 + 1.112 + response.setHeader("Content-type", "text-html", false); 1.113 + response.write("KO"); 1.114 +} 1.115 + 1.116 +function getQuery(request) { 1.117 + var query = {}; 1.118 + request.queryString.split('&').forEach(function (val) { 1.119 + var [name, value] = val.split('='); 1.120 + query[name] = unescape(value); 1.121 + }); 1.122 + return query; 1.123 +} 1.124 + 1.125 +function getEtag(request, version) { 1.126 + return request.queryString.replace(/&/g, '-').replace(/=/g, '-') + 1.127 + '-' + version; 1.128 +} 1.129 + 1.130 +function etagMatches(request, etag) { 1.131 + return request.hasHeader("If-None-Match") && 1.132 + request.getHeader("If-None-Match") == etag; 1.133 +} 1.134 + 1.135 +// File and resources helpers 1.136 + 1.137 +function addZipEntry(zipWriter, entry, entryName) { 1.138 + var stream = Cc["@mozilla.org/io/string-input-stream;1"] 1.139 + .createInstance(Ci.nsIStringInputStream); 1.140 + stream.setData(entry, entry.length); 1.141 + zipWriter.addEntryStream(entryName, Date.now(), 1.142 + Ci.nsIZipWriter.COMPRESSION_BEST, stream, false); 1.143 +} 1.144 + 1.145 +function readFile(path, fromTmp) { 1.146 + var dir = fromTmp ? "TmpD" : "CurWorkD"; 1.147 + var file = Cc["@mozilla.org/file/directory_service;1"] 1.148 + .getService(Ci.nsIProperties) 1.149 + .get(dir, Ci.nsILocalFile); 1.150 + var fstream = Cc["@mozilla.org/network/file-input-stream;1"] 1.151 + .createInstance(Ci.nsIFileInputStream); 1.152 + var split = path.split("/"); 1.153 + for(var i = 0; i < split.length; ++i) { 1.154 + file.append(split[i]); 1.155 + } 1.156 + fstream.init(file, -1, 0, 0); 1.157 + var data = NetUtil.readInputStreamToString(fstream, fstream.available()); 1.158 + fstream.close(); 1.159 + return data; 1.160 +} 1.161 + 1.162 +function makeResource(templatePath, version, packagePath, packageSize, 1.163 + appName, developerName, developerUrl) { 1.164 + var res = readFile(templatePath, false) 1.165 + .replace(/VERSIONTOKEN/g, version) 1.166 + .replace(/PACKAGEPATHTOKEN/g, packagePath) 1.167 + .replace(/PACKAGESIZETOKEN/g, packageSize) 1.168 + .replace(/NAMETOKEN/g, appName) 1.169 + .replace(/DEVELOPERTOKEN/g, developerName) 1.170 + .replace(/DEVELOPERURLTOKEN/g, developerUrl); 1.171 + return res; 1.172 +}