Sat, 03 Jan 2015 20:18:00 +0100
Conditionally enable double key logic according to:
private browsing mode or privacy.thirdparty.isolate preference and
implement in GetCookieStringCommon and FindCookie where it counts...
With some reservations of how to convince FindCookie users to test
condition and pass a nullptr when disabling double key logic.
michael@0 | 1 | /* -*- Mode: js2; js2-basic-offset: 2; indent-tabs-mode: nil; -*- */ |
michael@0 | 2 | /* vim: set ft=javascript ts=2 et sw=2 tw=80: */ |
michael@0 | 3 | /* This Source Code Form is subject to the terms of the Mozilla Public |
michael@0 | 4 | * License, v. 2.0. If a copy of the MPL was not distributed with this file, |
michael@0 | 5 | * You can obtain one at http://mozilla.org/MPL/2.0/. */ |
michael@0 | 6 | |
michael@0 | 7 | "use strict"; |
michael@0 | 8 | |
michael@0 | 9 | const Cu = Components.utils; |
michael@0 | 10 | const Ci = Components.interfaces; |
michael@0 | 11 | const Cc = Components.classes; |
michael@0 | 12 | const Cr = Components.results; |
michael@0 | 13 | |
michael@0 | 14 | Cu.import("resource://gre/modules/XPCOMUtils.jsm"); |
michael@0 | 15 | Cu.import("resource://gre/modules/Services.jsm"); |
michael@0 | 16 | Cu.import("resource://gre/modules/identity/LogUtils.jsm"); |
michael@0 | 17 | Cu.import("resource://gre/modules/identity/Sandbox.jsm"); |
michael@0 | 18 | |
michael@0 | 19 | this.EXPORTED_SYMBOLS = ["IdentityProvider"]; |
michael@0 | 20 | const FALLBACK_PROVIDER = "browserid.org"; |
michael@0 | 21 | |
michael@0 | 22 | XPCOMUtils.defineLazyModuleGetter(this, |
michael@0 | 23 | "jwcrypto", |
michael@0 | 24 | "resource://gre/modules/identity/jwcrypto.jsm"); |
michael@0 | 25 | |
michael@0 | 26 | function log(...aMessageArgs) { |
michael@0 | 27 | Logger.log.apply(Logger, ["IDP"].concat(aMessageArgs)); |
michael@0 | 28 | } |
michael@0 | 29 | function reportError(...aMessageArgs) { |
michael@0 | 30 | Logger.reportError.apply(Logger, ["IDP"].concat(aMessageArgs)); |
michael@0 | 31 | } |
michael@0 | 32 | |
michael@0 | 33 | |
michael@0 | 34 | function IdentityProviderService() { |
michael@0 | 35 | XPCOMUtils.defineLazyModuleGetter(this, |
michael@0 | 36 | "_store", |
michael@0 | 37 | "resource://gre/modules/identity/IdentityStore.jsm", |
michael@0 | 38 | "IdentityStore"); |
michael@0 | 39 | |
michael@0 | 40 | this.reset(); |
michael@0 | 41 | } |
michael@0 | 42 | |
michael@0 | 43 | IdentityProviderService.prototype = { |
michael@0 | 44 | QueryInterface: XPCOMUtils.generateQI([Ci.nsISupports, Ci.nsIObserver]), |
michael@0 | 45 | _sandboxConfigured: false, |
michael@0 | 46 | |
michael@0 | 47 | observe: function observe(aSubject, aTopic, aData) { |
michael@0 | 48 | switch (aTopic) { |
michael@0 | 49 | case "quit-application-granted": |
michael@0 | 50 | Services.obs.removeObserver(this, "quit-application-granted"); |
michael@0 | 51 | this.shutdown(); |
michael@0 | 52 | break; |
michael@0 | 53 | } |
michael@0 | 54 | }, |
michael@0 | 55 | |
michael@0 | 56 | reset: function IDP_reset() { |
michael@0 | 57 | // Clear the provisioning flows. Provision flows contain an |
michael@0 | 58 | // identity, idpParams (how to reach the IdP to provision and |
michael@0 | 59 | // authenticate), a callback (a completion callback for when things |
michael@0 | 60 | // are done), and a provisioningFrame (which is the provisioning |
michael@0 | 61 | // sandbox). Additionally, two callbacks will be attached: |
michael@0 | 62 | // beginProvisioningCallback and genKeyPairCallback. |
michael@0 | 63 | this._provisionFlows = {}; |
michael@0 | 64 | |
michael@0 | 65 | // Clear the authentication flows. Authentication flows attach |
michael@0 | 66 | // to provision flows. In the process of provisioning an id, it |
michael@0 | 67 | // may be necessary to authenticate with an IdP. The authentication |
michael@0 | 68 | // flow maintains the state of that authentication process. |
michael@0 | 69 | this._authenticationFlows = {}; |
michael@0 | 70 | }, |
michael@0 | 71 | |
michael@0 | 72 | getProvisionFlow: function getProvisionFlow(aProvId, aErrBack) { |
michael@0 | 73 | let provFlow = this._provisionFlows[aProvId]; |
michael@0 | 74 | if (provFlow) { |
michael@0 | 75 | return provFlow; |
michael@0 | 76 | } |
michael@0 | 77 | |
michael@0 | 78 | let err = "No provisioning flow found with id " + aProvId; |
michael@0 | 79 | log("ERROR:", err); |
michael@0 | 80 | if (typeof aErrBack === 'function') { |
michael@0 | 81 | aErrBack(err); |
michael@0 | 82 | } |
michael@0 | 83 | }, |
michael@0 | 84 | |
michael@0 | 85 | shutdown: function RP_shutdown() { |
michael@0 | 86 | this.reset(); |
michael@0 | 87 | |
michael@0 | 88 | if (this._sandboxConfigured) { |
michael@0 | 89 | // Tear down message manager listening on the hidden window |
michael@0 | 90 | Cu.import("resource://gre/modules/DOMIdentity.jsm"); |
michael@0 | 91 | DOMIdentity._configureMessages(Services.appShell.hiddenDOMWindow, false); |
michael@0 | 92 | this._sandboxConfigured = false; |
michael@0 | 93 | } |
michael@0 | 94 | |
michael@0 | 95 | Services.obs.removeObserver(this, "quit-application-granted"); |
michael@0 | 96 | }, |
michael@0 | 97 | |
michael@0 | 98 | get securityLevel() { |
michael@0 | 99 | return 1; |
michael@0 | 100 | }, |
michael@0 | 101 | |
michael@0 | 102 | get certDuration() { |
michael@0 | 103 | switch(this.securityLevel) { |
michael@0 | 104 | default: |
michael@0 | 105 | return 3600; |
michael@0 | 106 | } |
michael@0 | 107 | }, |
michael@0 | 108 | |
michael@0 | 109 | /** |
michael@0 | 110 | * Provision an Identity |
michael@0 | 111 | * |
michael@0 | 112 | * @param aIdentity |
michael@0 | 113 | * (string) the email we're logging in with |
michael@0 | 114 | * |
michael@0 | 115 | * @param aIDPParams |
michael@0 | 116 | * (object) parameters of the IdP |
michael@0 | 117 | * |
michael@0 | 118 | * @param aCallback |
michael@0 | 119 | * (function) callback to invoke on completion |
michael@0 | 120 | * with first-positional parameter the error. |
michael@0 | 121 | */ |
michael@0 | 122 | _provisionIdentity: function _provisionIdentity(aIdentity, aIDPParams, aProvId, aCallback) { |
michael@0 | 123 | let provPath = aIDPParams.idpParams.provisioning; |
michael@0 | 124 | let url = Services.io.newURI("https://" + aIDPParams.domain, null, null).resolve(provPath); |
michael@0 | 125 | log("_provisionIdentity: identity:", aIdentity, "url:", url); |
michael@0 | 126 | |
michael@0 | 127 | // If aProvId is not null, then we already have a flow |
michael@0 | 128 | // with a sandbox. Otherwise, get a sandbox and create a |
michael@0 | 129 | // new provision flow. |
michael@0 | 130 | |
michael@0 | 131 | if (aProvId) { |
michael@0 | 132 | // Re-use an existing sandbox |
michael@0 | 133 | log("_provisionIdentity: re-using sandbox in provisioning flow with id:", aProvId); |
michael@0 | 134 | this._provisionFlows[aProvId].provisioningSandbox.reload(); |
michael@0 | 135 | |
michael@0 | 136 | } else { |
michael@0 | 137 | this._createProvisioningSandbox(url, function createdSandbox(aSandbox) { |
michael@0 | 138 | // create a provisioning flow, using the sandbox id, and |
michael@0 | 139 | // stash callback associated with this provisioning workflow. |
michael@0 | 140 | |
michael@0 | 141 | let provId = aSandbox.id; |
michael@0 | 142 | this._provisionFlows[provId] = { |
michael@0 | 143 | identity: aIdentity, |
michael@0 | 144 | idpParams: aIDPParams, |
michael@0 | 145 | securityLevel: this.securityLevel, |
michael@0 | 146 | provisioningSandbox: aSandbox, |
michael@0 | 147 | callback: function doCallback(aErr) { |
michael@0 | 148 | aCallback(aErr, provId); |
michael@0 | 149 | }, |
michael@0 | 150 | }; |
michael@0 | 151 | |
michael@0 | 152 | log("_provisionIdentity: Created sandbox and provisioning flow with id:", provId); |
michael@0 | 153 | // XXX bug 769862 - provisioning flow should timeout after N seconds |
michael@0 | 154 | |
michael@0 | 155 | }.bind(this)); |
michael@0 | 156 | } |
michael@0 | 157 | }, |
michael@0 | 158 | |
michael@0 | 159 | // DOM Methods |
michael@0 | 160 | /** |
michael@0 | 161 | * the provisioning iframe sandbox has called navigator.id.beginProvisioning() |
michael@0 | 162 | * |
michael@0 | 163 | * @param aCaller |
michael@0 | 164 | * (object) the iframe sandbox caller with all callbacks and |
michael@0 | 165 | * other information. Callbacks include: |
michael@0 | 166 | * - doBeginProvisioningCallback(id, duration_s) |
michael@0 | 167 | * - doGenKeyPairCallback(pk) |
michael@0 | 168 | */ |
michael@0 | 169 | beginProvisioning: function beginProvisioning(aCaller) { |
michael@0 | 170 | log("beginProvisioning:", aCaller.id); |
michael@0 | 171 | |
michael@0 | 172 | // Expect a flow for this caller already to be underway. |
michael@0 | 173 | let provFlow = this.getProvisionFlow(aCaller.id, aCaller.doError); |
michael@0 | 174 | |
michael@0 | 175 | // keep the caller object around |
michael@0 | 176 | provFlow.caller = aCaller; |
michael@0 | 177 | |
michael@0 | 178 | let identity = provFlow.identity; |
michael@0 | 179 | let frame = provFlow.provisioningFrame; |
michael@0 | 180 | |
michael@0 | 181 | // Determine recommended length of cert. |
michael@0 | 182 | let duration = this.certDuration; |
michael@0 | 183 | |
michael@0 | 184 | // Make a record that we have begun provisioning. This is required |
michael@0 | 185 | // for genKeyPair. |
michael@0 | 186 | provFlow.didBeginProvisioning = true; |
michael@0 | 187 | |
michael@0 | 188 | // Let the sandbox know to invoke the callback to beginProvisioning with |
michael@0 | 189 | // the identity and cert length. |
michael@0 | 190 | return aCaller.doBeginProvisioningCallback(identity, duration); |
michael@0 | 191 | }, |
michael@0 | 192 | |
michael@0 | 193 | /** |
michael@0 | 194 | * the provisioning iframe sandbox has called |
michael@0 | 195 | * navigator.id.raiseProvisioningFailure() |
michael@0 | 196 | * |
michael@0 | 197 | * @param aProvId |
michael@0 | 198 | * (int) the identifier of the provisioning flow tied to that sandbox |
michael@0 | 199 | * @param aReason |
michael@0 | 200 | */ |
michael@0 | 201 | raiseProvisioningFailure: function raiseProvisioningFailure(aProvId, aReason) { |
michael@0 | 202 | reportError("Provisioning failure", aReason); |
michael@0 | 203 | |
michael@0 | 204 | // look up the provisioning caller and its callback |
michael@0 | 205 | let provFlow = this.getProvisionFlow(aProvId); |
michael@0 | 206 | |
michael@0 | 207 | // Sandbox is deleted in _cleanUpProvisionFlow in case we re-use it. |
michael@0 | 208 | |
michael@0 | 209 | // This may be either a "soft" or "hard" fail. If it's a |
michael@0 | 210 | // soft fail, we'll flow through setAuthenticationFlow, where |
michael@0 | 211 | // the provision flow data will be copied into a new auth |
michael@0 | 212 | // flow. If it's a hard fail, then the callback will be |
michael@0 | 213 | // responsible for cleaning up the now defunct provision flow. |
michael@0 | 214 | |
michael@0 | 215 | // invoke the callback with an error. |
michael@0 | 216 | provFlow.callback(aReason); |
michael@0 | 217 | }, |
michael@0 | 218 | |
michael@0 | 219 | /** |
michael@0 | 220 | * When navigator.id.genKeyPair is called from provisioning iframe sandbox. |
michael@0 | 221 | * Generates a keypair for the current user being provisioned. |
michael@0 | 222 | * |
michael@0 | 223 | * @param aProvId |
michael@0 | 224 | * (int) the identifier of the provisioning caller tied to that sandbox |
michael@0 | 225 | * |
michael@0 | 226 | * It is an error to call genKeypair without receiving the callback for |
michael@0 | 227 | * the beginProvisioning() call first. |
michael@0 | 228 | */ |
michael@0 | 229 | genKeyPair: function genKeyPair(aProvId) { |
michael@0 | 230 | // Look up the provisioning caller and make sure it's valid. |
michael@0 | 231 | let provFlow = this.getProvisionFlow(aProvId); |
michael@0 | 232 | |
michael@0 | 233 | if (!provFlow.didBeginProvisioning) { |
michael@0 | 234 | let errStr = "ERROR: genKeyPair called before beginProvisioning"; |
michael@0 | 235 | log(errStr); |
michael@0 | 236 | provFlow.callback(errStr); |
michael@0 | 237 | return; |
michael@0 | 238 | } |
michael@0 | 239 | |
michael@0 | 240 | // Ok generate a keypair |
michael@0 | 241 | jwcrypto.generateKeyPair(jwcrypto.ALGORITHMS.DS160, function gkpCb(err, kp) { |
michael@0 | 242 | log("in gkp callback"); |
michael@0 | 243 | if (err) { |
michael@0 | 244 | log("ERROR: genKeyPair:", err); |
michael@0 | 245 | provFlow.callback(err); |
michael@0 | 246 | return; |
michael@0 | 247 | } |
michael@0 | 248 | |
michael@0 | 249 | provFlow.kp = kp; |
michael@0 | 250 | |
michael@0 | 251 | // Serialize the publicKey of the keypair and send it back to the |
michael@0 | 252 | // sandbox. |
michael@0 | 253 | log("genKeyPair: generated keypair for provisioning flow with id:", aProvId); |
michael@0 | 254 | provFlow.caller.doGenKeyPairCallback(provFlow.kp.serializedPublicKey); |
michael@0 | 255 | }.bind(this)); |
michael@0 | 256 | }, |
michael@0 | 257 | |
michael@0 | 258 | /** |
michael@0 | 259 | * When navigator.id.registerCertificate is called from provisioning iframe |
michael@0 | 260 | * sandbox. |
michael@0 | 261 | * |
michael@0 | 262 | * Sets the certificate for the user for which a certificate was requested |
michael@0 | 263 | * via a preceding call to beginProvisioning (and genKeypair). |
michael@0 | 264 | * |
michael@0 | 265 | * @param aProvId |
michael@0 | 266 | * (integer) the identifier of the provisioning caller tied to that |
michael@0 | 267 | * sandbox |
michael@0 | 268 | * |
michael@0 | 269 | * @param aCert |
michael@0 | 270 | * (String) A JWT representing the signed certificate for the user |
michael@0 | 271 | * being provisioned, provided by the IdP. |
michael@0 | 272 | */ |
michael@0 | 273 | registerCertificate: function registerCertificate(aProvId, aCert) { |
michael@0 | 274 | log("registerCertificate:", aProvId, aCert); |
michael@0 | 275 | |
michael@0 | 276 | // look up provisioning caller, make sure it's valid. |
michael@0 | 277 | let provFlow = this.getProvisionFlow(aProvId); |
michael@0 | 278 | |
michael@0 | 279 | if (!provFlow.caller) { |
michael@0 | 280 | reportError("registerCertificate", "No provision flow or caller"); |
michael@0 | 281 | return; |
michael@0 | 282 | } |
michael@0 | 283 | if (!provFlow.kp) { |
michael@0 | 284 | let errStr = "Cannot register a certificate without a keypair"; |
michael@0 | 285 | reportError("registerCertificate", errStr); |
michael@0 | 286 | provFlow.callback(errStr); |
michael@0 | 287 | return; |
michael@0 | 288 | } |
michael@0 | 289 | |
michael@0 | 290 | // store the keypair and certificate just provided in IDStore. |
michael@0 | 291 | this._store.addIdentity(provFlow.identity, provFlow.kp, aCert); |
michael@0 | 292 | |
michael@0 | 293 | // Great success! |
michael@0 | 294 | provFlow.callback(null); |
michael@0 | 295 | |
michael@0 | 296 | // Clean up the flow. |
michael@0 | 297 | this._cleanUpProvisionFlow(aProvId); |
michael@0 | 298 | }, |
michael@0 | 299 | |
michael@0 | 300 | /** |
michael@0 | 301 | * Begin the authentication process with an IdP |
michael@0 | 302 | * |
michael@0 | 303 | * @param aProvId |
michael@0 | 304 | * (int) the identifier of the provisioning flow which failed |
michael@0 | 305 | * |
michael@0 | 306 | * @param aCallback |
michael@0 | 307 | * (function) to invoke upon completion, with |
michael@0 | 308 | * first-positional-param error. |
michael@0 | 309 | */ |
michael@0 | 310 | _doAuthentication: function _doAuthentication(aProvId, aIDPParams) { |
michael@0 | 311 | log("_doAuthentication: provId:", aProvId, "idpParams:", aIDPParams); |
michael@0 | 312 | // create an authentication caller and its identifier AuthId |
michael@0 | 313 | // stash aIdentity, idpparams, and callback in it. |
michael@0 | 314 | |
michael@0 | 315 | // extract authentication URL from idpParams |
michael@0 | 316 | let authPath = aIDPParams.idpParams.authentication; |
michael@0 | 317 | let authURI = Services.io.newURI("https://" + aIDPParams.domain, null, null).resolve(authPath); |
michael@0 | 318 | |
michael@0 | 319 | // beginAuthenticationFlow causes the "identity-auth" topic to be |
michael@0 | 320 | // observed. Since it's sending a notification to the DOM, there's |
michael@0 | 321 | // no callback. We wait for the DOM to trigger the next phase of |
michael@0 | 322 | // provisioning. |
michael@0 | 323 | this._beginAuthenticationFlow(aProvId, authURI); |
michael@0 | 324 | |
michael@0 | 325 | // either we bind the AuthID to the sandbox ourselves, or UX does that, |
michael@0 | 326 | // in which case we need to tell UX the AuthId. |
michael@0 | 327 | // Currently, the UX creates the UI and gets the AuthId from the window |
michael@0 | 328 | // and sets is with setAuthenticationFlow |
michael@0 | 329 | }, |
michael@0 | 330 | |
michael@0 | 331 | /** |
michael@0 | 332 | * The authentication frame has called navigator.id.beginAuthentication |
michael@0 | 333 | * |
michael@0 | 334 | * IMPORTANT: the aCaller is *always* non-null, even if this is called from |
michael@0 | 335 | * a regular content page. We have to make sure, on every DOM call, that |
michael@0 | 336 | * aCaller is an expected authentication-flow identifier. If not, we throw |
michael@0 | 337 | * an error or something. |
michael@0 | 338 | * |
michael@0 | 339 | * @param aCaller |
michael@0 | 340 | * (object) the authentication caller |
michael@0 | 341 | * |
michael@0 | 342 | */ |
michael@0 | 343 | beginAuthentication: function beginAuthentication(aCaller) { |
michael@0 | 344 | log("beginAuthentication: caller id:", aCaller.id); |
michael@0 | 345 | |
michael@0 | 346 | // Begin the authentication flow after having concluded a provisioning |
michael@0 | 347 | // flow. The aCaller that the DOM gives us will have the same ID as |
michael@0 | 348 | // the provisioning flow we just concluded. (see setAuthenticationFlow) |
michael@0 | 349 | let authFlow = this._authenticationFlows[aCaller.id]; |
michael@0 | 350 | if (!authFlow) { |
michael@0 | 351 | return aCaller.doError("beginAuthentication: no flow for caller id", aCaller.id); |
michael@0 | 352 | } |
michael@0 | 353 | |
michael@0 | 354 | authFlow.caller = aCaller; |
michael@0 | 355 | |
michael@0 | 356 | let identity = this._provisionFlows[authFlow.provId].identity; |
michael@0 | 357 | |
michael@0 | 358 | // tell the UI to start the authentication process |
michael@0 | 359 | log("beginAuthentication: authFlow:", aCaller.id, "identity:", identity); |
michael@0 | 360 | return authFlow.caller.doBeginAuthenticationCallback(identity); |
michael@0 | 361 | }, |
michael@0 | 362 | |
michael@0 | 363 | /** |
michael@0 | 364 | * The auth frame has called navigator.id.completeAuthentication |
michael@0 | 365 | * |
michael@0 | 366 | * @param aAuthId |
michael@0 | 367 | * (int) the identifier of the authentication caller tied to that sandbox |
michael@0 | 368 | * |
michael@0 | 369 | */ |
michael@0 | 370 | completeAuthentication: function completeAuthentication(aAuthId) { |
michael@0 | 371 | log("completeAuthentication:", aAuthId); |
michael@0 | 372 | |
michael@0 | 373 | // look up the AuthId caller, and get its callback. |
michael@0 | 374 | let authFlow = this._authenticationFlows[aAuthId]; |
michael@0 | 375 | if (!authFlow) { |
michael@0 | 376 | reportError("completeAuthentication", "No auth flow with id", aAuthId); |
michael@0 | 377 | return; |
michael@0 | 378 | } |
michael@0 | 379 | let provId = authFlow.provId; |
michael@0 | 380 | |
michael@0 | 381 | // delete caller |
michael@0 | 382 | delete authFlow['caller']; |
michael@0 | 383 | delete this._authenticationFlows[aAuthId]; |
michael@0 | 384 | |
michael@0 | 385 | let provFlow = this.getProvisionFlow(provId); |
michael@0 | 386 | provFlow.didAuthentication = true; |
michael@0 | 387 | let subject = { |
michael@0 | 388 | rpId: provFlow.rpId, |
michael@0 | 389 | identity: provFlow.identity, |
michael@0 | 390 | }; |
michael@0 | 391 | Services.obs.notifyObservers({ wrappedJSObject: subject }, "identity-auth-complete", aAuthId); |
michael@0 | 392 | }, |
michael@0 | 393 | |
michael@0 | 394 | /** |
michael@0 | 395 | * The auth frame has called navigator.id.cancelAuthentication |
michael@0 | 396 | * |
michael@0 | 397 | * @param aAuthId |
michael@0 | 398 | * (int) the identifier of the authentication caller |
michael@0 | 399 | * |
michael@0 | 400 | */ |
michael@0 | 401 | cancelAuthentication: function cancelAuthentication(aAuthId) { |
michael@0 | 402 | log("cancelAuthentication:", aAuthId); |
michael@0 | 403 | |
michael@0 | 404 | // look up the AuthId caller, and get its callback. |
michael@0 | 405 | let authFlow = this._authenticationFlows[aAuthId]; |
michael@0 | 406 | if (!authFlow) { |
michael@0 | 407 | reportError("cancelAuthentication", "No auth flow with id:", aAuthId); |
michael@0 | 408 | return; |
michael@0 | 409 | } |
michael@0 | 410 | let provId = authFlow.provId; |
michael@0 | 411 | |
michael@0 | 412 | // delete caller |
michael@0 | 413 | delete authFlow['caller']; |
michael@0 | 414 | delete this._authenticationFlows[aAuthId]; |
michael@0 | 415 | |
michael@0 | 416 | let provFlow = this.getProvisionFlow(provId); |
michael@0 | 417 | provFlow.didAuthentication = true; |
michael@0 | 418 | Services.obs.notifyObservers(null, "identity-auth-complete", aAuthId); |
michael@0 | 419 | |
michael@0 | 420 | // invoke callback with ERROR. |
michael@0 | 421 | let errStr = "Authentication canceled by IDP"; |
michael@0 | 422 | log("ERROR: cancelAuthentication:", errStr); |
michael@0 | 423 | provFlow.callback(errStr); |
michael@0 | 424 | }, |
michael@0 | 425 | |
michael@0 | 426 | /** |
michael@0 | 427 | * Called by the UI to set the ID and caller for the authentication flow after it gets its ID |
michael@0 | 428 | */ |
michael@0 | 429 | setAuthenticationFlow: function(aAuthId, aProvId) { |
michael@0 | 430 | // this is the transition point between the two flows, |
michael@0 | 431 | // provision and authenticate. We tell the auth flow which |
michael@0 | 432 | // provisioning flow it is started from. |
michael@0 | 433 | log("setAuthenticationFlow: authId:", aAuthId, "provId:", aProvId); |
michael@0 | 434 | this._authenticationFlows[aAuthId] = { provId: aProvId }; |
michael@0 | 435 | this._provisionFlows[aProvId].authId = aAuthId; |
michael@0 | 436 | }, |
michael@0 | 437 | |
michael@0 | 438 | /** |
michael@0 | 439 | * Load the provisioning URL in a hidden frame to start the provisioning |
michael@0 | 440 | * process. |
michael@0 | 441 | */ |
michael@0 | 442 | _createProvisioningSandbox: function _createProvisioningSandbox(aURL, aCallback) { |
michael@0 | 443 | log("_createProvisioningSandbox:", aURL); |
michael@0 | 444 | |
michael@0 | 445 | if (!this._sandboxConfigured) { |
michael@0 | 446 | // Configure message manager listening on the hidden window |
michael@0 | 447 | Cu.import("resource://gre/modules/DOMIdentity.jsm"); |
michael@0 | 448 | DOMIdentity._configureMessages(Services.appShell.hiddenDOMWindow, true); |
michael@0 | 449 | this._sandboxConfigured = true; |
michael@0 | 450 | } |
michael@0 | 451 | |
michael@0 | 452 | new Sandbox(aURL, aCallback); |
michael@0 | 453 | }, |
michael@0 | 454 | |
michael@0 | 455 | /** |
michael@0 | 456 | * Load the authentication UI to start the authentication process. |
michael@0 | 457 | */ |
michael@0 | 458 | _beginAuthenticationFlow: function _beginAuthenticationFlow(aProvId, aURL) { |
michael@0 | 459 | log("_beginAuthenticationFlow:", aProvId, aURL); |
michael@0 | 460 | let propBag = {provId: aProvId}; |
michael@0 | 461 | |
michael@0 | 462 | Services.obs.notifyObservers({wrappedJSObject:propBag}, "identity-auth", aURL); |
michael@0 | 463 | }, |
michael@0 | 464 | |
michael@0 | 465 | /** |
michael@0 | 466 | * Clean up a provision flow and the authentication flow and sandbox |
michael@0 | 467 | * that may be attached to it. |
michael@0 | 468 | */ |
michael@0 | 469 | _cleanUpProvisionFlow: function _cleanUpProvisionFlow(aProvId) { |
michael@0 | 470 | log('_cleanUpProvisionFlow:', aProvId); |
michael@0 | 471 | let prov = this._provisionFlows[aProvId]; |
michael@0 | 472 | |
michael@0 | 473 | // Clean up the sandbox, if there is one. |
michael@0 | 474 | if (prov.provisioningSandbox) { |
michael@0 | 475 | let sandbox = this._provisionFlows[aProvId]['provisioningSandbox']; |
michael@0 | 476 | if (sandbox.free) { |
michael@0 | 477 | log('_cleanUpProvisionFlow: freeing sandbox'); |
michael@0 | 478 | sandbox.free(); |
michael@0 | 479 | } |
michael@0 | 480 | delete this._provisionFlows[aProvId]['provisioningSandbox']; |
michael@0 | 481 | } |
michael@0 | 482 | |
michael@0 | 483 | // Clean up a related authentication flow, if there is one. |
michael@0 | 484 | if (this._authenticationFlows[prov.authId]) { |
michael@0 | 485 | delete this._authenticationFlows[prov.authId]; |
michael@0 | 486 | } |
michael@0 | 487 | |
michael@0 | 488 | // Finally delete the provision flow |
michael@0 | 489 | delete this._provisionFlows[aProvId]; |
michael@0 | 490 | } |
michael@0 | 491 | |
michael@0 | 492 | }; |
michael@0 | 493 | |
michael@0 | 494 | this.IdentityProvider = new IdentityProviderService(); |