1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/toolkit/identity/tests/unit/head_identity.js Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,256 @@ 1.4 +/* Any copyright is dedicated to the Public Domain. 1.5 + * http://creativecommons.org/publicdomain/zero/1.0/ */ 1.6 + 1.7 +const Cc = Components.classes; 1.8 +const Ci = Components.interfaces; 1.9 +const Cu = Components.utils; 1.10 +const Cr = Components.results; 1.11 + 1.12 +Cu.import("resource://testing-common/httpd.js"); 1.13 + 1.14 +// XXX until bug 937114 is fixed 1.15 +Cu.importGlobalProperties(["atob"]); 1.16 + 1.17 +// The following boilerplate makes sure that XPCom calls 1.18 +// that use the profile directory work. 1.19 + 1.20 +Cu.import("resource://gre/modules/XPCOMUtils.jsm"); 1.21 +Cu.import("resource://gre/modules/Services.jsm"); 1.22 + 1.23 +XPCOMUtils.defineLazyModuleGetter(this, "jwcrypto", 1.24 + "resource://gre/modules/identity/jwcrypto.jsm"); 1.25 + 1.26 +XPCOMUtils.defineLazyModuleGetter(this, "IDService", 1.27 + "resource://gre/modules/identity/Identity.jsm", 1.28 + "IdentityService"); 1.29 + 1.30 +XPCOMUtils.defineLazyModuleGetter(this, 1.31 + "IdentityStore", 1.32 + "resource://gre/modules/identity/IdentityStore.jsm"); 1.33 + 1.34 +XPCOMUtils.defineLazyModuleGetter(this, 1.35 + "Logger", 1.36 + "resource://gre/modules/identity/LogUtils.jsm"); 1.37 + 1.38 +XPCOMUtils.defineLazyServiceGetter(this, 1.39 + "uuidGenerator", 1.40 + "@mozilla.org/uuid-generator;1", 1.41 + "nsIUUIDGenerator"); 1.42 + 1.43 +const TEST_MESSAGE_MANAGER = "Mr McFeeley"; 1.44 +const TEST_URL = "https://myfavoritebacon.com"; 1.45 +const TEST_URL2 = "https://myfavoritebaconinacan.com"; 1.46 +const TEST_USER = "user@mozilla.com"; 1.47 +const TEST_PRIVKEY = "fake-privkey"; 1.48 +const TEST_CERT = "fake-cert"; 1.49 +const TEST_ASSERTION = "fake-assertion"; 1.50 +const TEST_IDPPARAMS = { 1.51 + domain: "myfavoriteflan.com", 1.52 + authentication: "/foo/authenticate.html", 1.53 + provisioning: "/foo/provision.html" 1.54 +}; 1.55 + 1.56 +// The following are utility functions for Identity testing 1.57 + 1.58 +function log(...aMessageArgs) { 1.59 + Logger.log.apply(Logger, ["test"].concat(aMessageArgs)); 1.60 +} 1.61 + 1.62 +function get_idstore() { 1.63 + return IdentityStore; 1.64 +} 1.65 + 1.66 +function partial(fn) { 1.67 + let args = Array.prototype.slice.call(arguments, 1); 1.68 + return function() { 1.69 + return fn.apply(this, args.concat(Array.prototype.slice.call(arguments))); 1.70 + }; 1.71 +} 1.72 + 1.73 +function uuid() { 1.74 + return uuidGenerator.generateUUID().toString(); 1.75 +} 1.76 + 1.77 +function base64UrlDecode(s) { 1.78 + s = s.replace(/-/g, "+"); 1.79 + s = s.replace(/_/g, "/"); 1.80 + 1.81 + // Replace padding if it was stripped by the sender. 1.82 + // See http://tools.ietf.org/html/rfc4648#section-4 1.83 + switch (s.length % 4) { 1.84 + case 0: 1.85 + break; // No pad chars in this case 1.86 + case 2: 1.87 + s += "=="; 1.88 + break; // Two pad chars 1.89 + case 3: 1.90 + s += "="; 1.91 + break; // One pad char 1.92 + default: 1.93 + throw new InputException("Illegal base64url string!"); 1.94 + } 1.95 + 1.96 + // With correct padding restored, apply the standard base64 decoder 1.97 + return atob(s); 1.98 +} 1.99 + 1.100 +// create a mock "doc" object, which the Identity Service 1.101 +// uses as a pointer back into the doc object 1.102 +function mock_doc(aIdentity, aOrigin, aDoFunc) { 1.103 + let mockedDoc = {}; 1.104 + mockedDoc.id = uuid(); 1.105 + mockedDoc.loggedInUser = aIdentity; 1.106 + mockedDoc.origin = aOrigin; 1.107 + mockedDoc["do"] = aDoFunc; 1.108 + mockedDoc._mm = TEST_MESSAGE_MANAGER; 1.109 + mockedDoc.doReady = partial(aDoFunc, "ready"); 1.110 + mockedDoc.doLogin = partial(aDoFunc, "login"); 1.111 + mockedDoc.doLogout = partial(aDoFunc, "logout"); 1.112 + mockedDoc.doError = partial(aDoFunc, "error"); 1.113 + mockedDoc.doCancel = partial(aDoFunc, "cancel"); 1.114 + mockedDoc.doCoffee = partial(aDoFunc, "coffee"); 1.115 + mockedDoc.childProcessShutdown = partial(aDoFunc, "child-process-shutdown"); 1.116 + 1.117 + mockedDoc.RP = mockedDoc; 1.118 + 1.119 + return mockedDoc; 1.120 +} 1.121 + 1.122 +function mock_fxa_rp(aIdentity, aOrigin, aDoFunc) { 1.123 + let mockedDoc = {}; 1.124 + mockedDoc.id = uuid(); 1.125 + mockedDoc.emailHint = aIdentity; 1.126 + mockedDoc.origin = aOrigin; 1.127 + mockedDoc.wantIssuer = "firefox-accounts"; 1.128 + mockedDoc._mm = TEST_MESSAGE_MANAGER; 1.129 + 1.130 + mockedDoc.doReady = partial(aDoFunc, "ready"); 1.131 + mockedDoc.doLogin = partial(aDoFunc, "login"); 1.132 + mockedDoc.doLogout = partial(aDoFunc, "logout"); 1.133 + mockedDoc.doError = partial(aDoFunc, "error"); 1.134 + mockedDoc.doCancel = partial(aDoFunc, "cancel"); 1.135 + mockedDoc.childProcessShutdown = partial(aDoFunc, "child-process-shutdown"); 1.136 + 1.137 + mockedDoc.RP = mockedDoc; 1.138 + 1.139 + return mockedDoc; 1.140 +} 1.141 + 1.142 +// mimicking callback funtionality for ease of testing 1.143 +// this observer auto-removes itself after the observe function 1.144 +// is called, so this is meant to observe only ONE event. 1.145 +function makeObserver(aObserveTopic, aObserveFunc) { 1.146 + let observer = { 1.147 + // nsISupports provides type management in C++ 1.148 + // nsIObserver is to be an observer 1.149 + QueryInterface: XPCOMUtils.generateQI([Ci.nsISupports, Ci.nsIObserver]), 1.150 + 1.151 + observe: function (aSubject, aTopic, aData) { 1.152 + if (aTopic == aObserveTopic) { 1.153 + aObserveFunc(aSubject, aTopic, aData); 1.154 + Services.obs.removeObserver(observer, aObserveTopic); 1.155 + } 1.156 + } 1.157 + }; 1.158 + 1.159 + Services.obs.addObserver(observer, aObserveTopic, false); 1.160 +} 1.161 + 1.162 +// set up the ID service with an identity with keypair and all 1.163 +// when ready, invoke callback with the identity 1.164 +function setup_test_identity(identity, cert, cb) { 1.165 + // set up the store so that we're supposed to be logged in 1.166 + let store = get_idstore(); 1.167 + 1.168 + function keyGenerated(err, kpo) { 1.169 + store.addIdentity(identity, kpo, cert); 1.170 + cb(); 1.171 + }; 1.172 + 1.173 + jwcrypto.generateKeyPair("DS160", keyGenerated); 1.174 +} 1.175 + 1.176 +// takes a list of functions and returns a function that 1.177 +// when called the first time, calls the first func, 1.178 +// then the next time the second, etc. 1.179 +function call_sequentially() { 1.180 + let numCalls = 0; 1.181 + let funcs = arguments; 1.182 + 1.183 + return function() { 1.184 + if (!funcs[numCalls]) { 1.185 + let argString = Array.prototype.slice.call(arguments).join(","); 1.186 + do_throw("Too many calls: " + argString); 1.187 + return; 1.188 + } 1.189 + funcs[numCalls].apply(funcs[numCalls],arguments); 1.190 + numCalls += 1; 1.191 + }; 1.192 +} 1.193 + 1.194 +/* 1.195 + * Setup a provisioning workflow with appropriate callbacks 1.196 + * 1.197 + * identity is the email we're provisioning. 1.198 + * 1.199 + * afterSetupCallback is required. 1.200 + * 1.201 + * doneProvisioningCallback is optional, if the caller 1.202 + * wants to be notified when the whole provisioning workflow is done 1.203 + * 1.204 + * frameCallbacks is optional, contains the callbacks that the sandbox 1.205 + * frame would provide in response to DOM calls. 1.206 + */ 1.207 +function setup_provisioning(identity, afterSetupCallback, doneProvisioningCallback, callerCallbacks) { 1.208 + IDService.reset(); 1.209 + 1.210 + let provId = uuid(); 1.211 + IDService.IDP._provisionFlows[provId] = { 1.212 + identity : identity, 1.213 + idpParams: TEST_IDPPARAMS, 1.214 + callback: function(err) { 1.215 + if (doneProvisioningCallback) 1.216 + doneProvisioningCallback(err); 1.217 + }, 1.218 + sandbox: { 1.219 + // Emulate the free() method on the iframe sandbox 1.220 + free: function() {} 1.221 + } 1.222 + }; 1.223 + 1.224 + let caller = {}; 1.225 + caller.id = provId; 1.226 + caller.doBeginProvisioningCallback = function(id, duration_s) { 1.227 + if (callerCallbacks && callerCallbacks.beginProvisioningCallback) 1.228 + callerCallbacks.beginProvisioningCallback(id, duration_s); 1.229 + }; 1.230 + caller.doGenKeyPairCallback = function(pk) { 1.231 + if (callerCallbacks && callerCallbacks.genKeyPairCallback) 1.232 + callerCallbacks.genKeyPairCallback(pk); 1.233 + }; 1.234 + 1.235 + afterSetupCallback(caller); 1.236 +} 1.237 + 1.238 +// Switch debug messages on by default 1.239 +let initialPrefDebugValue = false; 1.240 +try { 1.241 + initialPrefDebugValue = Services.prefs.getBoolPref("toolkit.identity.debug"); 1.242 +} catch(noPref) {} 1.243 +Services.prefs.setBoolPref("toolkit.identity.debug", true); 1.244 + 1.245 +// Switch on firefox accounts 1.246 +let initialPrefFXAValue = false; 1.247 +try { 1.248 + initialPrefFXAValue = Services.prefs.getBoolPref("identity.fxaccounts.enabled"); 1.249 +} catch(noPref) {} 1.250 +Services.prefs.setBoolPref("identity.fxaccounts.enabled", true); 1.251 + 1.252 +// after execution, restore prefs 1.253 +do_register_cleanup(function() { 1.254 + log("restoring prefs to their initial values"); 1.255 + Services.prefs.setBoolPref("toolkit.identity.debug", initialPrefDebugValue); 1.256 + Services.prefs.setBoolPref("identity.fxaccounts.enabled", initialPrefFXAValue); 1.257 +}); 1.258 + 1.259 +