Sat, 03 Jan 2015 20:18:00 +0100
Conditionally enable double key logic according to:
private browsing mode or privacy.thirdparty.isolate preference and
implement in GetCookieStringCommon and FindCookie where it counts...
With some reservations of how to convince FindCookie users to test
condition and pass a nullptr when disabling double key logic.
1 var gBasePath = "tests/dom/apps/tests/";
2 var gAppTemplatePath = "tests/dom/apps/tests/file_app.template.html";
3 var gAppcacheTemplatePath = "tests/dom/apps/tests/file_cached_app.template.appcache";
4 var gDefaultIcon = "default_icon";
6 function makeResource(templatePath, version, apptype) {
7 let icon = getState('icon') || gDefaultIcon;
8 var res = readTemplate(templatePath).replace(/VERSIONTOKEN/g, version)
9 .replace(/APPTYPETOKEN/g, apptype)
10 .replace(/ICONTOKEN/g, icon);
12 // Hack - This is necessary to make the tests pass, but hbambas says it
13 // shouldn't be necessary. Comment it out and watch the tests fail.
14 if (templatePath == gAppTemplatePath && apptype == 'cached') {
15 res = res.replace('<html>', '<html manifest="file_app.sjs?apptype=cached&getappcache=true">');
16 }
18 return res;
19 }
21 function handleRequest(request, response) {
22 var query = getQuery(request);
24 // If this is a version update, update state and return.
25 if ("setVersion" in query) {
26 setState('version', query.setVersion);
27 response.setHeader("Content-Type", "text/html", false);
28 response.setHeader("Access-Control-Allow-Origin", "*", false);
29 response.write('OK');
30 return;
31 }
33 if ("setIcon" in query) {
34 let icon = query.setIcon;
35 if (icon === 'DEFAULT') {
36 icon = null;
37 }
39 setState('icon', icon);
41 response.setHeader("Content-Type", "text/html", false);
42 response.setHeader("Access-Control-Allow-Origin", "*", false);
43 response.write('OK');
44 return;
45 }
47 // Get the app type.
48 var apptype = query.apptype;
49 if (apptype != 'hosted' && apptype != 'cached')
50 throw "Invalid app type: " + apptype;
52 // Get the version from server state and handle the etag.
53 var version = Number(getState('version'));
54 var etag = getEtag(request, version);
55 dump("Server Etag: " + etag + "\n");
57 if (etagMatches(request, etag)) {
58 dump("Etags Match. Sending 304\n");
59 response.setStatusLine(request.httpVersion, "304", "Not Modified");
60 return;
61 }
63 response.setHeader("Etag", etag, false);
64 if (request.hasHeader("If-None-Match"))
65 dump("Client Etag: " + request.getHeader("If-None-Match") + "\n");
66 else
67 dump("No Client Etag\n");
69 // Check if we're generating a webapp manifest.
70 if ('getmanifest' in query) {
71 var template = gBasePath + 'file_' + apptype + '_app.template.webapp';
72 response.setHeader("Content-Type", "application/x-web-app-manifest+json", false);
73 response.write(makeResource(template, version, apptype));
74 return;
75 }
77 // If apptype==cached, we might be generating the appcache manifest.
78 //
79 // NB: Among other reasons, we use the same sjs file here so that the version
80 // state is shared.
81 if (apptype == 'cached' && 'getappcache' in query) {
82 response.setHeader("Content-Type", "text/cache-manifest", false);
83 response.write(makeResource(gAppcacheTemplatePath, version, apptype));
84 return;
85 }
87 // Generate the app.
88 response.setHeader("Content-Type", "text/html", false);
89 response.write(makeResource(gAppTemplatePath, version, apptype));
90 }
92 function getEtag(request, version) {
93 return request.queryString.replace(/&/g, '-').replace(/=/g, '-') + '-' + version;
94 }
96 function etagMatches(request, etag) {
97 return request.hasHeader("If-None-Match") && request.getHeader("If-None-Match") == etag;
98 }
100 function getQuery(request) {
101 var query = {};
102 request.queryString.split('&').forEach(function (val) {
103 var [name, value] = val.split('=');
104 query[name] = unescape(value);
105 });
106 return query;
107 }
109 // Copy-pasted incantations. There ought to be a better way to synchronously read
110 // a file into a string, but I guess we're trying to discourage that.
111 function readTemplate(path) {
112 var file = Components.classes["@mozilla.org/file/directory_service;1"].
113 getService(Components.interfaces.nsIProperties).
114 get("CurWorkD", Components.interfaces.nsILocalFile);
115 var fis = Components.classes['@mozilla.org/network/file-input-stream;1'].
116 createInstance(Components.interfaces.nsIFileInputStream);
117 var cis = Components.classes["@mozilla.org/intl/converter-input-stream;1"].
118 createInstance(Components.interfaces.nsIConverterInputStream);
119 var split = path.split("/");
120 for(var i = 0; i < split.length; ++i) {
121 file.append(split[i]);
122 }
123 fis.init(file, -1, -1, false);
124 cis.init(fis, "UTF-8", 0, 0);
126 var data = "";
127 let (str = {}) {
128 let read = 0;
129 do {
130 read = cis.readString(0xffffffff, str); // read as much as we can and put it in str.value
131 data += str.value;
132 } while (read != 0);
133 }
134 cis.close();
135 return data;
136 }