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