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 | /* Any copyright is dedicated to the Public Domain. |
michael@0 | 2 | * http://creativecommons.org/publicdomain/zero/1.0/ */ |
michael@0 | 3 | |
michael@0 | 4 | "use strict"; |
michael@0 | 5 | |
michael@0 | 6 | const {utils: Cu} = Components; |
michael@0 | 7 | |
michael@0 | 8 | Cu.import("resource://gre/modules/XPCOMUtils.jsm"); |
michael@0 | 9 | Cu.import("resource://gre/modules/Services.jsm"); |
michael@0 | 10 | Cu.import("resource://services-common/utils.js"); |
michael@0 | 11 | Cu.import("resource://testing-common/httpd.js"); |
michael@0 | 12 | |
michael@0 | 13 | XPCOMUtils.defineLazyModuleGetter(this, "FxAccountsMgmtService", |
michael@0 | 14 | "resource://gre/modules/FxAccountsMgmtService.jsm", |
michael@0 | 15 | "FxAccountsMgmtService"); |
michael@0 | 16 | |
michael@0 | 17 | // At end of test, restore original state |
michael@0 | 18 | const ORIGINAL_AUTH_URI = Services.prefs.getCharPref("identity.fxaccounts.auth.uri"); |
michael@0 | 19 | let { SystemAppProxy } = Cu.import("resource://gre/modules/FxAccountsMgmtService.jsm"); |
michael@0 | 20 | const ORIGINAL_SENDCUSTOM = SystemAppProxy._sendCustomEvent; |
michael@0 | 21 | do_register_cleanup(function() { |
michael@0 | 22 | Services.prefs.setCharPref("identity.fxaccounts.auth.uri", ORIGINAL_AUTH_URI); |
michael@0 | 23 | SystemAppProxy._sendCustomEvent = ORIGINAL_SENDCUSTOM; |
michael@0 | 24 | }); |
michael@0 | 25 | |
michael@0 | 26 | // Make profile available so that fxaccounts can store user data |
michael@0 | 27 | do_get_profile(); |
michael@0 | 28 | |
michael@0 | 29 | // Mock the system app proxy; make message passing possible |
michael@0 | 30 | let mockSendCustomEvent = function(aEventName, aMsg) { |
michael@0 | 31 | Services.obs.notifyObservers({wrappedJSObject: aMsg}, aEventName, null); |
michael@0 | 32 | }; |
michael@0 | 33 | |
michael@0 | 34 | function run_test() { |
michael@0 | 35 | run_next_test(); |
michael@0 | 36 | } |
michael@0 | 37 | |
michael@0 | 38 | add_task(function test_overall() { |
michael@0 | 39 | do_check_neq(FxAccountsMgmtService, null); |
michael@0 | 40 | }); |
michael@0 | 41 | |
michael@0 | 42 | // Check that invalid email capitalization is corrected on signIn. |
michael@0 | 43 | // https://github.com/mozilla/fxa-auth-server/blob/master/docs/api.md#post-v1accountlogin |
michael@0 | 44 | add_test(function test_invalidEmailCase_signIn() { |
michael@0 | 45 | do_test_pending(); |
michael@0 | 46 | let clientEmail = "greta.garbo@gmail.com"; |
michael@0 | 47 | let canonicalEmail = "Greta.Garbo@gmail.COM"; |
michael@0 | 48 | let attempts = 0; |
michael@0 | 49 | |
michael@0 | 50 | function writeResp(response, msg) { |
michael@0 | 51 | if (typeof msg === "object") { |
michael@0 | 52 | msg = JSON.stringify(msg); |
michael@0 | 53 | } |
michael@0 | 54 | response.bodyOutputStream.write(msg, msg.length); |
michael@0 | 55 | } |
michael@0 | 56 | |
michael@0 | 57 | // Mock of the fxa accounts auth server, reproducing the behavior of |
michael@0 | 58 | // /account/login when email capitalization is incorrect on signIn. |
michael@0 | 59 | let server = httpd_setup({ |
michael@0 | 60 | "/account/login": function(request, response) { |
michael@0 | 61 | response.setHeader("Content-Type", "application/json"); |
michael@0 | 62 | attempts += 1; |
michael@0 | 63 | |
michael@0 | 64 | // Ensure we don't get in an endless loop |
michael@0 | 65 | if (attempts > 2) { |
michael@0 | 66 | response.setStatusLine(request.httpVersion, 429, "Sorry, you had your chance"); |
michael@0 | 67 | writeResp(response, {}); |
michael@0 | 68 | return; |
michael@0 | 69 | } |
michael@0 | 70 | |
michael@0 | 71 | let body = CommonUtils.readBytesFromInputStream(request.bodyInputStream); |
michael@0 | 72 | let jsonBody = JSON.parse(body); |
michael@0 | 73 | let email = jsonBody.email; |
michael@0 | 74 | |
michael@0 | 75 | // The second time through, the accounts client will call the api with |
michael@0 | 76 | // the correct email capitalization. |
michael@0 | 77 | if (email == canonicalEmail) { |
michael@0 | 78 | response.setStatusLine(request.httpVersion, 200, "Yay"); |
michael@0 | 79 | writeResp(response, { |
michael@0 | 80 | uid: "your-uid", |
michael@0 | 81 | sessionToken: "your-sessionToken", |
michael@0 | 82 | keyFetchToken: "your-keyFetchToken", |
michael@0 | 83 | verified: true, |
michael@0 | 84 | authAt: 1392144866, |
michael@0 | 85 | }); |
michael@0 | 86 | return; |
michael@0 | 87 | } |
michael@0 | 88 | |
michael@0 | 89 | // If the client has the wrong case on the email, we return a 400, with |
michael@0 | 90 | // the capitalization of the email as saved in the accounts database. |
michael@0 | 91 | response.setStatusLine(request.httpVersion, 400, "Incorrect email case"); |
michael@0 | 92 | writeResp(response, { |
michael@0 | 93 | code: 400, |
michael@0 | 94 | errno: 120, |
michael@0 | 95 | error: "Incorrect email case", |
michael@0 | 96 | email: canonicalEmail, |
michael@0 | 97 | }); |
michael@0 | 98 | return; |
michael@0 | 99 | }, |
michael@0 | 100 | }); |
michael@0 | 101 | |
michael@0 | 102 | // Point the FxAccountsClient's hawk rest request client to the mock server |
michael@0 | 103 | Services.prefs.setCharPref("identity.fxaccounts.auth.uri", server.baseURI); |
michael@0 | 104 | |
michael@0 | 105 | // Receive a mozFxAccountsChromeEvent message |
michael@0 | 106 | function onMessage(subject, topic, data) { |
michael@0 | 107 | let message = subject.wrappedJSObject; |
michael@0 | 108 | |
michael@0 | 109 | switch (message.id) { |
michael@0 | 110 | // When we signed in as "Greta.Garbo", the server should have told us |
michael@0 | 111 | // that the proper capitalization is really "greta.garbo". Call |
michael@0 | 112 | // getAccounts to get the signed-in user and ensure that the |
michael@0 | 113 | // capitalization is correct. |
michael@0 | 114 | case "signIn": |
michael@0 | 115 | FxAccountsMgmtService.handleEvent({ |
michael@0 | 116 | detail: { |
michael@0 | 117 | id: "getAccounts", |
michael@0 | 118 | data: { |
michael@0 | 119 | method: "getAccounts", |
michael@0 | 120 | } |
michael@0 | 121 | } |
michael@0 | 122 | }); |
michael@0 | 123 | break; |
michael@0 | 124 | |
michael@0 | 125 | // Having initially signed in as "Greta.Garbo", getAccounts should show |
michael@0 | 126 | // us that the signed-in user has the properly-capitalized email, |
michael@0 | 127 | // "greta.garbo". |
michael@0 | 128 | case "getAccounts": |
michael@0 | 129 | Services.obs.removeObserver(onMessage, "mozFxAccountsChromeEvent"); |
michael@0 | 130 | |
michael@0 | 131 | do_check_eq(message.data.accountId, canonicalEmail); |
michael@0 | 132 | |
michael@0 | 133 | do_test_finished(); |
michael@0 | 134 | server.stop(run_next_test); |
michael@0 | 135 | break; |
michael@0 | 136 | |
michael@0 | 137 | // We should not receive any other mozFxAccountsChromeEvent messages |
michael@0 | 138 | default: |
michael@0 | 139 | do_throw("wat!"); |
michael@0 | 140 | break; |
michael@0 | 141 | } |
michael@0 | 142 | } |
michael@0 | 143 | |
michael@0 | 144 | Services.obs.addObserver(onMessage, "mozFxAccountsChromeEvent", false); |
michael@0 | 145 | |
michael@0 | 146 | SystemAppProxy._sendCustomEvent = mockSendCustomEvent; |
michael@0 | 147 | |
michael@0 | 148 | // Trigger signIn using an email with incorrect capitalization |
michael@0 | 149 | FxAccountsMgmtService.handleEvent({ |
michael@0 | 150 | detail: { |
michael@0 | 151 | id: "signIn", |
michael@0 | 152 | data: { |
michael@0 | 153 | method: "signIn", |
michael@0 | 154 | accountId: clientEmail, |
michael@0 | 155 | password: "123456", |
michael@0 | 156 | }, |
michael@0 | 157 | }, |
michael@0 | 158 | }); |
michael@0 | 159 | }); |
michael@0 | 160 | |
michael@0 | 161 | // End of tests |
michael@0 | 162 | // Utility functions follow |
michael@0 | 163 | |
michael@0 | 164 | function httpd_setup (handlers, port=-1) { |
michael@0 | 165 | let server = new HttpServer(); |
michael@0 | 166 | for (let path in handlers) { |
michael@0 | 167 | server.registerPathHandler(path, handlers[path]); |
michael@0 | 168 | } |
michael@0 | 169 | try { |
michael@0 | 170 | server.start(port); |
michael@0 | 171 | } catch (ex) { |
michael@0 | 172 | dump("ERROR starting server on port " + port + ". Already a process listening?"); |
michael@0 | 173 | do_throw(ex); |
michael@0 | 174 | } |
michael@0 | 175 | |
michael@0 | 176 | // Set the base URI for convenience. |
michael@0 | 177 | let i = server.identity; |
michael@0 | 178 | server.baseURI = i.primaryScheme + "://" + i.primaryHost + ":" + i.primaryPort; |
michael@0 | 179 | |
michael@0 | 180 | return server; |
michael@0 | 181 | } |
michael@0 | 182 | |
michael@0 | 183 |