1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/b2g/components/test/unit/test_fxaccounts.js Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,183 @@ 1.4 +/* Any copyright is dedicated to the Public Domain. 1.5 + * http://creativecommons.org/publicdomain/zero/1.0/ */ 1.6 + 1.7 +"use strict"; 1.8 + 1.9 +const {utils: Cu} = Components; 1.10 + 1.11 +Cu.import("resource://gre/modules/XPCOMUtils.jsm"); 1.12 +Cu.import("resource://gre/modules/Services.jsm"); 1.13 +Cu.import("resource://services-common/utils.js"); 1.14 +Cu.import("resource://testing-common/httpd.js"); 1.15 + 1.16 +XPCOMUtils.defineLazyModuleGetter(this, "FxAccountsMgmtService", 1.17 + "resource://gre/modules/FxAccountsMgmtService.jsm", 1.18 + "FxAccountsMgmtService"); 1.19 + 1.20 +// At end of test, restore original state 1.21 +const ORIGINAL_AUTH_URI = Services.prefs.getCharPref("identity.fxaccounts.auth.uri"); 1.22 +let { SystemAppProxy } = Cu.import("resource://gre/modules/FxAccountsMgmtService.jsm"); 1.23 +const ORIGINAL_SENDCUSTOM = SystemAppProxy._sendCustomEvent; 1.24 +do_register_cleanup(function() { 1.25 + Services.prefs.setCharPref("identity.fxaccounts.auth.uri", ORIGINAL_AUTH_URI); 1.26 + SystemAppProxy._sendCustomEvent = ORIGINAL_SENDCUSTOM; 1.27 +}); 1.28 + 1.29 +// Make profile available so that fxaccounts can store user data 1.30 +do_get_profile(); 1.31 + 1.32 +// Mock the system app proxy; make message passing possible 1.33 +let mockSendCustomEvent = function(aEventName, aMsg) { 1.34 + Services.obs.notifyObservers({wrappedJSObject: aMsg}, aEventName, null); 1.35 +}; 1.36 + 1.37 +function run_test() { 1.38 + run_next_test(); 1.39 +} 1.40 + 1.41 +add_task(function test_overall() { 1.42 + do_check_neq(FxAccountsMgmtService, null); 1.43 +}); 1.44 + 1.45 +// Check that invalid email capitalization is corrected on signIn. 1.46 +// https://github.com/mozilla/fxa-auth-server/blob/master/docs/api.md#post-v1accountlogin 1.47 +add_test(function test_invalidEmailCase_signIn() { 1.48 + do_test_pending(); 1.49 + let clientEmail = "greta.garbo@gmail.com"; 1.50 + let canonicalEmail = "Greta.Garbo@gmail.COM"; 1.51 + let attempts = 0; 1.52 + 1.53 + function writeResp(response, msg) { 1.54 + if (typeof msg === "object") { 1.55 + msg = JSON.stringify(msg); 1.56 + } 1.57 + response.bodyOutputStream.write(msg, msg.length); 1.58 + } 1.59 + 1.60 + // Mock of the fxa accounts auth server, reproducing the behavior of 1.61 + // /account/login when email capitalization is incorrect on signIn. 1.62 + let server = httpd_setup({ 1.63 + "/account/login": function(request, response) { 1.64 + response.setHeader("Content-Type", "application/json"); 1.65 + attempts += 1; 1.66 + 1.67 + // Ensure we don't get in an endless loop 1.68 + if (attempts > 2) { 1.69 + response.setStatusLine(request.httpVersion, 429, "Sorry, you had your chance"); 1.70 + writeResp(response, {}); 1.71 + return; 1.72 + } 1.73 + 1.74 + let body = CommonUtils.readBytesFromInputStream(request.bodyInputStream); 1.75 + let jsonBody = JSON.parse(body); 1.76 + let email = jsonBody.email; 1.77 + 1.78 + // The second time through, the accounts client will call the api with 1.79 + // the correct email capitalization. 1.80 + if (email == canonicalEmail) { 1.81 + response.setStatusLine(request.httpVersion, 200, "Yay"); 1.82 + writeResp(response, { 1.83 + uid: "your-uid", 1.84 + sessionToken: "your-sessionToken", 1.85 + keyFetchToken: "your-keyFetchToken", 1.86 + verified: true, 1.87 + authAt: 1392144866, 1.88 + }); 1.89 + return; 1.90 + } 1.91 + 1.92 + // If the client has the wrong case on the email, we return a 400, with 1.93 + // the capitalization of the email as saved in the accounts database. 1.94 + response.setStatusLine(request.httpVersion, 400, "Incorrect email case"); 1.95 + writeResp(response, { 1.96 + code: 400, 1.97 + errno: 120, 1.98 + error: "Incorrect email case", 1.99 + email: canonicalEmail, 1.100 + }); 1.101 + return; 1.102 + }, 1.103 + }); 1.104 + 1.105 + // Point the FxAccountsClient's hawk rest request client to the mock server 1.106 + Services.prefs.setCharPref("identity.fxaccounts.auth.uri", server.baseURI); 1.107 + 1.108 + // Receive a mozFxAccountsChromeEvent message 1.109 + function onMessage(subject, topic, data) { 1.110 + let message = subject.wrappedJSObject; 1.111 + 1.112 + switch (message.id) { 1.113 + // When we signed in as "Greta.Garbo", the server should have told us 1.114 + // that the proper capitalization is really "greta.garbo". Call 1.115 + // getAccounts to get the signed-in user and ensure that the 1.116 + // capitalization is correct. 1.117 + case "signIn": 1.118 + FxAccountsMgmtService.handleEvent({ 1.119 + detail: { 1.120 + id: "getAccounts", 1.121 + data: { 1.122 + method: "getAccounts", 1.123 + } 1.124 + } 1.125 + }); 1.126 + break; 1.127 + 1.128 + // Having initially signed in as "Greta.Garbo", getAccounts should show 1.129 + // us that the signed-in user has the properly-capitalized email, 1.130 + // "greta.garbo". 1.131 + case "getAccounts": 1.132 + Services.obs.removeObserver(onMessage, "mozFxAccountsChromeEvent"); 1.133 + 1.134 + do_check_eq(message.data.accountId, canonicalEmail); 1.135 + 1.136 + do_test_finished(); 1.137 + server.stop(run_next_test); 1.138 + break; 1.139 + 1.140 + // We should not receive any other mozFxAccountsChromeEvent messages 1.141 + default: 1.142 + do_throw("wat!"); 1.143 + break; 1.144 + } 1.145 + } 1.146 + 1.147 + Services.obs.addObserver(onMessage, "mozFxAccountsChromeEvent", false); 1.148 + 1.149 + SystemAppProxy._sendCustomEvent = mockSendCustomEvent; 1.150 + 1.151 + // Trigger signIn using an email with incorrect capitalization 1.152 + FxAccountsMgmtService.handleEvent({ 1.153 + detail: { 1.154 + id: "signIn", 1.155 + data: { 1.156 + method: "signIn", 1.157 + accountId: clientEmail, 1.158 + password: "123456", 1.159 + }, 1.160 + }, 1.161 + }); 1.162 +}); 1.163 + 1.164 +// End of tests 1.165 +// Utility functions follow 1.166 + 1.167 +function httpd_setup (handlers, port=-1) { 1.168 + let server = new HttpServer(); 1.169 + for (let path in handlers) { 1.170 + server.registerPathHandler(path, handlers[path]); 1.171 + } 1.172 + try { 1.173 + server.start(port); 1.174 + } catch (ex) { 1.175 + dump("ERROR starting server on port " + port + ". Already a process listening?"); 1.176 + do_throw(ex); 1.177 + } 1.178 + 1.179 + // Set the base URI for convenience. 1.180 + let i = server.identity; 1.181 + server.baseURI = i.primaryScheme + "://" + i.primaryHost + ":" + i.primaryPort; 1.182 + 1.183 + return server; 1.184 +} 1.185 + 1.186 +