Thu, 22 Jan 2015 13:21:57 +0100
Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6
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 */
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;
52 const TEST_DOMAIN = "http://example.org";
53 const SHIM_PATH = "/tests/dom/permission/tests/file_shim.html"
54 var gContent = document.getElementById('content');
56 //var gData; defined in external files
57 var gCurrentTest = 0;
58 var gRemainingTests;
59 var pendingTests = {};
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 });
73 this.setupParent = false;
74 this.perms = expandPermissions(aData.perm);
75 this.id = gCurrentTest++;
76 this.iframe = null;
78 // keep a reference to this for eventhandler
79 pendingTests[this.id] = this;
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);
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 });
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 });
113 self.iframe = iframe;
114 gContent.appendChild(iframe);
115 }
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 }
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 }
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 }
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 });
179 return perms;
180 }
182 function msgHandler(evt) {
183 var data = evt.data;
184 var test = pendingTests[data.id];
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 }
196 if (test) {
197 test.next();
198 } else {
199 ok(false, "Received unknown id " + data.id);
200 checkFinish();
201 }
202 }
204 function checkFinish() {
205 if (--gRemainingTests) {
206 gTestRunner.next();
207 } else {
208 window.removeEventListener('message', msgHandler);
209 SimpleTest.finish();
210 }
211 }
213 function runTest() {
214 gRemainingTests = Object.keys(gData).length;
216 for (var test in gData) {
217 var test = new PermTest(gData[test]);
218 test.start();
219 yield undefined;
220 }
221 }
223 var gTestRunner = runTest();
225 window.addEventListener('load', function() { gTestRunner.next(); }, false);
226 window.addEventListener('message', msgHandler, false);