/toolkit/mozapps/update/test/chrome/update.sjs

http://github.com/zpao/v8monkey · Unknown · 262 lines · 238 code · 24 blank · 0 comment · 0 complexity · 05af4999b0e9e43886f2a2f26e368888 MD5 · raw file

  1. /* Any copyright is dedicated to the Public Domain.
  2. * http://creativecommons.org/publicdomain/zero/1.0/
  3. */
  4. /**
  5. * Server side http server script for application update tests.
  6. *
  7. * !IMPORTANT - Since xpcshell used by the http server is launched with -v 170
  8. * this file must not use features greater than JavaScript 1.7.
  9. */
  10. const AUS_Cc = Components.classes;
  11. const AUS_Ci = Components.interfaces;
  12. #include ../sharedUpdateXML.js
  13. const URL_HOST = "http://example.com/";
  14. const URL_PATH = "chrome/toolkit/mozapps/update/test/chrome/";
  15. const URL_UPDATE = URL_HOST + URL_PATH + "update.sjs";
  16. const SERVICE_URL = URL_HOST + URL_PATH + FILE_SIMPLE_MAR;
  17. const SLOW_MAR_DOWNLOAD_INTERVAL = 100;
  18. var gTimer;
  19. function handleRequest(aRequest, aResponse) {
  20. var params = { };
  21. if (aRequest.queryString)
  22. params = parseQueryString(aRequest.queryString);
  23. var statusCode = params.statusCode ? parseInt(params.statusCode) : 200;
  24. var statusReason = params.statusReason ? params.statusReason : "OK";
  25. aResponse.setStatusLine(aRequest.httpVersion, statusCode, statusReason);
  26. aResponse.setHeader("Cache-Control", "no-cache", false);
  27. if (params.addonID) {
  28. aResponse.write(getUpdateRDF(params));
  29. return;
  30. }
  31. // When a mar download is started by the update service it can finish
  32. // downloading before the ui has loaded. By specifying a serviceURL for the
  33. // update patch that points to this file and has a slowDownloadMar param the
  34. // mar will be downloaded asynchronously which will allow the ui to load
  35. // before the download completes.
  36. if (params.slowDownloadMar) {
  37. aResponse.processAsync();
  38. aResponse.setHeader("Content-Type", "binary/octet-stream");
  39. aResponse.setHeader("Content-Length", SIZE_SIMPLE_MAR);
  40. var marFile = AUS_Cc["@mozilla.org/file/directory_service;1"].
  41. getService(AUS_Ci.nsIProperties).
  42. get("CurWorkD", AUS_Ci.nsILocalFile);
  43. var path = URL_PATH + FILE_SIMPLE_MAR;
  44. var pathParts = path.split("/");
  45. for(var i = 0; i < pathParts.length; ++i)
  46. marFile.append(pathParts[i]);
  47. var contents = readFileBytes(marFile);
  48. gTimer = AUS_Cc["@mozilla.org/timer;1"].
  49. createInstance(AUS_Ci.nsITimer);
  50. gTimer.initWithCallback(function(aTimer) {
  51. aResponse.write(contents);
  52. aResponse.finish();
  53. }, SLOW_MAR_DOWNLOAD_INTERVAL, AUS_Ci.nsITimer.TYPE_ONE_SHOT);
  54. return;
  55. }
  56. if (params.uiURL) {
  57. var remoteType = "";
  58. if (!params.remoteNoTypeAttr &&
  59. (params.uiURL == "BILLBOARD" || params.uiURL == "LICENSE")) {
  60. remoteType = " " + params.uiURL.toLowerCase() + "=\"1\"";
  61. }
  62. aResponse.write("<html><head><meta http-equiv=\"content-type\" content=" +
  63. "\"text/html; charset=utf-8\"></head><body" +
  64. remoteType + ">" + params.uiURL +
  65. "<br><br>this is a test mar that will not affect your " +
  66. "build.</body></html>");
  67. return;
  68. }
  69. if (params.xmlMalformed) {
  70. aResponse.write("xml error");
  71. return;
  72. }
  73. if (params.noUpdates) {
  74. aResponse.write(getRemoteUpdatesXMLString(""));
  75. return;
  76. }
  77. var hash;
  78. var patches = "";
  79. if (!params.partialPatchOnly) {
  80. hash = SHA512_HASH_SIMPLE_MAR + (params.invalidCompleteHash ? "e" : "");
  81. patches += getRemotePatchString("complete", SERVICE_URL, "SHA512",
  82. hash, SIZE_SIMPLE_MAR);
  83. }
  84. if (!params.completePatchOnly) {
  85. hash = SHA512_HASH_SIMPLE_MAR + (params.invalidPartialHash ? "e" : "");
  86. patches += getRemotePatchString("partial", SERVICE_URL, "SHA512",
  87. hash, SIZE_SIMPLE_MAR);
  88. }
  89. var type = params.type ? params.type : "major";
  90. var name = params.name ? params.name : "App Update Test";
  91. var appVersion = params.appVersion ? params.appVersion : "99.9";
  92. var displayVersion = params.displayVersion ? params.displayVersion
  93. : "version " + appVersion;
  94. var platformVersion = params.platformVersion ? params.platformVersion : "99.8";
  95. var buildID = params.buildID ? params.buildID : "01234567890123";
  96. // XXXrstrong - not specifying a detailsURL will cause a leak due to bug 470244
  97. // var detailsURL = params.showDetails ? URL_UPDATE + "?uiURL=DETAILS" : null;
  98. var detailsURL = URL_UPDATE + "?uiURL=DETAILS";
  99. var billboardURL = params.showBillboard ? URL_UPDATE + "?uiURL=BILLBOARD" : null;
  100. if (billboardURL && params.remoteNoTypeAttr)
  101. billboardURL += "&amp;remoteNoTypeAttr=1";
  102. if (params.billboard404)
  103. billboardURL = URL_HOST + URL_PATH + "missing.html";
  104. var licenseURL = params.showLicense ? URL_UPDATE + "?uiURL=LICENSE" : null;
  105. if (licenseURL && params.remoteNoTypeAttr)
  106. licenseURL += "&amp;remoteNoTypeAttr=1";
  107. if (params.license404)
  108. licenseURL = URL_HOST + URL_PATH + "missing.html";
  109. var showPrompt = params.showPrompt ? "true" : null;
  110. var showNever = params.showNever ? "true" : null;
  111. var showSurvey = params.showSurvey ? "true" : null;
  112. // For testing the deprecated update xml format
  113. if (params.oldFormat) {
  114. appVersion = null;
  115. displayVersion = null;
  116. billboardURL = null;
  117. showPrompt = null;
  118. showNever = null;
  119. showSurvey = null;
  120. detailsURL = URL_UPDATE + "?uiURL=BILLBOARD";
  121. if (params.remoteNoTypeAttr)
  122. detailsURL += "&amp;remoteNoTypeAttr=1";
  123. var extensionVersion = params.appVersion ? params.appVersion : "99.9";
  124. var version = params.displayVersion ? params.displayVersion
  125. : "version " + extensionVersion;
  126. }
  127. var updates = getRemoteUpdateString(patches, type, "App Update Test",
  128. displayVersion, appVersion,
  129. platformVersion, buildID, detailsURL,
  130. billboardURL, licenseURL, showPrompt,
  131. showNever, showSurvey, version,
  132. extensionVersion);
  133. aResponse.write(getRemoteUpdatesXMLString(updates));
  134. }
  135. /**
  136. * Helper function to create a JS object representing the url parameters from
  137. * the request's queryString.
  138. *
  139. * @param aQueryString
  140. * The request's query string.
  141. * @return A JS object representing the url parameters from the request's
  142. * queryString.
  143. */
  144. function parseQueryString(aQueryString) {
  145. var paramArray = aQueryString.split("&");
  146. var regex = /^([^=]+)=(.*)$/;
  147. var params = {};
  148. for (var i = 0, sz = paramArray.length; i < sz; i++) {
  149. var match = regex.exec(paramArray[i]);
  150. if (!match)
  151. throw "Bad parameter in queryString! '" + paramArray[i] + "'";
  152. params[decodeURIComponent(match[1])] = decodeURIComponent(match[2]);
  153. }
  154. return params;
  155. }
  156. /**
  157. * Helper function to gets the string representation of the contents of the
  158. * add-on's update manifest file.
  159. *
  160. * @param aParams
  161. * A JS object representing the url parameters from the request's
  162. * queryString.
  163. * @return A string representation of the contents of the add-on's update
  164. * manifest file.
  165. */
  166. function getUpdateRDF(aParams) {
  167. var addonVersion;
  168. var addonID = aParams.addonID;
  169. var addonUpdateType = addonID.split("_")[0];
  170. var maxVersion = aParams.platformVersion;
  171. switch (addonUpdateType) {
  172. case "updatecompatibility":
  173. // Use "1.0" for the add-on version for the compatibility update case since
  174. // the tests create all add-ons with "1.0" for the version.
  175. addonVersion = "1.0";
  176. break;
  177. case "updateversion":
  178. // Use "2.0" for the add-on version for the version update case since the
  179. // tests create all add-ons with "1.0" for the version.
  180. addonVersion = "2.0";
  181. break;
  182. default:
  183. return "<?xml version=\"1.0\"?>\n" +
  184. "<RDF:RDF xmlns:RDF=\"http://www.w3.org/1999/02/22-rdf-syntax-ns#\" " +
  185. " xmlns:em=\"http://www.mozilla.org/2004/em-rdf#\">\n" +
  186. "</RDF:RDF>\n";
  187. }
  188. return "<?xml version=\"1.0\"?>\n" +
  189. "<RDF:RDF xmlns:RDF=\"http://www.w3.org/1999/02/22-rdf-syntax-ns#\" " +
  190. " xmlns:em=\"http://www.mozilla.org/2004/em-rdf#\">\n" +
  191. " <RDF:Description about=\"urn:mozilla:extension:" + addonID + "\">\n" +
  192. " <em:updates>\n" +
  193. " <RDF:Seq>\n" +
  194. " <RDF:li resource=\"urn:mozilla:extension:" + addonID + ":" + addonVersion + "\"/>\n" +
  195. " </RDF:Seq>\n" +
  196. " </em:updates>\n" +
  197. " </RDF:Description>\n" +
  198. " <RDF:Description about=\"urn:mozilla:extension:" + addonID + ":" + addonVersion + "\">\n" +
  199. " <em:version>" + addonVersion + "</em:version>\n" +
  200. " <em:targetApplication>\n" +
  201. " <RDF:Description>\n" +
  202. " <em:id>toolkit@mozilla.org</em:id>\n" +
  203. " <em:minVersion>0</em:minVersion>\n" +
  204. " <em:maxVersion>" + maxVersion + "</em:maxVersion>\n" +
  205. " <em:updateLink>" + URL_HOST + URL_PATH + "</em:updateLink>\n" +
  206. " <em:updateHash>sha256:0</em:updateHash>\n" +
  207. " </RDF:Description>\n" +
  208. " </em:targetApplication>\n" +
  209. " </RDF:Description>\n" +
  210. "</RDF:RDF>\n";
  211. }
  212. /**
  213. * Reads the binary contents of a file and returns it as a string.
  214. *
  215. * @param aFile
  216. * The file to read from.
  217. * @return The contents of the file as a string.
  218. */
  219. function readFileBytes(aFile) {
  220. var fis = AUS_Cc["@mozilla.org/network/file-input-stream;1"].
  221. createInstance(AUS_Ci.nsIFileInputStream);
  222. fis.init(aFile, -1, -1, false);
  223. var bis = AUS_Cc["@mozilla.org/binaryinputstream;1"].
  224. createInstance(AUS_Ci.nsIBinaryInputStream);
  225. bis.setInputStream(fis);
  226. var data = [];
  227. var count = fis.available();
  228. while (count > 0) {
  229. var bytes = bis.readByteArray(Math.min(65535, count));
  230. data.push(String.fromCharCode.apply(null, bytes));
  231. count -= bytes.length;
  232. if (bytes.length == 0)
  233. throw "Nothing read from input stream!";
  234. }
  235. data.join('');
  236. fis.close();
  237. return data.toString();
  238. }