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