Tue, 06 Jan 2015 21:39:09 +0100
Conditionally force memory storage according to privacy.thirdparty.isolate;
This solves Tor bug #9701, complying with disk avoidance documented in
https://www.torproject.org/projects/torbrowser/design/#disk-avoidance.
1 /* -*- Mode: Java; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /* This Source Code Form is subject to the terms of the Mozilla Public
3 * License, v. 2.0. If a copy of the MPL was not distributed with this
4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6 var parser = new DOMParser();
7 var methodExpr = (new XPathEvaluator).createExpression("xsl:output/@method",
8 {
9 lookupNamespaceURI: function(aPrefix)
10 {
11 if (aPrefix == "xsl")
12 return "http://www.w3.org/1999/XSL/Transform";
13 return "";
14 }
15 });
17 const nsIWebProgListener = Components.interfaces.nsIWebProgressListener;
19 var runQueue =
20 {
21 mArray : new Array(),
22 push : function(aRunItem)
23 {
24 this.mArray.push(aRunItem);
25 },
26 observe : function(aSubject, aTopic, aData)
27 {
28 var item = this.mArray.shift();
29 if (item) {
30 item.run(this);
31 }
32 },
33 run : function()
34 {
35 this.observe(null,'','');
36 }
37 }
39 var itemCache =
40 {
41 mArray : new Array(),
42 getItem : function(aResource)
43 {
44 // Directory selected
45 if (kContUtils.IsSeq(runItem.prototype.kDatabase, aResource)) {
46 var aSeq = kContUtils.MakeSeq(runItem.prototype.kDatabase, aResource);
47 dump("sequence: "+aSeq+" with "+aSeq.GetCount()+" elements\n");
48 var child, children = aSeq.GetElements();
49 var m = 0, first;
50 while (children.hasMoreElements()) {
51 m += 1;
52 child = children.getNext();
53 child.QueryInterface(nsIRDFResource);
54 if (!first)
55 first = itemCache.getItem(child);
56 else
57 itemCache.getItem(child);
58 }
59 return first;
60 }
61 if (aResource.Value in this.mArray) {
62 return this.mArray[aResource.Value];
63 }
64 var retItem = new runItem(aResource);
65 this.mArray[aResource.Value] = retItem;
66 runQueue.push(retItem);
67 return retItem;
68 },
69 rerunItem : function(aResource, aObserver)
70 {
71 var anItem = new runItem(aResource);
72 this.mArray[aResource.Value] = anItem;
73 anItem.run(aObserver);
74 },
75 observe : function(aSubject, aTopic, aData)
76 {
77 this.mRun += 1;
78 if (aTopic == "success") {
79 if (aData == "yes") {
80 this.mGood += 1;
81 }
82 else {
83 this.mFalse +=1;
84 }
85 }
86 }
87 }
89 function runItem(aResource)
90 {
91 this.mResource = aResource;
92 // Directory selected
93 if (kContUtils.IsSeq(this.kDatabase,this.mResource)) {
94 var aSeq = kContUtils.MakeSeq(this.kDatabase,this.mResource);
95 dump("THIS SHOULDN'T HAPPEN\n");
96 var child, children = aSeq.GetElements();
97 var m = 0;
98 while (children.hasMoreElements()) {
99 m += 1;
100 child = children.getNext();
101 child.QueryInterface(nsIRDFResource);
102 itemCache.getItem(child);
103 }
104 }
105 }
107 runItem.prototype =
108 {
109 // RDF resource associated with this test
110 mResource : null,
111 // XML documents for the XSLT transformation
112 mSourceDoc : null,
113 mStyleDoc : null,
114 mResDoc : null,
115 // XML or plaintext document for the reference
116 mRefDoc : null,
117 // bitfield signaling the loaded documents
118 mLoaded : 0,
119 kSource : 1,
120 kStyle : 2,
121 kReference : 4,
122 // a observer, potential argument to run()
123 mObserver : null,
124 mSuccess : null,
125 mMethod : 'xml',
126 // XSLTProcessor, shared by the instances
127 kProcessor : new XSLTProcessor(),
128 kXalan : kStandardURL.createInstance(nsIURL),
129 kDatabase : null,
130 kObservers : new Array(),
132 run : function(aObserver)
133 {
134 if (aObserver && typeof(aObserver)=='function' ||
135 (typeof(aObserver)=='object' &&
136 typeof(aObserver.observe)=='function')) {
137 this.mObserver=aObserver;
138 }
139 var name = this.kDatabase.GetTarget(this.mResource, krTypeName, true);
140 if (name) {
141 var cat = this.kDatabase.GetTarget(this.mResource, krTypeCat, true);
142 var path = this.kDatabase.GetTarget(this.mResource, krTypePath, true);
143 cat = cat.QueryInterface(nsIRDFLiteral);
144 name = name.QueryInterface(nsIRDFLiteral);
145 path = path.QueryInterface(nsIRDFLiteral);
146 var xalan_fl = this.kXalan.resolve(cat.Value+"/"+path.Value);
147 var xalan_ref = this.kXalan.resolve(cat.Value+"-gold/"+path.Value);
148 this.mRefURL =
149 this.kXalan.resolve(cat.Value + "-gold/" + path.Value + ".out");
150 dump(name.Value+" links to "+xalan_fl+"\n");
151 }
152 // Directory selected
153 if (kContUtils.IsSeq(this.kDatabase,this.mResource)) {
154 return;
155 var aSeq = kContUtils.MakeSeq(this.kDatabase,this.mResource);
156 dump("sequence: "+aSeq+" with "+aSeq.GetCount()+" elements\n");
157 var child, children = aSeq.GetElements();
158 var m = 0;
159 while (children.hasMoreElements()) {
160 m += 1;
161 child = children.getNext();
162 child.QueryInterface(nsIRDFResource);
163 }
164 }
165 this.mSourceDoc = document.implementation.createDocument('', '', null);
166 this.mSourceDoc.addEventListener("load",this.onload(1),false);
167 this.mSourceDoc.load(xalan_fl+".xml");
168 this.mStyleDoc = document.implementation.createDocument('', '', null);
169 this.mStyleDoc.addEventListener("load",this.styleLoaded(),false);
170 this.mStyleDoc.load(xalan_fl+".xsl");
171 },
173 // nsIWebProgressListener
174 QueryInterface: function(aIID)
175 {
176 return this;
177 },
178 onStateChange: function(aProg, aRequest, aFlags, aStatus)
179 {
180 if ((aFlags & nsIWebProgListener.STATE_STOP) &&
181 (aFlags & nsIWebProgListener.STATE_IS_DOCUMENT)) {
182 aProg.removeProgressListener(this);
183 this.mRefDoc = document.getElementById('hiddenHtml').contentDocument;
184 this.fileLoaded(4);
185 }
186 },
187 onProgressChange: function(aProg, b,c,d,e,f)
188 {
189 },
190 onLocationChange: function(aProg, aRequest, aURI, aFlags)
191 {
192 },
193 onStatusChange: function(aProg, aRequest, aStatus, aMessage)
194 {
195 },
196 onSecurityChange: function(aWebProgress, aRequest, aState)
197 {
198 },
200 // onload handler helper
201 onload : function(file)
202 {
203 var self = this;
204 return function(e)
205 {
206 return self.fileLoaded(file);
207 };
208 },
210 styleLoaded : function()
211 {
212 var self = this;
213 return function(e)
214 {
215 return self.styleLoadedHelper();
216 };
217 },
218 styleLoadedHelper : function()
219 {
220 var method = methodExpr.evaluate(this.mStyleDoc.documentElement, 2,
221 null).stringValue;
222 var refContent;
223 if (!method) {
224 // implicit method, guess from result
225 refContent = this.loadTextFile(this.mRefURL);
226 if (refContent.match(/^\s*<html/gi)) {
227 method = 'html';
228 }
229 else {
230 method = 'xml';
231 }
232 }
233 this.mMethod = method;
235 switch (method) {
236 case 'xml':
237 if (!refContent) {
238 refContent = this.loadTextFile(this.mRefURL);
239 }
240 this.mRefDoc = parser.parseFromString(refContent, 'application/xml');
241 this.mLoaded += 4;
242 break;
243 case 'html':
244 view.loadHtml(this.mRefURL, this);
245 break;
246 case 'text':
247 if (!refContent) {
248 refContent = this.loadTextFile(this.mRefURL);
249 }
250 const ns = 'http://www.mozilla.org/TransforMiix';
251 const qn = 'transformiix:result';
252 this.mRefDoc =
253 document.implementation.createDocument(ns, qn, null);
254 var txt = this.mRefDoc.createTextNode(refContent);
255 this.mRefDoc.documentElement.appendChild(txt);
256 this.mLoaded += 4;
257 break;
258 default:
259 throw "unkown XSLT output method";
260 }
261 this.fileLoaded(2)
262 },
264 fileLoaded : function(mask)
265 {
266 this.mLoaded += mask;
267 if (this.mLoaded < 7) {
268 return;
269 }
270 this.doTransform();
271 },
273 doTransform : function()
274 {
275 this.kProcessor.reset();
276 try {
277 this.kProcessor.importStylesheet(this.mStyleDoc);
278 this.mResDoc =
279 this.kProcessor.transformToDocument(this.mSourceDoc);
280 this.mRefDoc.normalize();
281 isGood = DiffDOM(this.mResDoc.documentElement,
282 this.mRefDoc.documentElement,
283 this.mMethod == 'html');
284 } catch (e) {
285 isGood = false;
286 };
287 dump("This succeeded. "+isGood+"\n");
288 isGood = isGood.toString();
289 for (var i=0; i<this.kObservers.length; i++) {
290 var aObs = this.kObservers[i];
291 if (typeof(aObs)=='object' && typeof(aObs.observe)=='function') {
292 aObs.observe(this.mResource, 'success', isGood);
293 }
294 else if (typeof(aObs)=='function') {
295 aObs(this.mResource, 'success', isGood);
296 }
297 }
298 if (this.mObserver) {
299 if (typeof(this.mObserver)=='object') {
300 this.mObserver.observe(this.mResource, 'success', isGood);
301 }
302 else {
303 this.mObserver(this.mResource, 'success', isGood);
304 }
305 }
306 },
308 loadTextFile : function(url)
309 {
310 var serv = Components.classes[IOSERVICE_CTRID].
311 getService(nsIIOService);
312 if (!serv) {
313 throw Components.results.ERR_FAILURE;
314 }
315 var chan = serv.newChannel(url, null, null);
316 var instream = doCreate(SIS_CTRID, nsISIS);
317 instream.init(chan.open());
319 return instream.read(instream.available());
320 }
321 }
323 runItem.prototype.kXalan.QueryInterface(nsIStandardURL);
325 var cmdTestController =
326 {
327 supportsCommand: function(aCommand)
328 {
329 switch(aCommand) {
330 case 'cmd_tst_run':
331 case 'cmd_tst_runall':
332 return true;
333 default:
334 }
335 return false;
336 },
337 isCommandEnabled: function(aCommand)
338 {
339 return this.supportsCommand(aCommand);
340 },
341 doCommand: function(aCommand)
342 {
343 switch(aCommand) {
344 case 'cmd_tst_run':
345 dump("cmd_tst_run\n");
346 break;
347 case 'cmd_tst_runall':
348 dump("cmd_tst_runall\n");
349 var tst_run = document.getElementById('cmd_tst_run');
350 tst_run.doCommand();
351 default:
352 }
353 }
354 };
356 registerController(cmdTestController);