test_exportFunction.js (5489B)
1 function run_test() { 2 var epsb = new Cu.Sandbox(["http://example.com", "http://example.org"], { wantExportHelpers: true }); 3 var subsb = new Cu.Sandbox("http://example.com", { wantGlobalProperties: ["XMLHttpRequest"] }); 4 var subsb2 = new Cu.Sandbox("http://example.com", { wantGlobalProperties: ["XMLHttpRequest"] }); 5 var xorigsb = new Cu.Sandbox("http://test.com", { wantGlobalProperties: ["XMLHttpRequest"] }); 6 7 epsb.subsb = subsb; 8 epsb.xorigsb = xorigsb; 9 epsb.ok = ok; 10 epsb.equal = equal; 11 subsb.ok = ok; 12 subsb.equal = equal; 13 14 // Exporting should work if prinicipal of the source sandbox 15 // subsumes the principal of the target sandbox. 16 Cu.evalInSandbox("(" + function() { 17 var wasCalled = false; 18 this.funToExport = function(expectedThis, a, obj, native, mixed, callback) { 19 equal(arguments.callee.length, 6); 20 equal(a, 42); 21 equal(obj, subsb.tobecloned); 22 equal(obj.cloned, "cloned"); 23 equal(native, subsb.native); 24 equal(expectedThis, this); 25 equal(mixed.xrayed, subsb.xrayed); 26 equal(mixed.xrayed2, subsb.xrayed2); 27 if (typeof callback == 'function') { 28 equal(typeof subsb.callback, 'function'); 29 equal(callback, subsb.callback); 30 callback(); 31 } 32 wasCalled = true; 33 }; 34 this.checkIfCalled = function() { 35 ok(wasCalled); 36 wasCalled = false; 37 } 38 exportFunction(funToExport, subsb, { defineAs: "imported", allowCallbacks: true }); 39 exportFunction((x) => x, subsb, { defineAs: "echoAllowXO", allowCallbacks: true, allowCrossOriginArguments: true }); 40 }.toSource() + ")()", epsb); 41 42 subsb.xrayed = Cu.evalInSandbox("(" + function () { 43 return new XMLHttpRequest(); 44 }.toSource() + ")()", subsb2); 45 46 // Exported function should be able to be call from the 47 // target sandbox. Native arguments should be just wrapped 48 // every other argument should be cloned. 49 Cu.evalInSandbox("(" + function () { 50 native = new XMLHttpRequest(); 51 xrayed2 = XPCNativeWrapper(new XMLHttpRequest()); 52 mixed = { xrayed: xrayed, xrayed2: xrayed2 }; 53 tobecloned = { cloned: "cloned" }; 54 invokedCallback = false; 55 callback = function() { invokedCallback = true; }; 56 imported(this, 42, tobecloned, native, mixed, callback); 57 equal(imported.length, 6); 58 ok(invokedCallback); 59 }.toSource() + ")()", subsb); 60 61 // Invoking an exported function with cross-origin arguments should throw. 62 subsb.xoNative = Cu.evalInSandbox('new XMLHttpRequest()', xorigsb); 63 try { 64 Cu.evalInSandbox('imported(this, xoNative)', subsb); 65 Assert.ok(false); 66 } catch (e) { 67 Assert.ok(/denied|insecure/.test(e)); 68 } 69 70 // Callers can opt-out of the above. 71 subsb.xoNative = Cu.evalInSandbox('new XMLHttpRequest()', xorigsb); 72 try { 73 Assert.equal(Cu.evalInSandbox('echoAllowXO(xoNative)', subsb), subsb.xoNative); 74 Assert.ok(true); 75 } catch (e) { 76 Assert.ok(false); 77 } 78 79 // Apply should work and |this| should carry over appropriately. 80 Cu.evalInSandbox("(" + function() { 81 var someThis = {}; 82 imported.apply(someThis, [someThis, 42, tobecloned, native, mixed]); 83 }.toSource() + ")()", subsb); 84 85 Cu.evalInSandbox("(" + function() { 86 checkIfCalled(); 87 }.toSource() + ")()", epsb); 88 89 // Exporting should throw if principal of the source sandbox does 90 // not subsume the principal of the target. 91 Cu.evalInSandbox("(" + function() { 92 try{ 93 exportFunction(function() {}, this.xorigsb, { defineAs: "denied" }); 94 ok(false); 95 } catch (e) { 96 ok(e.toString().indexOf('Permission denied') > -1); 97 } 98 }.toSource() + ")()", epsb); 99 100 // Exporting should throw if the principal of the source sandbox does 101 // not subsume the principal of the function. 102 epsb.xo_function = new xorigsb.Function(); 103 Cu.evalInSandbox("(" + function() { 104 try{ 105 exportFunction(xo_function, this.subsb, { defineAs: "denied" }); 106 ok(false); 107 } catch (e) { 108 dump('Exception: ' + e); 109 ok(e.toString().indexOf('Permission denied') > -1); 110 } 111 }.toSource() + ")()", epsb); 112 113 // Let's create an object in the target scope and add privileged 114 // function to it as a property. 115 Cu.evalInSandbox("(" + function() { 116 var newContentObject = createObjectIn(subsb, { defineAs: "importedObject" }); 117 exportFunction(funToExport, newContentObject, { defineAs: "privMethod" }); 118 }.toSource() + ")()", epsb); 119 120 Cu.evalInSandbox("(" + function () { 121 importedObject.privMethod(importedObject, 42, tobecloned, native, mixed); 122 }.toSource() + ")()", subsb); 123 124 Cu.evalInSandbox("(" + function() { 125 checkIfCalled(); 126 }.toSource() + ")()", epsb); 127 128 // exportFunction and createObjectIn should be available from Cu too. 129 var newContentObject = Cu.createObjectIn(subsb, { defineAs: "importedObject2" }); 130 var wasCalled = false; 131 Cu.exportFunction(function(arg) { wasCalled = arg.wasCalled; }, 132 newContentObject, { defineAs: "privMethod" }); 133 134 Cu.evalInSandbox("(" + function () { 135 importedObject2.privMethod({wasCalled: true}); 136 }.toSource() + ")()", subsb); 137 138 // 3rd argument of exportFunction should be optional. 139 Cu.evalInSandbox("(" + function() { 140 subsb.imported2 = exportFunction(funToExport, subsb); 141 }.toSource() + ")()", epsb); 142 143 Cu.evalInSandbox("(" + function () { 144 imported2(this, 42, tobecloned, native, mixed); 145 }.toSource() + ")()", subsb); 146 147 Cu.evalInSandbox("(" + function() { 148 checkIfCalled(); 149 }.toSource() + ")()", epsb); 150 151 Assert.ok(wasCalled); 152 }