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 | const Ci = Components.interfaces; |
michael@0 | 5 | const Cu = Components.utils; |
michael@0 | 6 | |
michael@0 | 7 | // The following boilerplate makes sure that XPCom calls |
michael@0 | 8 | // that use the profile directory work. |
michael@0 | 9 | |
michael@0 | 10 | Cu.import("resource://gre/modules/XPCOMUtils.jsm"); |
michael@0 | 11 | Cu.import("resource://gre/modules/Services.jsm"); |
michael@0 | 12 | |
michael@0 | 13 | XPCOMUtils.defineLazyModuleGetter(this, "MinimalIDService", |
michael@0 | 14 | "resource://gre/modules/identity/MinimalIdentity.jsm", |
michael@0 | 15 | "IdentityService"); |
michael@0 | 16 | |
michael@0 | 17 | XPCOMUtils.defineLazyModuleGetter(this, |
michael@0 | 18 | "Logger", |
michael@0 | 19 | "resource://gre/modules/identity/LogUtils.jsm"); |
michael@0 | 20 | |
michael@0 | 21 | XPCOMUtils.defineLazyServiceGetter(this, |
michael@0 | 22 | "uuidGenerator", |
michael@0 | 23 | "@mozilla.org/uuid-generator;1", |
michael@0 | 24 | "nsIUUIDGenerator"); |
michael@0 | 25 | |
michael@0 | 26 | const TEST_URL = "https://myfavoriteflan.com"; |
michael@0 | 27 | const TEST_USER = "uumellmahaye1969@hotmail.com"; |
michael@0 | 28 | const TEST_PRIVKEY = "i-am-a-secret"; |
michael@0 | 29 | const TEST_CERT = "i~like~pie"; |
michael@0 | 30 | |
michael@0 | 31 | // The following are utility functions for Identity testing |
michael@0 | 32 | |
michael@0 | 33 | function log(...aMessageArgs) { |
michael@0 | 34 | Logger.log.apply(Logger, ["test"].concat(aMessageArgs)); |
michael@0 | 35 | } |
michael@0 | 36 | |
michael@0 | 37 | function partial(fn) { |
michael@0 | 38 | let args = Array.prototype.slice.call(arguments, 1); |
michael@0 | 39 | return function() { |
michael@0 | 40 | return fn.apply(this, args.concat(Array.prototype.slice.call(arguments))); |
michael@0 | 41 | }; |
michael@0 | 42 | } |
michael@0 | 43 | |
michael@0 | 44 | function uuid() { |
michael@0 | 45 | return uuidGenerator.generateUUID().toString(); |
michael@0 | 46 | } |
michael@0 | 47 | |
michael@0 | 48 | // create a mock "doc" object, which the Identity Service |
michael@0 | 49 | // uses as a pointer back into the doc object |
michael@0 | 50 | function mockDoc(aParams, aDoFunc) { |
michael@0 | 51 | let mockedDoc = {}; |
michael@0 | 52 | mockedDoc.id = uuid(); |
michael@0 | 53 | |
michael@0 | 54 | // Properties of aParams may include loggedInUser |
michael@0 | 55 | Object.keys(aParams).forEach(function(param) { |
michael@0 | 56 | mockedDoc[param] = aParams[param]; |
michael@0 | 57 | }); |
michael@0 | 58 | |
michael@0 | 59 | // the origin is set inside nsDOMIdentity by looking at the |
michael@0 | 60 | // document.nodePrincipal.origin. Here we, we must satisfy |
michael@0 | 61 | // ourselves with pretending. |
michael@0 | 62 | mockedDoc.origin = "https://jedp.gov"; |
michael@0 | 63 | |
michael@0 | 64 | mockedDoc['do'] = aDoFunc; |
michael@0 | 65 | mockedDoc.doReady = partial(aDoFunc, 'ready'); |
michael@0 | 66 | mockedDoc.doLogin = partial(aDoFunc, 'login'); |
michael@0 | 67 | mockedDoc.doLogout = partial(aDoFunc, 'logout'); |
michael@0 | 68 | mockedDoc.doError = partial(aDoFunc, 'error'); |
michael@0 | 69 | mockedDoc.doCancel = partial(aDoFunc, 'cancel'); |
michael@0 | 70 | mockedDoc.doCoffee = partial(aDoFunc, 'coffee'); |
michael@0 | 71 | |
michael@0 | 72 | return mockedDoc; |
michael@0 | 73 | } |
michael@0 | 74 | |
michael@0 | 75 | // create a mock "pipe" object that would normally communicate |
michael@0 | 76 | // messages up to gaia (either the trusty ui or the hidden iframe), |
michael@0 | 77 | // and convey messages back down from gaia to the controller through |
michael@0 | 78 | // the message callback. |
michael@0 | 79 | |
michael@0 | 80 | // The mock receiving pipe simulates gaia which, after receiving messages |
michael@0 | 81 | // through the pipe, will call back with instructions to invoke |
michael@0 | 82 | // certain methods. It mocks what comes back from the other end of |
michael@0 | 83 | // the pipe. |
michael@0 | 84 | function mockReceivingPipe() { |
michael@0 | 85 | let MockedPipe = { |
michael@0 | 86 | communicate: function(aRpOptions, aGaiaOptions, aMessageCallback) { |
michael@0 | 87 | switch (aGaiaOptions.message) { |
michael@0 | 88 | case "identity-delegate-watch": |
michael@0 | 89 | aMessageCallback({json: {method: "ready"}}); |
michael@0 | 90 | break; |
michael@0 | 91 | case "identity-delegate-request": |
michael@0 | 92 | aMessageCallback({json: {method: "login", assertion: TEST_CERT}}); |
michael@0 | 93 | break; |
michael@0 | 94 | case "identity-delegate-logout": |
michael@0 | 95 | aMessageCallback({json: {method: "logout"}}); |
michael@0 | 96 | break; |
michael@0 | 97 | default: |
michael@0 | 98 | throw("what the what?? " + aGaiaOptions.message); |
michael@0 | 99 | break; |
michael@0 | 100 | } |
michael@0 | 101 | } |
michael@0 | 102 | }; |
michael@0 | 103 | return MockedPipe; |
michael@0 | 104 | } |
michael@0 | 105 | |
michael@0 | 106 | // The mock sending pipe lets us test what's actually getting put in the |
michael@0 | 107 | // pipe. |
michael@0 | 108 | function mockSendingPipe(aMessageCallback) { |
michael@0 | 109 | let MockedPipe = { |
michael@0 | 110 | communicate: function(aRpOptions, aGaiaOptions, aDummyCallback) { |
michael@0 | 111 | aMessageCallback(aRpOptions, aGaiaOptions); |
michael@0 | 112 | } |
michael@0 | 113 | }; |
michael@0 | 114 | return MockedPipe; |
michael@0 | 115 | } |
michael@0 | 116 | |
michael@0 | 117 | // mimicking callback funtionality for ease of testing |
michael@0 | 118 | // this observer auto-removes itself after the observe function |
michael@0 | 119 | // is called, so this is meant to observe only ONE event. |
michael@0 | 120 | function makeObserver(aObserveTopic, aObserveFunc) { |
michael@0 | 121 | let observer = { |
michael@0 | 122 | // nsISupports provides type management in C++ |
michael@0 | 123 | // nsIObserver is to be an observer |
michael@0 | 124 | QueryInterface: XPCOMUtils.generateQI([Ci.nsISupports, Ci.nsIObserver]), |
michael@0 | 125 | |
michael@0 | 126 | observe: function (aSubject, aTopic, aData) { |
michael@0 | 127 | if (aTopic == aObserveTopic) { |
michael@0 | 128 | Services.obs.removeObserver(observer, aObserveTopic); |
michael@0 | 129 | aObserveFunc(aSubject, aTopic, aData); |
michael@0 | 130 | } |
michael@0 | 131 | } |
michael@0 | 132 | }; |
michael@0 | 133 | |
michael@0 | 134 | Services.obs.addObserver(observer, aObserveTopic, false); |
michael@0 | 135 | } |
michael@0 | 136 | |
michael@0 | 137 | // a hook to set up the ID service with an identity with keypair and all |
michael@0 | 138 | // when ready, invoke callback with the identity. It's there if we need it. |
michael@0 | 139 | function setup_test_identity(identity, cert, cb) { |
michael@0 | 140 | cb(); |
michael@0 | 141 | } |
michael@0 | 142 | |
michael@0 | 143 | // takes a list of functions and returns a function that |
michael@0 | 144 | // when called the first time, calls the first func, |
michael@0 | 145 | // then the next time the second, etc. |
michael@0 | 146 | function call_sequentially() { |
michael@0 | 147 | let numCalls = 0; |
michael@0 | 148 | let funcs = arguments; |
michael@0 | 149 | |
michael@0 | 150 | return function() { |
michael@0 | 151 | if (!funcs[numCalls]) { |
michael@0 | 152 | let argString = Array.prototype.slice.call(arguments).join(","); |
michael@0 | 153 | do_throw("Too many calls: " + argString); |
michael@0 | 154 | return; |
michael@0 | 155 | } |
michael@0 | 156 | funcs[numCalls].apply(funcs[numCalls],arguments); |
michael@0 | 157 | numCalls += 1; |
michael@0 | 158 | }; |
michael@0 | 159 | } |