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