|
1 // Any copyright is dedicated to the Public Domain. |
|
2 // http://creativecommons.org/publicdomain/zero/1.0/ |
|
3 |
|
4 // Test Debugger.Object.prototype.unsafeDereference in the presence of |
|
5 // interesting cross-compartment wrappers. |
|
6 // |
|
7 // This is not really a debugger server test; it's more of a Debugger test. |
|
8 // But we need xpcshell and Components.utils.Sandbox to get |
|
9 // cross-compartment wrappers with interesting properties, and this is the |
|
10 // xpcshell test directory most closely related to the JS Debugger API. |
|
11 |
|
12 Components.utils.import("resource://gre/modules/jsdebugger.jsm"); |
|
13 addDebuggerToGlobal(this); |
|
14 |
|
15 // Add a method to Debugger.Object for fetching value properties |
|
16 // conveniently. |
|
17 Debugger.Object.prototype.getProperty = function (aName) { |
|
18 let desc = this.getOwnPropertyDescriptor(aName); |
|
19 if (!desc) |
|
20 return undefined; |
|
21 if (!desc.value) { |
|
22 throw Error("Debugger.Object.prototype.getProperty: " + |
|
23 "not a value property: " + aName); |
|
24 } |
|
25 return desc.value; |
|
26 }; |
|
27 |
|
28 function run_test() { |
|
29 // Create a low-privilege sandbox, and a chrome-privilege sandbox. |
|
30 let contentBox = Components.utils.Sandbox('http://www.example.com'); |
|
31 let chromeBox = Components.utils.Sandbox(this); |
|
32 |
|
33 // Create an objects in this compartment, and one in each sandbox. We'll |
|
34 // refer to the objects as "mainObj", "contentObj", and "chromeObj", in |
|
35 // variable and property names. |
|
36 var mainObj = { name: "mainObj" }; |
|
37 Components.utils.evalInSandbox('var contentObj = { name: "contentObj" };', |
|
38 contentBox); |
|
39 Components.utils.evalInSandbox('var chromeObj = { name: "chromeObj" };', |
|
40 chromeBox); |
|
41 |
|
42 // Give each global a pointer to all the other globals' objects. |
|
43 contentBox.mainObj = chromeBox.mainObj = mainObj; |
|
44 var contentObj = chromeBox.contentObj = contentBox.contentObj; |
|
45 var chromeObj = contentBox.chromeObj = chromeBox.chromeObj; |
|
46 |
|
47 // First, a whole bunch of basic sanity checks, to ensure that JavaScript |
|
48 // evaluated in various scopes really does see the world the way this |
|
49 // test expects it to. |
|
50 |
|
51 // The objects appear as global variables in the sandbox, and as |
|
52 // the sandbox object's properties in chrome. |
|
53 do_check_true(Components.utils.evalInSandbox('mainObj', contentBox) |
|
54 === contentBox.mainObj); |
|
55 do_check_true(Components.utils.evalInSandbox('contentObj', contentBox) |
|
56 === contentBox.contentObj); |
|
57 do_check_true(Components.utils.evalInSandbox('chromeObj', contentBox) |
|
58 === contentBox.chromeObj); |
|
59 do_check_true(Components.utils.evalInSandbox('mainObj', chromeBox) |
|
60 === chromeBox.mainObj); |
|
61 do_check_true(Components.utils.evalInSandbox('contentObj', chromeBox) |
|
62 === chromeBox.contentObj); |
|
63 do_check_true(Components.utils.evalInSandbox('chromeObj', chromeBox) |
|
64 === chromeBox.chromeObj); |
|
65 |
|
66 // We (the main global) can see properties of all objects in all globals. |
|
67 do_check_true(contentBox.mainObj.name === "mainObj"); |
|
68 do_check_true(contentBox.contentObj.name === "contentObj"); |
|
69 do_check_true(contentBox.chromeObj.name === "chromeObj"); |
|
70 |
|
71 // chromeBox can see properties of all objects in all globals. |
|
72 do_check_eq(Components.utils.evalInSandbox('mainObj.name', chromeBox), |
|
73 'mainObj'); |
|
74 do_check_eq(Components.utils.evalInSandbox('contentObj.name', chromeBox), |
|
75 'contentObj'); |
|
76 do_check_eq(Components.utils.evalInSandbox('chromeObj.name', chromeBox), |
|
77 'chromeObj'); |
|
78 |
|
79 // contentBox can see properties of the content object, but not of either |
|
80 // chrome object, because by default, content -> chrome wrappers hide all |
|
81 // object properties. |
|
82 do_check_eq(Components.utils.evalInSandbox('mainObj.name', contentBox), |
|
83 undefined); |
|
84 do_check_eq(Components.utils.evalInSandbox('contentObj.name', contentBox), |
|
85 'contentObj'); |
|
86 do_check_eq(Components.utils.evalInSandbox('chromeObj.name', contentBox), |
|
87 undefined); |
|
88 |
|
89 // When viewing an object in compartment A from the vantage point of |
|
90 // compartment B, Debugger should give the same results as debuggee code |
|
91 // would. |
|
92 |
|
93 // Create a debugger, debugging our two sandboxes. |
|
94 let dbg = new Debugger; |
|
95 |
|
96 // Create Debugger.Object instances referring to the two sandboxes, as |
|
97 // seen from their own compartments. |
|
98 let contentBoxDO = dbg.addDebuggee(contentBox); |
|
99 let chromeBoxDO = dbg.addDebuggee(chromeBox); |
|
100 |
|
101 // Use Debugger to view the objects from contentBox. We should get the |
|
102 // same D.O instance from both getProperty and makeDebuggeeValue, and the |
|
103 // same property visibility we checked for above. |
|
104 let mainFromContentDO = contentBoxDO.getProperty('mainObj'); |
|
105 do_check_eq(mainFromContentDO, contentBoxDO.makeDebuggeeValue(mainObj)); |
|
106 do_check_eq(mainFromContentDO.getProperty('name'), undefined); |
|
107 do_check_eq(mainFromContentDO.unsafeDereference(), mainObj); |
|
108 |
|
109 let contentFromContentDO = contentBoxDO.getProperty('contentObj'); |
|
110 do_check_eq(contentFromContentDO, contentBoxDO.makeDebuggeeValue(contentObj)); |
|
111 do_check_eq(contentFromContentDO.getProperty('name'), 'contentObj'); |
|
112 do_check_eq(contentFromContentDO.unsafeDereference(), contentObj); |
|
113 |
|
114 let chromeFromContentDO = contentBoxDO.getProperty('chromeObj'); |
|
115 do_check_eq(chromeFromContentDO, contentBoxDO.makeDebuggeeValue(chromeObj)); |
|
116 do_check_eq(chromeFromContentDO.getProperty('name'), undefined); |
|
117 do_check_eq(chromeFromContentDO.unsafeDereference(), chromeObj); |
|
118 |
|
119 // Similarly, viewing from chromeBox. |
|
120 let mainFromChromeDO = chromeBoxDO.getProperty('mainObj'); |
|
121 do_check_eq(mainFromChromeDO, chromeBoxDO.makeDebuggeeValue(mainObj)); |
|
122 do_check_eq(mainFromChromeDO.getProperty('name'), 'mainObj'); |
|
123 do_check_eq(mainFromChromeDO.unsafeDereference(), mainObj); |
|
124 |
|
125 let contentFromChromeDO = chromeBoxDO.getProperty('contentObj'); |
|
126 do_check_eq(contentFromChromeDO, chromeBoxDO.makeDebuggeeValue(contentObj)); |
|
127 do_check_eq(contentFromChromeDO.getProperty('name'), 'contentObj'); |
|
128 do_check_eq(contentFromChromeDO.unsafeDereference(), contentObj); |
|
129 |
|
130 let chromeFromChromeDO = chromeBoxDO.getProperty('chromeObj'); |
|
131 do_check_eq(chromeFromChromeDO, chromeBoxDO.makeDebuggeeValue(chromeObj)); |
|
132 do_check_eq(chromeFromChromeDO.getProperty('name'), 'chromeObj'); |
|
133 do_check_eq(chromeFromChromeDO.unsafeDereference(), chromeObj); |
|
134 } |