|
1 /** Test for Bug 815105 **/ |
|
2 /* |
|
3 * gData is an array of object that tests using this framework must pass in |
|
4 * The current tests only pass in a single element array. Each test in |
|
5 * gData is executed by the framework for a given file |
|
6 * |
|
7 * Fields in gData object |
|
8 * perms (required) Array of Strings |
|
9 * list of permissions that this test will need. See |
|
10 * http://mxr.mozilla.org/mozilla-central/source/dom/apps/src/PermissionsTable.jsm |
|
11 * These permissions are added after a sanity check and removed at |
|
12 * test conclusion |
|
13 * |
|
14 * obj (required for default verifier) String |
|
15 * The name of the window.navigator object used for accessing the |
|
16 * WebAPI during the tests |
|
17 * |
|
18 * webidl (required for default verifier) String |
|
19 * idl (required for default verifier) String |
|
20 * Only one of webidl / idl is required |
|
21 * The IDL describing the navigator object. The returned object |
|
22 * during tests /must/ be an instanceof this |
|
23 * |
|
24 * skip (optional) Array of Strings |
|
25 * A list of navigator.userAgent's to skip the second part of tests |
|
26 * on. The tests still verify that you can't get obj on those |
|
27 * platforms without permissions, however it is expected that adding |
|
28 * the permission still won't allow access to those objects |
|
29 * |
|
30 * settings (optional) Array of preference tuples |
|
31 * A list of settings that need to be set before this API is |
|
32 * enabled. Note the settings are set before the sanity check is |
|
33 * performed. If an API gates access only by preferences, then it |
|
34 * will fail the initial test |
|
35 * |
|
36 * verifier (optional) Function |
|
37 * A function used to test whether a WebAPI is accessible or not. |
|
38 * The function takes a success and failure callback which both |
|
39 * accept a msg argument. msg is surfaced up to the top level tests |
|
40 * A default verifier is provided which only attempts to access |
|
41 * the navigator object. |
|
42 * |
|
43 * needParentPerm (optional) Boolean |
|
44 * Whether or not the parent frame requires these permissions as |
|
45 * well. Otherwise the test process may be killed. |
|
46 */ |
|
47 |
|
48 SimpleTest.waitForExplicitFinish(); |
|
49 var expand = SpecialPowers.Cu.import("resource://gre/modules/PermissionsTable.jsm").expandPermissions; |
|
50 const permTable = SpecialPowers.Cu.import("resource://gre/modules/PermissionsTable.jsm").PermissionsTable; |
|
51 |
|
52 const TEST_DOMAIN = "http://example.org"; |
|
53 const SHIM_PATH = "/tests/dom/permission/tests/file_shim.html" |
|
54 var gContent = document.getElementById('content'); |
|
55 |
|
56 //var gData; defined in external files |
|
57 var gCurrentTest = 0; |
|
58 var gRemainingTests; |
|
59 var pendingTests = {}; |
|
60 |
|
61 function PermTest(aData) { |
|
62 var self = this; |
|
63 var skip = aData.skip || false; |
|
64 this.step = 0; |
|
65 this.data = aData; |
|
66 this.isSkip = skip && |
|
67 skip.some(function (el) { |
|
68 return navigator. |
|
69 userAgent.toLowerCase(). |
|
70 indexOf(el.toLowerCase()) != -1; |
|
71 }); |
|
72 |
|
73 this.setupParent = false; |
|
74 this.perms = expandPermissions(aData.perm); |
|
75 this.id = gCurrentTest++; |
|
76 this.iframe = null; |
|
77 |
|
78 // keep a reference to this for eventhandler |
|
79 pendingTests[this.id] = this; |
|
80 |
|
81 this.createFrame = function() { |
|
82 if (self.iframe) { |
|
83 gContent.removeChild(self.iframe); |
|
84 } |
|
85 var iframe = document.createElement('iframe'); |
|
86 iframe.setAttribute('id', 'testframe' + self.step + self.perms) |
|
87 iframe.setAttribute('remote', true); |
|
88 iframe.src = TEST_DOMAIN + SHIM_PATH; |
|
89 iframe.addEventListener('load', function _iframeLoad() { |
|
90 iframe.removeEventListener('load', _iframeLoad); |
|
91 |
|
92 // check permissions are correct |
|
93 var allow = (self.step == 0 ? false : true); |
|
94 self.perms.forEach(function (el) { |
|
95 try { |
|
96 var res = SpecialPowers.hasPermission(el, SpecialPowers.wrap(iframe) |
|
97 .contentDocument); |
|
98 is(res, allow, (allow ? "Has " : "Doesn't have ") + el); |
|
99 } catch(e) { |
|
100 ok(false, "failed " + e); |
|
101 } |
|
102 }); |
|
103 |
|
104 var msg = { |
|
105 id: self.id, |
|
106 step: self.step++, |
|
107 testdata: self.data, |
|
108 } |
|
109 // start the tests |
|
110 iframe.contentWindow.postMessage(msg, "*"); |
|
111 }); |
|
112 |
|
113 self.iframe = iframe; |
|
114 gContent.appendChild(iframe); |
|
115 } |
|
116 |
|
117 this.next = function () { |
|
118 switch(self.step) { |
|
119 case 0: |
|
120 self.createFrame(); |
|
121 break; |
|
122 case 1: |
|
123 // add permissions |
|
124 addPermissions(self.perms, SpecialPowers. |
|
125 wrap(self.iframe). |
|
126 contentDocument, |
|
127 self.createFrame.bind(self)); |
|
128 break; |
|
129 case 2: |
|
130 if (self.iframe) { |
|
131 gContent.removeChild(self.iframe); |
|
132 } |
|
133 checkFinish(); |
|
134 break; |
|
135 default: |
|
136 ok(false, "Should not be reached"); |
|
137 break |
|
138 } |
|
139 } |
|
140 |
|
141 this.start = function() { |
|
142 // some permissions need parent to have permission as well |
|
143 if (!self.setupParent && self.data.needParentPerm && |
|
144 !SpecialPowers.isMainProcess()) { |
|
145 self.setupParent = true; |
|
146 addPermissions(self.perms, window.document, self.start.bind(self)); |
|
147 } else if (self.data.settings && self.data.settings.length) { |
|
148 SpecialPowers.pushPrefEnv({'set': self.data.settings.slice(0)}, |
|
149 self.next.bind(self)); |
|
150 } else { |
|
151 self.next(); |
|
152 } |
|
153 } |
|
154 } |
|
155 |
|
156 function addPermissions(aPerms, aDoc, aCallback) { |
|
157 var permList = []; |
|
158 aPerms.forEach(function (el) { |
|
159 var obj = {'type': el, |
|
160 'allow': 1, |
|
161 'context': aDoc}; |
|
162 permList.push(obj); |
|
163 }); |
|
164 SpecialPowers.pushPermissions(permList, aCallback); |
|
165 } |
|
166 |
|
167 function expandPermissions(aPerms) { |
|
168 var perms = []; |
|
169 aPerms.forEach(function(el) { |
|
170 var access = permTable[el].access ? "readwrite" : null; |
|
171 var expanded = SpecialPowers.unwrap(expand(el, access)); |
|
172 // COW arrays don't behave array-like enough, to allow |
|
173 // using expanded.slice(0) here. |
|
174 for (let i = 0; i < expanded.length; i++) { |
|
175 perms.push(expanded[i]); |
|
176 } |
|
177 }); |
|
178 |
|
179 return perms; |
|
180 } |
|
181 |
|
182 function msgHandler(evt) { |
|
183 var data = evt.data; |
|
184 var test = pendingTests[data.id]; |
|
185 |
|
186 /* |
|
187 * step 2 of tests should fail on |
|
188 * platforms which are skipped |
|
189 */ |
|
190 if (test.isSkip && test.step == 2) { |
|
191 todo(data.result, data.msg); |
|
192 } else { |
|
193 ok(data.result, data.msg); |
|
194 } |
|
195 |
|
196 if (test) { |
|
197 test.next(); |
|
198 } else { |
|
199 ok(false, "Received unknown id " + data.id); |
|
200 checkFinish(); |
|
201 } |
|
202 } |
|
203 |
|
204 function checkFinish() { |
|
205 if (--gRemainingTests) { |
|
206 gTestRunner.next(); |
|
207 } else { |
|
208 window.removeEventListener('message', msgHandler); |
|
209 SimpleTest.finish(); |
|
210 } |
|
211 } |
|
212 |
|
213 function runTest() { |
|
214 gRemainingTests = Object.keys(gData).length; |
|
215 |
|
216 for (var test in gData) { |
|
217 var test = new PermTest(gData[test]); |
|
218 test.start(); |
|
219 yield undefined; |
|
220 } |
|
221 } |
|
222 |
|
223 var gTestRunner = runTest(); |
|
224 |
|
225 window.addEventListener('load', function() { gTestRunner.next(); }, false); |
|
226 window.addEventListener('message', msgHandler, false); |