michael@0: /* Any copyright is dedicated to the Public Domain. michael@0: * http://creativecommons.org/publicdomain/zero/1.0/ */ michael@0: michael@0: const Ci = Components.interfaces; michael@0: const Cu = Components.utils; michael@0: michael@0: // The following boilerplate makes sure that XPCom calls michael@0: // that use the profile directory work. michael@0: michael@0: Cu.import("resource://gre/modules/XPCOMUtils.jsm"); michael@0: Cu.import("resource://gre/modules/Services.jsm"); michael@0: michael@0: XPCOMUtils.defineLazyModuleGetter(this, "MinimalIDService", michael@0: "resource://gre/modules/identity/MinimalIdentity.jsm", michael@0: "IdentityService"); michael@0: michael@0: XPCOMUtils.defineLazyModuleGetter(this, michael@0: "Logger", michael@0: "resource://gre/modules/identity/LogUtils.jsm"); michael@0: michael@0: XPCOMUtils.defineLazyServiceGetter(this, michael@0: "uuidGenerator", michael@0: "@mozilla.org/uuid-generator;1", michael@0: "nsIUUIDGenerator"); michael@0: michael@0: const TEST_URL = "https://myfavoriteflan.com"; michael@0: const TEST_USER = "uumellmahaye1969@hotmail.com"; michael@0: const TEST_PRIVKEY = "i-am-a-secret"; michael@0: const TEST_CERT = "i~like~pie"; michael@0: michael@0: // The following are utility functions for Identity testing michael@0: michael@0: function log(...aMessageArgs) { michael@0: Logger.log.apply(Logger, ["test"].concat(aMessageArgs)); michael@0: } michael@0: michael@0: function partial(fn) { michael@0: let args = Array.prototype.slice.call(arguments, 1); michael@0: return function() { michael@0: return fn.apply(this, args.concat(Array.prototype.slice.call(arguments))); michael@0: }; michael@0: } michael@0: michael@0: function uuid() { michael@0: return uuidGenerator.generateUUID().toString(); michael@0: } michael@0: michael@0: // create a mock "doc" object, which the Identity Service michael@0: // uses as a pointer back into the doc object michael@0: function mockDoc(aParams, aDoFunc) { michael@0: let mockedDoc = {}; michael@0: mockedDoc.id = uuid(); michael@0: michael@0: // Properties of aParams may include loggedInUser michael@0: Object.keys(aParams).forEach(function(param) { michael@0: mockedDoc[param] = aParams[param]; michael@0: }); michael@0: michael@0: // the origin is set inside nsDOMIdentity by looking at the michael@0: // document.nodePrincipal.origin. Here we, we must satisfy michael@0: // ourselves with pretending. michael@0: mockedDoc.origin = "https://jedp.gov"; michael@0: michael@0: mockedDoc['do'] = aDoFunc; michael@0: mockedDoc.doReady = partial(aDoFunc, 'ready'); michael@0: mockedDoc.doLogin = partial(aDoFunc, 'login'); michael@0: mockedDoc.doLogout = partial(aDoFunc, 'logout'); michael@0: mockedDoc.doError = partial(aDoFunc, 'error'); michael@0: mockedDoc.doCancel = partial(aDoFunc, 'cancel'); michael@0: mockedDoc.doCoffee = partial(aDoFunc, 'coffee'); michael@0: michael@0: return mockedDoc; michael@0: } michael@0: michael@0: // create a mock "pipe" object that would normally communicate michael@0: // messages up to gaia (either the trusty ui or the hidden iframe), michael@0: // and convey messages back down from gaia to the controller through michael@0: // the message callback. michael@0: michael@0: // The mock receiving pipe simulates gaia which, after receiving messages michael@0: // through the pipe, will call back with instructions to invoke michael@0: // certain methods. It mocks what comes back from the other end of michael@0: // the pipe. michael@0: function mockReceivingPipe() { michael@0: let MockedPipe = { michael@0: communicate: function(aRpOptions, aGaiaOptions, aMessageCallback) { michael@0: switch (aGaiaOptions.message) { michael@0: case "identity-delegate-watch": michael@0: aMessageCallback({json: {method: "ready"}}); michael@0: break; michael@0: case "identity-delegate-request": michael@0: aMessageCallback({json: {method: "login", assertion: TEST_CERT}}); michael@0: break; michael@0: case "identity-delegate-logout": michael@0: aMessageCallback({json: {method: "logout"}}); michael@0: break; michael@0: default: michael@0: throw("what the what?? " + aGaiaOptions.message); michael@0: break; michael@0: } michael@0: } michael@0: }; michael@0: return MockedPipe; michael@0: } michael@0: michael@0: // The mock sending pipe lets us test what's actually getting put in the michael@0: // pipe. michael@0: function mockSendingPipe(aMessageCallback) { michael@0: let MockedPipe = { michael@0: communicate: function(aRpOptions, aGaiaOptions, aDummyCallback) { michael@0: aMessageCallback(aRpOptions, aGaiaOptions); michael@0: } michael@0: }; michael@0: return MockedPipe; michael@0: } michael@0: michael@0: // mimicking callback funtionality for ease of testing michael@0: // this observer auto-removes itself after the observe function michael@0: // is called, so this is meant to observe only ONE event. michael@0: function makeObserver(aObserveTopic, aObserveFunc) { michael@0: let observer = { michael@0: // nsISupports provides type management in C++ michael@0: // nsIObserver is to be an observer michael@0: QueryInterface: XPCOMUtils.generateQI([Ci.nsISupports, Ci.nsIObserver]), michael@0: michael@0: observe: function (aSubject, aTopic, aData) { michael@0: if (aTopic == aObserveTopic) { michael@0: Services.obs.removeObserver(observer, aObserveTopic); michael@0: aObserveFunc(aSubject, aTopic, aData); michael@0: } michael@0: } michael@0: }; michael@0: michael@0: Services.obs.addObserver(observer, aObserveTopic, false); michael@0: } michael@0: michael@0: // a hook to set up the ID service with an identity with keypair and all michael@0: // when ready, invoke callback with the identity. It's there if we need it. michael@0: function setup_test_identity(identity, cert, cb) { michael@0: cb(); michael@0: } michael@0: michael@0: // takes a list of functions and returns a function that michael@0: // when called the first time, calls the first func, michael@0: // then the next time the second, etc. michael@0: function call_sequentially() { michael@0: let numCalls = 0; michael@0: let funcs = arguments; michael@0: michael@0: return function() { michael@0: if (!funcs[numCalls]) { michael@0: let argString = Array.prototype.slice.call(arguments).join(","); michael@0: do_throw("Too many calls: " + argString); michael@0: return; michael@0: } michael@0: funcs[numCalls].apply(funcs[numCalls],arguments); michael@0: numCalls += 1; michael@0: }; michael@0: }