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 | <?xml version="1.0"?> |
michael@0 | 2 | <?xml-stylesheet type="text/css" href="chrome://global/skin"?> |
michael@0 | 3 | <?xml-stylesheet type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css"?> |
michael@0 | 4 | <!-- |
michael@0 | 5 | https://bugzilla.mozilla.org/show_bug.cgi?id=741267 |
michael@0 | 6 | --> |
michael@0 | 7 | <window title="Mozilla Bug 741267" |
michael@0 | 8 | xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"> |
michael@0 | 9 | <script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"/> |
michael@0 | 10 | |
michael@0 | 11 | <iframe id="t"></iframe> |
michael@0 | 12 | |
michael@0 | 13 | <!-- test results are displayed in the html:body --> |
michael@0 | 14 | <body xmlns="http://www.w3.org/1999/xhtml"> |
michael@0 | 15 | <a href="https://bugzilla.mozilla.org/show_bug.cgi?id=741267" |
michael@0 | 16 | target="_blank">Mozilla Bug 741267</a> |
michael@0 | 17 | </body> |
michael@0 | 18 | |
michael@0 | 19 | <!-- test code goes here --> |
michael@0 | 20 | <script type="application/javascript"> |
michael@0 | 21 | <![CDATA[ |
michael@0 | 22 | |
michael@0 | 23 | /** Test for Bug 741267 **/ |
michael@0 | 24 | function isXrayWrapper(x) { |
michael@0 | 25 | return Components.utils.isXrayWrapper(x); |
michael@0 | 26 | } |
michael@0 | 27 | |
michael@0 | 28 | function doTest() { |
michael@0 | 29 | var win = $("t").contentWindow; |
michael@0 | 30 | var sandbox = Components.utils.Sandbox(win, { sandboxPrototype: win }); |
michael@0 | 31 | |
michael@0 | 32 | is(sandbox._content, undefined, "_content does nothing over Xray"); |
michael@0 | 33 | |
michael@0 | 34 | try { |
michael@0 | 35 | var css = Components.utils.evalInSandbox("CSSStyleDeclaration", sandbox); |
michael@0 | 36 | is(css.prototype, "[object XrayWrapper [object CSSStyleDeclarationPrototype]]", "'CSSStyleDeclaration.prototype' in a sandbox should return the CSSStyleDeclaration interface prototype object"); |
michael@0 | 37 | } catch (e) { |
michael@0 | 38 | ok(false, "'CSSStyleDeclaration' shouldn't throw in a sandbox"); |
michael@0 | 39 | } |
michael@0 | 40 | try { |
michael@0 | 41 | var et = Components.utils.evalInSandbox("EventTarget", sandbox); |
michael@0 | 42 | ok(et, "'EventTarget' in a sandbox should return the EventTarget interface object"); |
michael@0 | 43 | ok(isXrayWrapper(et), "Getting an interface object on an Xray wrapper should return an Xray wrapper"); |
michael@0 | 44 | } catch (e) { |
michael@0 | 45 | ok(false, "'EventTarget' shouldn't throw in a sandbox"); |
michael@0 | 46 | } |
michael@0 | 47 | try { |
michael@0 | 48 | var xhr = Components.utils.evalInSandbox("XMLHttpRequest.prototype", sandbox); |
michael@0 | 49 | ok(xhr, "'XMLHttpRequest.prototype' in a sandbox should return the XMLHttpRequest interface prototype object"); |
michael@0 | 50 | ok(isXrayWrapper(xhr), "Getting an interface prototype object on an Xray wrapper should return an Xray wrapper"); |
michael@0 | 51 | ok(isXrayWrapper(xhr.constructor), "Getting the constructor property on an Xray wrapper of an interface prototype object should return an Xray wrapper"); |
michael@0 | 52 | isnot(Object.getOwnPropertyDescriptor(xhr, "send"), undefined, |
michael@0 | 53 | "We should claim to have a send() method"); |
michael@0 | 54 | isnot(Object.keys(xhr).indexOf("responseType"), -1, |
michael@0 | 55 | "We should claim to have a responseType property"); |
michael@0 | 56 | isnot(Object.getOwnPropertyNames(xhr).indexOf("open"), -1, |
michael@0 | 57 | "We should claim to have an open() method"); |
michael@0 | 58 | isnot(Object.getOwnPropertyDescriptor(xhr, "constructor"), undefined, |
michael@0 | 59 | "We should claim to have a 'constructor' property"); |
michael@0 | 60 | } catch (e) { |
michael@0 | 61 | ok(false, "'XMLHttpRequest.prototype' shouldn't throw in a sandbox"); |
michael@0 | 62 | } |
michael@0 | 63 | try { |
michael@0 | 64 | var img = Components.utils.evalInSandbox("Image.prototype", sandbox); |
michael@0 | 65 | ok(img, "'Image.prototype' in a sandbox should return the interface prototype object"); |
michael@0 | 66 | ok(isXrayWrapper(img), "Getting an interface prototype object on an Xray wrapper should return an Xray wrapper"); |
michael@0 | 67 | } catch (e) { |
michael@0 | 68 | ok(false, "'Image.prototype' shouldn't throw in a sandbox"); |
michael@0 | 69 | } |
michael@0 | 70 | try { |
michael@0 | 71 | var xhr = Components.utils.evalInSandbox("XMLHttpRequest", sandbox); |
michael@0 | 72 | xhr.prototype = false; |
michael@0 | 73 | } catch (e) { |
michael@0 | 74 | ok(true, "'XMLHttpRequest.prototype' should be readonly"); |
michael@0 | 75 | } |
michael@0 | 76 | try { |
michael@0 | 77 | var xhr = Components.utils.evalInSandbox("XMLHttpRequest", sandbox); |
michael@0 | 78 | delete xhr.prototype; |
michael@0 | 79 | } catch (e) { |
michael@0 | 80 | ok(true, "'XMLHttpRequest.prototype' should be permanent"); |
michael@0 | 81 | } |
michael@0 | 82 | try { |
michael@0 | 83 | var xhr = Components.utils.evalInSandbox("XMLHttpRequest.prototype", sandbox); |
michael@0 | 84 | xhr.constructor = "ok"; |
michael@0 | 85 | } catch (e) { |
michael@0 | 86 | is(xhr.constructor, "ok", "'XMLHttpRequest.prototype.constructor' should be writeable"); |
michael@0 | 87 | } |
michael@0 | 88 | try { |
michael@0 | 89 | var xhr = Components.utils.evalInSandbox("XMLHttpRequest.prototype", sandbox); |
michael@0 | 90 | delete xhr.constructor; |
michael@0 | 91 | } catch (e) { |
michael@0 | 92 | is(xhr.constructor, undefined, "'XMLHttpRequest.prototype.constructor' should be permanent"); |
michael@0 | 93 | } |
michael@0 | 94 | try { |
michael@0 | 95 | var xhr = Components.utils.evalInSandbox("XMLHttpRequest", sandbox); |
michael@0 | 96 | is(xhr, "[object XrayWrapper " + XMLHttpRequest + "]", "'XMLHttpRequest' in a sandbox should return the XMLHttpRequest interface object"); |
michael@0 | 97 | ok(isXrayWrapper(xhr.prototype), "Getting the prototype property on an Xray wrapper of an interface object should return an Xray wrapper"); |
michael@0 | 98 | isnot(Object.getOwnPropertyDescriptor(xhr, "UNSENT"), undefined, |
michael@0 | 99 | "We should claim to have an UNSENT constant"); |
michael@0 | 100 | isnot(Object.keys(xhr).indexOf("OPENED"), -1, |
michael@0 | 101 | "We should claim to have an OPENED constant"); |
michael@0 | 102 | isnot(Object.getOwnPropertyNames(xhr).indexOf("DONE"), -1, |
michael@0 | 103 | "We should claim to have a DONE constant"); |
michael@0 | 104 | isnot(Object.getOwnPropertyDescriptor(xhr, "prototype"), undefined, |
michael@0 | 105 | "We should claim to have 'prototype' property"); |
michael@0 | 106 | } catch (e) { |
michael@0 | 107 | ok(false, "'XMLHttpRequest' shouldn't throw in a sandbox"); |
michael@0 | 108 | } |
michael@0 | 109 | try { |
michael@0 | 110 | var xhr = Components.utils.evalInSandbox("new XMLHttpRequest()", sandbox); |
michael@0 | 111 | is("" + xhr, "[object XrayWrapper " + new XMLHttpRequest() + "]", "'XMLHttpRequest()' in a sandbox should create an XMLHttpRequest object"); |
michael@0 | 112 | } catch (e) { |
michael@0 | 113 | ok(false, "'new XMLHttpRequest()' shouldn't throw in a sandbox (1)"); |
michael@0 | 114 | } |
michael@0 | 115 | try { |
michael@0 | 116 | var xhr = Components.utils.evalInSandbox("XMLHttpRequest.prototype.toString = function () { return 'Failed'; }; new XMLHttpRequest();", sandbox); |
michael@0 | 117 | is(xhr.toString(), "[object XrayWrapper " + new XMLHttpRequest() + "]", "XMLHttpRequest.prototype.toString in the sandbox should not override the native toString behaviour"); |
michael@0 | 118 | } catch (e) { |
michael@0 | 119 | ok(false, "'new XMLHttpRequest()' shouldn't throw in a sandbox (2)"); |
michael@0 | 120 | } |
michael@0 | 121 | |
michael@0 | 122 | try { |
michael@0 | 123 | // have to run this test before document.defaultView.XMLHttpRequest |
michael@0 | 124 | // gets munged in the sandbox. |
michael@0 | 125 | var proto = Components.utils.evalInSandbox("XMLHttpRequest.prototype", sandbox); |
michael@0 | 126 | props = []; |
michael@0 | 127 | for (var i in proto) { |
michael@0 | 128 | props.push(i); |
michael@0 | 129 | } |
michael@0 | 130 | isnot(props.indexOf("dispatchEvent"), -1, |
michael@0 | 131 | "'dispatchEvent' property should be enumerable on XMLHttpRequest.prototype"); |
michael@0 | 132 | props = Object.getOwnPropertyNames(proto); |
michael@0 | 133 | is(props.indexOf("dispatchEvent"), -1, |
michael@0 | 134 | "'dispatchEvent' is not an own property on XMLHttpRequest.prototype; it's on EventTarget.prototype") |
michael@0 | 135 | } catch (e) { |
michael@0 | 136 | ok(false, "XMLHttpRequest.prototype manipulation via an Xray shouldn't throw" + e); |
michael@0 | 137 | } |
michael@0 | 138 | |
michael@0 | 139 | try { |
michael@0 | 140 | Components.utils.evalInSandbox("document.defaultView.XMLHttpRequest = function() {};", sandbox); |
michael@0 | 141 | var win = Components.utils.evalInSandbox("document.defaultView", sandbox); |
michael@0 | 142 | var xhr = new win.XMLHttpRequest(); |
michael@0 | 143 | is("" + xhr, "[object XrayWrapper " + new XMLHttpRequest() + "]", "'XMLHttpRequest()' in a sandbox should create an XMLHttpRequest object"); |
michael@0 | 144 | } catch (e) { |
michael@0 | 145 | ok(false, "'XMLHttpRequest()' shouldn't throw in a sandbox"); |
michael@0 | 146 | } |
michael@0 | 147 | try { |
michael@0 | 148 | var canvas = Components.utils.evalInSandbox("document.createElement('canvas').getContext('2d')", sandbox); |
michael@0 | 149 | is(canvas.DRAWWINDOW_DRAW_CARET, CanvasRenderingContext2D.DRAWWINDOW_DRAW_CARET, "Constants should be defined on DOM objects in a sandbox"); |
michael@0 | 150 | } catch (e) { |
michael@0 | 151 | ok(false, "'document.createElement('canvas').getContext('2D')' shouldn't throw in a sandbox"); |
michael@0 | 152 | } |
michael@0 | 153 | try { |
michael@0 | 154 | var classList = Components.utils.evalInSandbox("document.body.className = 'a b'; document.body.classList", sandbox); |
michael@0 | 155 | is(classList.toString(), "a b", "Stringifier should be called"); |
michael@0 | 156 | } catch (e) { |
michael@0 | 157 | ok(false, "'document.createElement('canvas').getContext('2D')' shouldn't throw in a sandbox"); |
michael@0 | 158 | } |
michael@0 | 159 | try { |
michael@0 | 160 | var ctx = Components.utils.evalInSandbox("var ctx = document.createElement('canvas').getContext('2d'); ctx.foopy = 5; ctx", sandbox); |
michael@0 | 161 | ok(!("foopy" in ctx), "We should have an Xray here"); |
michael@0 | 162 | var data = ctx.createImageData(1, 1); |
michael@0 | 163 | for (var i = 0; i < data.data.length; ++i) { |
michael@0 | 164 | // Watch out for premultiplied bits... just set all the alphas to 255 |
michael@0 | 165 | if (i % 4 == 3) { |
michael@0 | 166 | data.data[i] = 255; |
michael@0 | 167 | } else { |
michael@0 | 168 | data.data[i] = i; |
michael@0 | 169 | } |
michael@0 | 170 | } |
michael@0 | 171 | ctx.putImageData(data, 0, 0); |
michael@0 | 172 | var data2 = ctx.getImageData(0, 0, 1, 1); |
michael@0 | 173 | is(data2.data.length, data.data.length, "Lengths must match"); |
michael@0 | 174 | for (i = 0; i < data.data.length; ++i) |
michael@0 | 175 | is(data.data[i], data2.data[i], "Data at " + i + " should match"); |
michael@0 | 176 | } catch (e) { |
michael@0 | 177 | ok(false, "Imagedata manipulation via an Xray shouldn't throw " + e); |
michael@0 | 178 | } |
michael@0 | 179 | |
michael@0 | 180 | try { |
michael@0 | 181 | var list = Components.utils.evalInSandbox("document.getElementsByTagName('*')", sandbox); |
michael@0 | 182 | props = []; |
michael@0 | 183 | for (var i in list) { |
michael@0 | 184 | props.push(i); |
michael@0 | 185 | } |
michael@0 | 186 | is(props.indexOf("constructor"), -1, |
michael@0 | 187 | "'constructor' property should not be enumerable on list object"); |
michael@0 | 188 | props = Object.getOwnPropertyNames(list); |
michael@0 | 189 | is(props.indexOf("constructor"), -1, |
michael@0 | 190 | "'constructor' property should not be an own property name on list object"); |
michael@0 | 191 | } catch (e) { |
michael@0 | 192 | ok(false, "NodeList.prototype manipulation via an Xray shouldn't throw" + e); |
michael@0 | 193 | } |
michael@0 | 194 | |
michael@0 | 195 | try { |
michael@0 | 196 | var proto = Components.utils.evalInSandbox("NodeList.prototype", sandbox); |
michael@0 | 197 | props = []; |
michael@0 | 198 | for (var i in proto) { |
michael@0 | 199 | props.push(i); |
michael@0 | 200 | } |
michael@0 | 201 | is(props.indexOf("constructor"), -1, |
michael@0 | 202 | "'constructor' property should not be enumerable on proto directly"); |
michael@0 | 203 | props = Object.getOwnPropertyNames(proto); |
michael@0 | 204 | isnot(props.indexOf("constructor"), -1, |
michael@0 | 205 | "'constructor' property should be an own property name on proto"); |
michael@0 | 206 | } catch (e) { |
michael@0 | 207 | ok(false, "NodeList.prototype manipulation via an Xray shouldn't throw" + e); |
michael@0 | 208 | } |
michael@0 | 209 | |
michael@0 | 210 | try { |
michael@0 | 211 | var url = Components.utils.evalInSandbox("URL", sandbox); |
michael@0 | 212 | for (var i in url) { |
michael@0 | 213 | url[i]; |
michael@0 | 214 | } |
michael@0 | 215 | isnot(url.createObjectURL, undefined, "Should have a createObjectURL"); |
michael@0 | 216 | ok(true, "We didn't crash!"); |
michael@0 | 217 | } catch (e) { |
michael@0 | 218 | ok(false, "URL interface object manipulation via an Xray shouldn't throw" + e); |
michael@0 | 219 | } |
michael@0 | 220 | |
michael@0 | 221 | try { |
michael@0 | 222 | url.revokeObjectURL(""); |
michael@0 | 223 | } catch (e) { |
michael@0 | 224 | // Just testing whether revokeObjectURL crashes us |
michael@0 | 225 | } |
michael@0 | 226 | ok(true, "We didn't crash!"); |
michael@0 | 227 | |
michael@0 | 228 | // And now tests that don't use a window-associated sandbox |
michael@0 | 229 | sandbox = Components.utils.Sandbox(win.document.nodePrincipal, |
michael@0 | 230 | { sandboxPrototype: win }); |
michael@0 | 231 | try { |
michael@0 | 232 | var ws = Components.utils.evalInSandbox('var ws = new WebSocket("ws://example.org"); ws', sandbox); |
michael@0 | 233 | // Test that we actually got a WebSocket object, probably |
michael@0 | 234 | ok("bufferedAmount" in ws, "What is this object?"); |
michael@0 | 235 | } catch (e) { |
michael@0 | 236 | ok(false, "Should be able to create a WebSocket in a sandbox " + e); |
michael@0 | 237 | } |
michael@0 | 238 | try { |
michael@0 | 239 | var es = Components.utils.evalInSandbox('var es = new EventSource("about:blank"); es', sandbox); |
michael@0 | 240 | // Test that we actually got a EventSource object, probably |
michael@0 | 241 | is(es.url, "about:blank", "What is this object?"); |
michael@0 | 242 | } catch (e) { |
michael@0 | 243 | ok(false, "Should be able to create an EventSource in a sandbox " + e); |
michael@0 | 244 | } |
michael@0 | 245 | |
michael@0 | 246 | try { |
michael@0 | 247 | var nodeFilterIface = Components.utils.evalInSandbox( |
michael@0 | 248 | 'NodeFilter.myExpando = "FAIL"; NodeFilter', sandbox); |
michael@0 | 249 | is(nodeFilterIface.myExpando, undefined, |
michael@0 | 250 | "Should have Xrays for callback interface objects"); |
michael@0 | 251 | } catch (e) { |
michael@0 | 252 | ok(false, "Should be able to return NodeFilter from a sandbox " + e); |
michael@0 | 253 | } |
michael@0 | 254 | |
michael@0 | 255 | try { |
michael@0 | 256 | var eventCtor = Components.utils.evalInSandbox("Event", sandbox); |
michael@0 | 257 | var e = new eventCtor("test", { bubbles: true }); |
michael@0 | 258 | is(e.bubbles, true, "Dictionary argument should work"); |
michael@0 | 259 | } catch (e) { |
michael@0 | 260 | ok(false, "Should be able to construct my event " + e); |
michael@0 | 261 | } |
michael@0 | 262 | |
michael@0 | 263 | try { |
michael@0 | 264 | var elem = Components.utils.evalInSandbox('document.createElement("p")', sandbox); |
michael@0 | 265 | elem.expando = 5; |
michael@0 | 266 | elem.expando = 7; |
michael@0 | 267 | is(elem.expando, 7, "Should be able to set expandos on Xrays for DOM bindings"); |
michael@0 | 268 | var doc = Components.utils.evalInSandbox('document', sandbox); |
michael@0 | 269 | doc.expando = 5; |
michael@0 | 270 | doc.expando = 7; |
michael@0 | 271 | is(doc.expando, 7, "Should be able to set expandos on Xrays for DOM bindings with named properties"); |
michael@0 | 272 | } catch (e) { |
michael@0 | 273 | ok(false, "Setting expandos on Xrays shouldn't throw " + e); |
michael@0 | 274 | } |
michael@0 | 275 | |
michael@0 | 276 | SimpleTest.finish(); |
michael@0 | 277 | } |
michael@0 | 278 | |
michael@0 | 279 | SimpleTest.waitForExplicitFinish(); |
michael@0 | 280 | addLoadEvent(doTest); |
michael@0 | 281 | ]]> |
michael@0 | 282 | </script> |
michael@0 | 283 | </window> |