gecko/js/xpconnect/tests/unit/test_interposition.js
2015-06-08 09:28:54 +02:00

166 lines
5.1 KiB
JavaScript

const Cu = Components.utils;
const Ci = Components.interfaces;
const Cc = Components.classes;
Components.utils.import("resource://gre/modules/XPCOMUtils.jsm");
const ADDONID = "bogus-addon@mozilla.org";
let gExpectedProp;
function expectAccess(prop, f)
{
gExpectedProp = prop;
f();
do_check_eq(gExpectedProp, undefined);
}
let getter_run = false;
function test_getter()
{
do_check_eq(getter_run, false);
getter_run = true;
return 200;
}
let setter_run = false;
function test_setter(v)
{
do_check_eq(setter_run, false);
do_check_eq(v, 300);
setter_run = true;
}
let TestInterposition = {
QueryInterface: XPCOMUtils.generateQI([Ci.nsIAddonInterposition,
Ci.nsISupportsWeakReference]),
getWhitelist: function() {
return ["abcxyz", "utils", "dataprop", "getterprop", "setterprop",
"objprop", "defineprop", "configurableprop"];
},
interposeProperty: function(addonId, target, iid, prop) {
do_check_eq(addonId, ADDONID);
do_check_eq(gExpectedProp, prop);
gExpectedProp = undefined;
if (prop == "dataprop") {
return { configurable: false, enumerable: true, writable: false, value: 100 };
} else if (prop == "getterprop") {
return { configurable: false, enumerable: true, get: test_getter };
} else if (prop == "setterprop") {
return { configurable: false, enumerable: true, get: test_getter, set: test_setter };
} else if (prop == "utils") {
do_check_eq(iid, Ci.nsIXPCComponents.number);
return null;
} else if (prop == "objprop") {
gExpectedProp = "objprop"; // allow recursive access here
return { configurable: false, enumerable: true, writable: false, value: { objprop: 1 } };
} else if (prop == "configurableprop") {
return { configurable: true, enumerable: true, writable: false, value: 10 };
}
return null;
},
interposeCall: function(addonId, originalFunc, originalThis, args) {
do_check_eq(addonId, ADDONID);
args.splice(0, 0, addonId);
return originalFunc.apply(originalThis, args);
}
};
function run_test()
{
Cu.setAddonInterposition(ADDONID, TestInterposition);
Cu.importGlobalProperties(["XMLHttpRequest"]);
let sandbox = Cu.Sandbox(this, {addonId: ADDONID});
sandbox.outerObj = new XMLHttpRequest();
expectAccess("abcxyz", () => {
Cu.evalInSandbox("outerObj.abcxyz = 12;", sandbox);
});
expectAccess("utils", () => {
Cu.evalInSandbox("Components.utils;", sandbox);
});
expectAccess("dataprop", () => {
do_check_eq(Cu.evalInSandbox("outerObj.dataprop;", sandbox), 100);
});
expectAccess("dataprop", () => {
try {
Cu.evalInSandbox("'use strict'; outerObj.dataprop = 400;", sandbox);
do_check_true(false); // it should throw
} catch (e) {}
});
expectAccess("objprop", () => {
Cu.evalInSandbox("outerObj.objprop.objprop;", sandbox);
gExpectedProp = undefined;
});
expectAccess("getterprop", () => {
do_check_eq(Cu.evalInSandbox("outerObj.getterprop;", sandbox), 200);
do_check_eq(getter_run, true);
getter_run = false;
});
expectAccess("getterprop", () => {
try {
Cu.evalInSandbox("'use strict'; outerObj.getterprop = 400;", sandbox);
do_check_true(false); // it should throw
} catch (e) {}
do_check_eq(getter_run, false);
});
expectAccess("setterprop", () => {
do_check_eq(Cu.evalInSandbox("outerObj.setterprop;", sandbox), 200);
do_check_eq(getter_run, true);
getter_run = false;
do_check_eq(setter_run, false);
});
expectAccess("setterprop", () => {
Cu.evalInSandbox("'use strict'; outerObj.setterprop = 300;", sandbox);
do_check_eq(getter_run, false);
do_check_eq(setter_run, true);
setter_run = false;
});
// Make sure that calling Object.defineProperty succeeds as long as
// we're not interposing on that property.
expectAccess("defineprop", () => {
Cu.evalInSandbox("'use strict'; Object.defineProperty(outerObj, 'defineprop', {configurable:true, enumerable:true, writable:true, value:10});", sandbox);
});
// Related to above: make sure we can delete those properties too.
expectAccess("defineprop", () => {
Cu.evalInSandbox("'use strict'; delete outerObj.defineprop;", sandbox);
});
// Make sure we get configurable=false even if the interposition
// sets it to true.
expectAccess("configurableprop", () => {
let desc = Cu.evalInSandbox("Object.getOwnPropertyDescriptor(outerObj, 'configurableprop')", sandbox);
do_check_eq(desc.configurable, false);
});
let moduleScope = Cu.Sandbox(this);
moduleScope.ADDONID = ADDONID;
moduleScope.do_check_eq = do_check_eq;
function funToIntercept(addonId) {
do_check_eq(addonId, ADDONID);
counter++;
}
sandbox.moduleFunction = Cu.evalInSandbox(funToIntercept.toSource() + "; funToIntercept", moduleScope);
Cu.evalInSandbox("var counter = 0;", moduleScope);
Cu.evalInSandbox("Components.utils.setAddonCallInterposition(this);", moduleScope);
Cu.evalInSandbox("moduleFunction()", sandbox);
do_check_eq(Cu.evalInSandbox("counter", moduleScope), 1);
Cu.setAddonInterposition(ADDONID, null);
}