diff options
Diffstat (limited to 'devtools/server/tests/xpcshell/test_unsafeDereference.js')
-rw-r--r-- | devtools/server/tests/xpcshell/test_unsafeDereference.js | 130 |
1 files changed, 130 insertions, 0 deletions
diff --git a/devtools/server/tests/xpcshell/test_unsafeDereference.js b/devtools/server/tests/xpcshell/test_unsafeDereference.js new file mode 100644 index 0000000000..f0eea91f31 --- /dev/null +++ b/devtools/server/tests/xpcshell/test_unsafeDereference.js @@ -0,0 +1,130 @@ +// Any copyright is dedicated to the Public Domain. +// http://creativecommons.org/publicdomain/zero/1.0/ + +/* eslint-disable strict */ + +// Test Debugger.Object.prototype.unsafeDereference in the presence of +// interesting cross-compartment wrappers. +// +// This is not really a devtools server test; it's more of a Debugger test. +// But we need xpcshell and Components.utils.Sandbox to get +// cross-compartment wrappers with interesting properties, and this is the +// xpcshell test directory most closely related to the JS Debugger API. + +addDebuggerToGlobal(globalThis); + +// Add a method to Debugger.Object for fetching value properties +// conveniently. +Debugger.Object.prototype.getProperty = function(name) { + const desc = this.getOwnPropertyDescriptor(name); + if (!desc) { + return undefined; + } + if (!desc.value) { + throw Error( + "Debugger.Object.prototype.getProperty: " + + "not a value property: " + + name + ); + } + return desc.value; +}; + +function run_test() { + // Create a low-privilege sandbox, and a chrome-privilege sandbox. + const contentBox = Cu.Sandbox("http://www.example.com"); + const chromeBox = Cu.Sandbox(this); + + // Create an objects in this compartment, and one in each sandbox. We'll + // refer to the objects as "mainObj", "contentObj", and "chromeObj", in + // variable and property names. + const mainObj = { name: "mainObj" }; + Cu.evalInSandbox('var contentObj = { name: "contentObj" };', contentBox); + Cu.evalInSandbox('var chromeObj = { name: "chromeObj" };', chromeBox); + + // Give each global a pointer to all the other globals' objects. + contentBox.mainObj = chromeBox.mainObj = mainObj; + const contentObj = (chromeBox.contentObj = contentBox.contentObj); + const chromeObj = (contentBox.chromeObj = chromeBox.chromeObj); + + // First, a whole bunch of basic sanity checks, to ensure that JavaScript + // evaluated in various scopes really does see the world the way this + // test expects it to. + + // The objects appear as global variables in the sandbox, and as + // the sandbox object's properties in chrome. + Assert.ok(Cu.evalInSandbox("mainObj", contentBox) === contentBox.mainObj); + Assert.ok( + Cu.evalInSandbox("contentObj", contentBox) === contentBox.contentObj + ); + Assert.ok(Cu.evalInSandbox("chromeObj", contentBox) === contentBox.chromeObj); + Assert.ok(Cu.evalInSandbox("mainObj", chromeBox) === chromeBox.mainObj); + Assert.ok(Cu.evalInSandbox("contentObj", chromeBox) === chromeBox.contentObj); + Assert.ok(Cu.evalInSandbox("chromeObj", chromeBox) === chromeBox.chromeObj); + + // We (the main global) can see properties of all objects in all globals. + Assert.ok(contentBox.mainObj.name === "mainObj"); + Assert.ok(contentBox.contentObj.name === "contentObj"); + Assert.ok(contentBox.chromeObj.name === "chromeObj"); + + // chromeBox can see properties of all objects in all globals. + Assert.equal(Cu.evalInSandbox("mainObj.name", chromeBox), "mainObj"); + Assert.equal(Cu.evalInSandbox("contentObj.name", chromeBox), "contentObj"); + Assert.equal(Cu.evalInSandbox("chromeObj.name", chromeBox), "chromeObj"); + + // contentBox can see properties of the content object, but not of either + // chrome object, because by default, content -> chrome wrappers hide all + // object properties. + Assert.equal(Cu.evalInSandbox("mainObj.name", contentBox), undefined); + Assert.equal(Cu.evalInSandbox("contentObj.name", contentBox), "contentObj"); + Assert.equal(Cu.evalInSandbox("chromeObj.name", contentBox), undefined); + + // When viewing an object in compartment A from the vantage point of + // compartment B, Debugger should give the same results as debuggee code + // would. + + // Create a debugger, debugging our two sandboxes. + const dbg = new Debugger(); + + // Create Debugger.Object instances referring to the two sandboxes, as + // seen from their own compartments. + const contentBoxDO = dbg.addDebuggee(contentBox); + const chromeBoxDO = dbg.addDebuggee(chromeBox); + + // Use Debugger to view the objects from contentBox. We should get the + // same D.O instance from both getProperty and makeDebuggeeValue, and the + // same property visibility we checked for above. + const mainFromContentDO = contentBoxDO.getProperty("mainObj"); + Assert.equal(mainFromContentDO, contentBoxDO.makeDebuggeeValue(mainObj)); + Assert.equal(mainFromContentDO.getProperty("name"), undefined); + Assert.equal(mainFromContentDO.unsafeDereference(), mainObj); + + const contentFromContentDO = contentBoxDO.getProperty("contentObj"); + Assert.equal( + contentFromContentDO, + contentBoxDO.makeDebuggeeValue(contentObj) + ); + Assert.equal(contentFromContentDO.getProperty("name"), "contentObj"); + Assert.equal(contentFromContentDO.unsafeDereference(), contentObj); + + const chromeFromContentDO = contentBoxDO.getProperty("chromeObj"); + Assert.equal(chromeFromContentDO, contentBoxDO.makeDebuggeeValue(chromeObj)); + Assert.equal(chromeFromContentDO.getProperty("name"), undefined); + Assert.equal(chromeFromContentDO.unsafeDereference(), chromeObj); + + // Similarly, viewing from chromeBox. + const mainFromChromeDO = chromeBoxDO.getProperty("mainObj"); + Assert.equal(mainFromChromeDO, chromeBoxDO.makeDebuggeeValue(mainObj)); + Assert.equal(mainFromChromeDO.getProperty("name"), "mainObj"); + Assert.equal(mainFromChromeDO.unsafeDereference(), mainObj); + + const contentFromChromeDO = chromeBoxDO.getProperty("contentObj"); + Assert.equal(contentFromChromeDO, chromeBoxDO.makeDebuggeeValue(contentObj)); + Assert.equal(contentFromChromeDO.getProperty("name"), "contentObj"); + Assert.equal(contentFromChromeDO.unsafeDereference(), contentObj); + + const chromeFromChromeDO = chromeBoxDO.getProperty("chromeObj"); + Assert.equal(chromeFromChromeDO, chromeBoxDO.makeDebuggeeValue(chromeObj)); + Assert.equal(chromeFromChromeDO.getProperty("name"), "chromeObj"); + Assert.equal(chromeFromChromeDO.unsafeDereference(), chromeObj); +} |