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 | <!DOCTYPE HTML> |
michael@0 | 2 | <html> |
michael@0 | 3 | <!-- |
michael@0 | 4 | https://bugzilla.mozilla.org/show_bug.cgi?id=971379 |
michael@0 | 5 | --> |
michael@0 | 6 | <head> |
michael@0 | 7 | <meta charset="utf-8"> |
michael@0 | 8 | <title>Certified/packaged apps may use synthetic events with FXA -- Bug 971379</title> |
michael@0 | 9 | <script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script> |
michael@0 | 10 | <link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css"/> |
michael@0 | 11 | </head> |
michael@0 | 12 | <body> |
michael@0 | 13 | <a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=971379">Mozilla Bug 971379</a> |
michael@0 | 14 | <p id="display"></p> |
michael@0 | 15 | <div id="content"> |
michael@0 | 16 | |
michael@0 | 17 | </div> |
michael@0 | 18 | <pre id="test"> |
michael@0 | 19 | <script type="application/javascript;version=1.8"> |
michael@0 | 20 | |
michael@0 | 21 | SimpleTest.waitForExplicitFinish(); |
michael@0 | 22 | |
michael@0 | 23 | Components.utils.import("resource://gre/modules/Promise.jsm"); |
michael@0 | 24 | Components.utils.import("resource://gre/modules/Services.jsm"); |
michael@0 | 25 | Components.utils.import("resource://gre/modules/DOMIdentity.jsm"); |
michael@0 | 26 | Components.utils.import("resource://gre/modules/identity/jwcrypto.jsm"); |
michael@0 | 27 | Components.utils.import("resource://gre/modules/identity/FirefoxAccounts.jsm"); |
michael@0 | 28 | |
michael@0 | 29 | // Mock the Firefox Accounts manager to give a dummy assertion, just to confirm |
michael@0 | 30 | // that we're making the trip through the dom/identity and toolkit/identity |
michael@0 | 31 | // plumbing. |
michael@0 | 32 | function MockFXAManager() {} |
michael@0 | 33 | MockFXAManager.prototype = { |
michael@0 | 34 | getAssertion: function(audience, options) { |
michael@0 | 35 | if (options.silent) { |
michael@0 | 36 | return Promise.resolve(null); |
michael@0 | 37 | } |
michael@0 | 38 | return Promise.resolve("here~you.go.dude"); |
michael@0 | 39 | } |
michael@0 | 40 | }; |
michael@0 | 41 | |
michael@0 | 42 | let originalManager = FirefoxAccounts.fxAccountsManager; |
michael@0 | 43 | FirefoxAccounts.fxAccountsManager = new MockFXAManager(); |
michael@0 | 44 | |
michael@0 | 45 | // Mock IdentityService (Persona) so we can test request() while not handling |
michael@0 | 46 | // user input on an installed app. Since in this test suite, we have only this |
michael@0 | 47 | // one test for Persona, we additionally cause request() to throw if invoked, as |
michael@0 | 48 | // added security that nsDOMIdentity did not emit a request message. |
michael@0 | 49 | let MockIdentityService = function() { |
michael@0 | 50 | this.RP = this; |
michael@0 | 51 | this.contexts = {}; |
michael@0 | 52 | } |
michael@0 | 53 | MockIdentityService.prototype = { |
michael@0 | 54 | watch: function(context) { |
michael@0 | 55 | this.contexts[context.id] = context; |
michael@0 | 56 | context.doReady(); |
michael@0 | 57 | }, |
michael@0 | 58 | |
michael@0 | 59 | request: function(message) { |
michael@0 | 60 | ok(false, "nsDOMIdentity should block Persona request() in this test suite"); |
michael@0 | 61 | }, |
michael@0 | 62 | }; |
michael@0 | 63 | DOMIdentity._mockIdentityService = new MockIdentityService(); |
michael@0 | 64 | |
michael@0 | 65 | // The manifests for these apps are all declared in |
michael@0 | 66 | // /testing/profiles/webapps_mochitest.json. They are injected into the profile |
michael@0 | 67 | // by /testing/mochitest/runtests.py with the appropriate appStatus. So we don't |
michael@0 | 68 | // have to manually install any apps. |
michael@0 | 69 | let apps = [ |
michael@0 | 70 | { |
michael@0 | 71 | title: "an installed app, which must request() in a native event", |
michael@0 | 72 | manifest: "https://example.com/manifest.webapp", |
michael@0 | 73 | origin: "https://example.com", |
michael@0 | 74 | uri: "https://example.com/chrome/dom/identity/tests/mochitest/file_syntheticEvents.html", |
michael@0 | 75 | wantIssuer: "", // default to persona |
michael@0 | 76 | expected: { |
michael@0 | 77 | success: false, |
michael@0 | 78 | errors: [ |
michael@0 | 79 | "ERROR_REQUEST_WHILE_NOT_HANDLING_USER_INPUT", |
michael@0 | 80 | ], |
michael@0 | 81 | }, |
michael@0 | 82 | }, |
michael@0 | 83 | { |
michael@0 | 84 | title: "an installed app, which must may not use firefox accounts", |
michael@0 | 85 | manifest: "https://example.com/manifest.webapp", |
michael@0 | 86 | origin: "https://example.com", |
michael@0 | 87 | uri: "https://example.com/chrome/dom/identity/tests/mochitest/file_syntheticEvents.html", |
michael@0 | 88 | wantIssuer: "firefox-accounts", |
michael@0 | 89 | expected: { |
michael@0 | 90 | success: false, |
michael@0 | 91 | errors: [ |
michael@0 | 92 | "ERROR_NOT_AUTHORIZED_FOR_FIREFOX_ACCOUNTS", |
michael@0 | 93 | ], |
michael@0 | 94 | }, |
michael@0 | 95 | }, |
michael@0 | 96 | { |
michael@0 | 97 | title: "a privileged app, which may use synthetic events", |
michael@0 | 98 | manifest: "https://example.com/manifest_priv.webapp", |
michael@0 | 99 | origin: "https://example.com", |
michael@0 | 100 | uri: "https://example.com/chrome/dom/identity/tests/mochitest/file_syntheticEvents.html", |
michael@0 | 101 | wantIssuer: "firefox-accounts", |
michael@0 | 102 | expected: { |
michael@0 | 103 | success: true, |
michael@0 | 104 | }, |
michael@0 | 105 | }, |
michael@0 | 106 | { |
michael@0 | 107 | title: "a certified app, which may use synthetic events", |
michael@0 | 108 | manifest: "https://example.com/manifest_cert.webapp", |
michael@0 | 109 | origin: "https://example.com", |
michael@0 | 110 | uri: "https://example.com/chrome/dom/identity/tests/mochitest/file_syntheticEvents.html", |
michael@0 | 111 | wantIssuer: "firefox-accounts", |
michael@0 | 112 | expected: { |
michael@0 | 113 | success: true, |
michael@0 | 114 | }, |
michael@0 | 115 | }, |
michael@0 | 116 | ]; |
michael@0 | 117 | |
michael@0 | 118 | let appIndex = 0; |
michael@0 | 119 | let testRunner = runTest(); |
michael@0 | 120 | let receivedErrors = []; |
michael@0 | 121 | |
michael@0 | 122 | function receiveMessage(event) { |
michael@0 | 123 | dump("** Received response: " + event.data + "\n"); |
michael@0 | 124 | let result = JSON.parse(event.data); |
michael@0 | 125 | let app = apps[appIndex]; |
michael@0 | 126 | let expected = app.expected; |
michael@0 | 127 | |
michael@0 | 128 | is(result.success, expected.success, |
michael@0 | 129 | "Assertion request " + (expected.success ? "succeeds" : "fails")); |
michael@0 | 130 | |
michael@0 | 131 | if (result.error) { |
michael@0 | 132 | receivedErrors.push(result.error); |
michael@0 | 133 | } |
michael@0 | 134 | |
michael@0 | 135 | if (receivedErrors.length === (expected.errors || []).length) { |
michael@0 | 136 | receivedErrors.forEach((error) => { |
michael@0 | 137 | ok(expected.errors.indexOf(error) > -1, |
michael@0 | 138 | "Received " + error + ". " + |
michael@0 | 139 | "Expected errors are: " + JSON.stringify(expected.errors)); |
michael@0 | 140 | }); |
michael@0 | 141 | |
michael@0 | 142 | appIndex += 1; |
michael@0 | 143 | |
michael@0 | 144 | if (appIndex === apps.length) { |
michael@0 | 145 | window.removeEventListener("message", receiveMessage); |
michael@0 | 146 | |
michael@0 | 147 | // Remove mock from DOMIdentity |
michael@0 | 148 | DOMIdentity._mockIdentityService = null; |
michael@0 | 149 | |
michael@0 | 150 | // Restore original fxa manager |
michael@0 | 151 | FirefoxAccounts.fxAccountsManager = originalManager; |
michael@0 | 152 | |
michael@0 | 153 | SimpleTest.finish(); |
michael@0 | 154 | return; |
michael@0 | 155 | } |
michael@0 | 156 | |
michael@0 | 157 | testRunner.next(); |
michael@0 | 158 | } |
michael@0 | 159 | } |
michael@0 | 160 | |
michael@0 | 161 | window.addEventListener("message", receiveMessage, false, true); |
michael@0 | 162 | |
michael@0 | 163 | function runTest() { |
michael@0 | 164 | for (let app of apps) { |
michael@0 | 165 | dump("** Testing " + app.title + "\n"); |
michael@0 | 166 | |
michael@0 | 167 | receivedErrors = []; |
michael@0 | 168 | |
michael@0 | 169 | let iframe = document.createElement("iframe"); |
michael@0 | 170 | |
michael@0 | 171 | iframe.setAttribute("mozapp", app.manifest); |
michael@0 | 172 | iframe.setAttribute("mozbrowser", "true"); |
michael@0 | 173 | iframe.src = app.uri; |
michael@0 | 174 | |
michael@0 | 175 | document.getElementById("content").appendChild(iframe); |
michael@0 | 176 | |
michael@0 | 177 | iframe.addEventListener("load", function onLoad() { |
michael@0 | 178 | iframe.removeEventListener("load", onLoad); |
michael@0 | 179 | |
michael@0 | 180 | // Because the <iframe mozapp> can't parent its way back to us, we |
michael@0 | 181 | // provide this handle to our window so it can postMessage to us. |
michael@0 | 182 | iframe.contentWindow.wrappedJSObject.realParent = window; |
michael@0 | 183 | iframe.contentWindow.postMessage({wantIssuer: app.wantIssuer}, "*"); |
michael@0 | 184 | }, false); |
michael@0 | 185 | |
michael@0 | 186 | yield undefined; |
michael@0 | 187 | } |
michael@0 | 188 | } |
michael@0 | 189 | |
michael@0 | 190 | SpecialPowers.pushPrefEnv({"set": |
michael@0 | 191 | [ |
michael@0 | 192 | ["dom.mozBrowserFramesEnabled", true], |
michael@0 | 193 | ["dom.identity.enabled", true], |
michael@0 | 194 | ["identity.fxaccounts.enabled", true], |
michael@0 | 195 | ["toolkit.identity.debug", true], |
michael@0 | 196 | |
michael@0 | 197 | ["security.apps.privileged.CSP.default", ""], |
michael@0 | 198 | ["security.apps.certified.CSP.default", ""], |
michael@0 | 199 | ]}, |
michael@0 | 200 | function() { |
michael@0 | 201 | testRunner.next(); |
michael@0 | 202 | } |
michael@0 | 203 | ); |
michael@0 | 204 | |
michael@0 | 205 | |
michael@0 | 206 | </script> |
michael@0 | 207 | </pre> |
michael@0 | 208 | </body> |
michael@0 | 209 | </html> |