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